Push notifications
Your users get notified when a long-running agent finishes, even after they close the app. The conversation stays on the Ably channel, and Ably Push delivers the alert to the device that originally subscribed.
Push notifications let you notify users when an agent completes a long-running task, even if the user has closed the app. Push notifications use Ably's native Push API alongside AI Transport.
The pattern
The flow:
- A user sends a message that triggers a long-running agent task (research, code generation, data analysis).
- The user closes the app or navigates away.
- The agent completes the task, and its response is on the conversation's channel.
- A push rule on the channel triggers a notification to the user's device.
- The user taps the notification and returns to the completed conversation.
The conversation's channel and your own store hold the full response, so it is available when the user returns.
Set up push rules
Configure a channel rule in the Ably dashboard to trigger push notifications when the agent publishes a completion event:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// Agent code: publish a completion event when the agent finishes.
import * as Ably from 'ably';
import OpenAI from 'openai';
import { createTransport } from '@ably/ai-transport';
import { openai } from '@ably/ai-transport/openai';
const ably = new Ably.Realtime({ key: process.env.ABLY_API_KEY });
const client = new OpenAI();
export async function POST(req) {
const { channelName, userId, items, requestId } = await req.json();
const transport = createTransport({ client: ably, channelName, codec: openai });
try {
const stream = await client.responses.create(
{ model: 'gpt-5.5', input: [...(await loadConversation(channelName)), ...items], stream: true },
{ signal: req.signal },
);
await transport.pipe(stream, {
signal: req.signal,
headers: { requestId },
});
} finally {
await transport.close();
}
// The pipe resolved, so the response is complete. Publish a push-eligible event on a notification channel.
const notificationChannel = ably.channels.get(`notifications:${userId}`);
await notificationChannel.publish('agent-complete', {
title: 'Your agent has finished',
body: 'Tap to view the response',
channelName,
});
return new Response(null, { status: 204 });
}On the client, register the device for push notifications and subscribe to the notification channel:
1
2
3
// Client: subscribe for push notifications
const notificationChannel = ably.channels.get(`notifications:${userId}`)
await notificationChannel.push.subscribeDevice()Open the conversation from the notification
The notification payload can include the conversation's channel name, so the client opens directly to the right conversation. When the user taps the notification, load the conversation from your store and replay the channel from the stored serial to show the completed response.
Edge cases and unhappy paths
- A pipe that is cancelled or fails rejects, so the route above does not reach the push publish. Publish the notification only after the pipe resolves.
- A device that never registered for push (no
notificationChannel.push.subscribeDevice()call) does not receive the alert. Register on first launch and after a token refresh. - Notification payload limits apply per platform (around 4KB for APNs). Do not embed the full agent response; carry the channel name and load the conversation when the user returns.
- A user with several devices receives the notification on every registered device. Deduplicate at the device level if you only want one.
- The notification channel is a separate Ably channel from the conversation channel. Capabilities scope independently; the user's token needs
subscribeon both, pluspush-subscribeon the notification channel.
FAQ
Do I need a separate notification channel?
Yes. The push rule is per-channel; using a dedicated notifications:{userId} channel keeps the push policy off the conversation channel and lets you scope capabilities cleanly.
Does AI Transport publish the notification for me?
No. The SDK has no built-in push integration. The agent decides when the response is done enough to notify and calls channel.publish on the notification channel; Ably's push rule turns that message into a device notification.
Can I reuse the conversation channel for push?
You can, but every streamed message would then trigger the push rule. Publish one completion event on a separate channel and the user gets one notification.
What happens if the user opens a new device after the response completes?
The notification fires only on devices that had registered for push before the agent published. A new device sees the completed conversation when it loads the conversation and replays the channel.
How do I avoid duplicate notifications across devices?
Either subscribe only one device per user, or include a messageId in the payload and dedupe on the client. Ably itself does not dedupe across a device fleet.
Related features
- History and replay: loading completed responses after reconnecting.
- Reconnection and recovery: receiving what you missed after a disconnection.
- Ably Push: full reference for the Push Notifications API.