Agent presence provides a realtime view to other session participants so they can know which agents are active in a session. Agent presence uses Ably's native Presence API to show real-time agent status in your application, and this could include a sole or orcestrator agent, or multiple sub-agents. Presence can convey whether the agent is streaming, thinking, idle, or offline - across all connected clients.
How it works
The agent enters presence on the AI Transport session channel with status data. As the agent moves through its turn lifecycle - receiving a message, thinking, streaming, finishing - it updates its presence data. All connected clients receive these updates in real time.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// Server: agent enters presence when it connects
const channel = ably.channels.get(sessionChannelName)
await channel.presence.enter({ status: 'idle' })
// Update status during each turn lifecycle
app.post('/api/chat', async (req, res) => {
const { turnId, clientId, messages } = req.body
const turn = transport.newTurn({ turnId, clientId })
await channel.presence.update({ status: 'thinking' })
const result = streamText({
model: openai('gpt-4o'),
messages,
abortSignal: turn.abortSignal,
})
await channel.presence.update({ status: 'streaming' })
await turn.streamResponse(result.toUIMessageStream())
await channel.presence.update({ status: 'idle' })
res.json({ ok: true })
})Subscribe to agent status
On the client, subscribe to presence events to track the agent's current state:
1
2
3
4
5
6
7
8
9
10
11
const channel = ably.channels.get(sessionChannelName)
channel.presence.subscribe((member) => {
if (member.clientId === 'agent') {
console.log(`Agent is ${member.data.status}`)
}
})
// Get the current presence set
const members = await channel.presence.get()
const agent = members.find(m => m.clientId === 'agent')Combine with active turns
For richer status indicators, combine presence data with useActiveTurns. Presence tells you the agent's self-reported state. Active turns tell you which turns are in progress:
1
2
3
4
5
6
7
8
9
10
11
const activeTurns = useActiveTurns(transport)
const agentStatus = useAgentPresence(channel) // your custom hook
// Agent is streaming if it has active turns
const isStreaming = activeTurns.has('agent')
// Agent is online but idle if present with no active turns
const isIdle = agentStatus === 'idle' && !isStreaming
// Agent is offline if not in the presence set
const isOffline = agentStatus === nullThis gives the UI enough information to show a typing indicator while the agent is thinking, a streaming animation while tokens are arriving, and an offline badge when the agent disconnects.
Related features
- Presence - the Ably Presence API used for agent status
- Concurrent turns - tracking active turns across clients
- Multi-device sessions - presence works across all connected devices
- Ably Presence - full reference for the Presence API.
- Sessions and turns - how sessions and presence work together.
- Get started - build your first AI Transport application.