Double texting is when a user sends a new message while the agent is still streaming a response. AI Transport supports this through concurrent turns - the new message starts a new turn that runs alongside the existing one.
Default behavior
By default, sending a message while the agent is streaming starts a new concurrent turn. Both the existing response and the new turn run in parallel:
1
2
3
4
5
6
7
8
9
// User sends a message
await send([{ id: crypto.randomUUID(), role: 'user', parts: [{ type: 'text', text: 'Explain quantum computing' }] }])
// Agent starts streaming a response...
// User sends another message before the response finishes
await send([{ id: crypto.randomUUID(), role: 'user', parts: [{ type: 'text', text: 'Also, what is superposition?' }] }])
// Both turns stream concurrentlyEach turn has its own stream and cancel handle. The conversation tree contains both exchanges.
Queue-while-streaming
If you want to prevent concurrent turns and instead queue messages, detect active turns and show a queued indicator in the UI:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const activeTurns = useActiveTurns(transport)
const handleSend = async (text) => {
if (activeTurns.size > 0) {
// Show a queued indicator in the UI
addToQueue(text)
return
}
await send([{ id: crypto.randomUUID(), role: 'user', parts: [{ type: 'text', text }] }])
}
// When the active turn finishes, send the next queued message
useEffect(() => {
if (activeTurns.size === 0 && queue.length > 0) {
const next = queue.shift()
send([{ id: crypto.randomUUID(), role: 'user', parts: [{ type: 'text', text: next }] }])
}
}, [activeTurns.size])This gives users feedback that their message was received and will be processed next, without interrupting the current response.
Cancel-then-send
An alternative is to cancel the current turn before sending the new message. This is the interruption pattern:
1
2
3
4
5
6
7
const handleSend = async (text) => {
if (activeTurns.size > 0) {
await transport.cancel()
}
await send([{ id: crypto.randomUUID(), role: 'user', parts: [{ type: 'text', text }] }])
}The current response stops, and the new message starts a fresh turn. This works well when the user's new message supersedes the previous one.
Choose a pattern
| Pattern | Behavior | Best for |
|---|---|---|
| Concurrent (default) | Both turns run in parallel | Multi-topic conversations, research tasks |
| Queue-while-streaming | New message waits for current turn to finish | Sequential conversations, chatbots |
| Cancel-then-send | Current turn is aborted, new turn starts | Corrections, redirections |
The right pattern depends on your application. Concurrent turns work well for exploratory conversations. Queuing is better for sequential interactions where order matters. Cancel-then-send is best when the new message replaces the previous one.
Related features
- Concurrent turns - the underlying mechanism for parallel turns
- Interruption and barge-in - the cancel-then-send pattern in detail
- Cancellation - cancel signals and scoped cancellation
- Client transport API - reference for
send,cancel, and other client methods. - Sessions and turns - how concurrent turns are managed within a session.
- Get started - build your first AI Transport application.