AI Transport uses a channel-oriented model where sessions persist independently of individual connections. Both users and agents can disconnect and rejoin without ending the session. When users or agents rejoin, they need to resume the session from where they left off.
An agent or user might resume an existing session when:
- A user goes offline or navigates away before returning, expecting to see the latest conversation state
- An agent goes offline and comes back online when the user returns
- An agent resumes after a failover or service restart
Hydrating presence
When you attach to a channel, Ably automatically syncs the complete current presence set to your client. You can then query the presence set or subscribe to presence events without any additional hydration steps. This works the same way for both users and agents.
For details on obtaining the synced presence set, see Viewing who is online.
User resumes a session
Users resume by reattaching to the same session channel and hydrating the conversation transcript, in-progress model output, or other session state.
Hydrating conversation history
The hydration strategy you choose depends on your application model and your chosen approach to token streaming. Clients typically hydrate conversation state using one of these patterns:
- Hydrate entirely from the channel: Use rewind or history to obtain previous messages on the channel.
- Hydrate in-progress responses from the channel: Load completed messages from your database and catch up on any in-progress responses from the channel.
For detailed examples of hydrating the token stream, see the token streaming documentation:
Agent resumes a session
When an agent restarts, it needs to resume from where it left off. This involves two distinct concerns:
-
Recovering the agent's execution state: The current step in the workflow, local variables, function call results, pending operations, and any other state needed to continue execution. This state is internal to the agent and typically not visible to users.
-
Catching up on session activity: Any user messages, events, or other activity that occurred while the agent was offline.
These are separate problems requiring different solutions. Agent execution state is handled by your application and you choose how to persist and restore the internal state your agent needs to resume.
Ably provides access to channel message history, enabling agents to retrieve any messages sent while they were offline. When your agent comes back online, it reattaches to the same channel and catches up on messages it missed. This channel-oriented model provides several key benefits:
- Guaranteed message delivery: Clients can continue publishing messages even while the agent faults and relocates since the channel exists independently of the agent
- Reliable catch-up: The agent can retrieve any messages published during the interim when it comes back online
- Ordered delivery: Messages are delivered in the order they were published, ensuring agents process events in the correct sequence
- Channel-based addressing: The agent only needs the channel name to reconnect, no need to track individual client connections or manage connection state
Catching up on messages using history
When an agent resumes, it needs to retrieve messages published while it was offline. Use channel history with the untilAttach option to catch up on historical messages while preserving continuity with live message delivery.
Persisted session state
Your agent should persist the following state to enable resumption:
- Channel name: The channel the agent was processing
- Last processed timestamp: The timestamp of the last message successfully processed by the agent
This state allows the agent to reconnect to the correct channel and retrieve only the messages it missed.
Catching up with continuity
The recommended pattern uses untilAttach to paginate backwards through history while maintaining continuity with live message delivery. This ensures no messages are lost between history retrieval and subscription.
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
37
38
39
40
41
42
43
44
45
// Agent code
import * as Ably from 'ably';
const ably = new Ably.Realtime({
key: process.env.ABLY_API_KEY,
clientId: 'agent:assistant'
});
// Load persisted session state
const channelName = await loadChannelName();
const lastProcessedTimestamp = await loadLastProcessedTimestamp();
// Use a channel in a namespace with persistence enabled
// to access more than 2 minutes of message history
const channel = ably.channels.get(channelName);
// Subscribe to live messages (implicitly attaches the channel)
await channel.subscribe('prompt', (message) => {
// Process the live message
processMessage(message);
// Persist the timestamp after successful processing
saveLastProcessedTimestamp(message.timestamp);
});
// Fetch history up until the point of attachment, starting from last checkpoint
let page = await channel.history({
untilAttach: true,
start: lastProcessedTimestamp,
direction: 'forwards'
});
// Paginate through all missed messages
while (page) {
for (const message of page.items) {
// Process the historical message
await processMessage(message);
// Persist the timestamp after successful processing
await saveLastProcessedTimestamp(message.timestamp);
}
// Move to next page if available
page = page.hasNext() ? await page.next() : null;
}This pattern provides guaranteed continuity between historical and live message processing by ensuring that:
- The subscription starts receiving live messages immediately when you subscribe
- History retrieval stops exactly at the point the channel attached
- No messages are lost between the end of history and the start of live delivery