# Optimistic updates
Your users see their messages the instant they hit send. AI Transport inserts the message into the local tree before the server confirms, and reconciles automatically using the message ID.
User messages appear in the conversation immediately, before the server confirms. The client inserts the message into the tree optimistically. When the server publishes it to the channel, the transport reconciles using the message ID. The user sees no flash, no re-render, and no position change.
## How it works
When a user sends a message, the client inserts it into the conversation tree before the POST request reaches the server. The message appears in the UI immediately.
Behind the scenes:
1. The client generates a message ID and inserts the message into the conversation tree.
2. The POST request is sent to the server with the message content and the generated ID.
3. The server processes the message and publishes it to the Ably channel.
4. The client receives the published message through its channel subscription.
5. The transport matches the published message to the optimistic insert using the `x-ably-msg-id` header and reconciles them.
After reconciliation, the optimistic message is replaced by the server-confirmed version. From the user's perspective, the message was always there.
## Serial promotion
Optimistic messages do not have an Ably serial number; they exist only in the local tree. When the server publishes the message to the channel, the reconciled message receives a real Ably serial. This is serial promotion.
Serial promotion matters for ordering. Messages in the conversation tree are ordered by their Ably serial. Optimistic messages sit at the end of the tree until they are promoted. Once promoted, their position reflects the true order of publication assigned by the Ably channel.
## Send multiple messages in one turn
A single turn includes one or more user messages. When sending more than one, each is inserted optimistically in sequence:
### Javascript
```
await view.edit(messageId, [
{ role: 'user', content: 'Here is my updated question' },
{ role: 'user', content: 'And some additional context' },
]);
```
Each message in the array is inserted into the tree optimistically. When the server publishes them, they are reconciled individually using their respective message IDs. The order is preserved.
## Handle errors
If the POST request fails, the optimistic message stays in the conversation tree and the transport emits an `error` event. The message is not removed automatically; `view.send()` is fire-and-forget. The POST happens in the background:
### Javascript
```
const turn = await view.send([{ role: 'user', content: 'Hello' }]);
transport.on('error', (error) => {
console.error('Send failed:', error.message);
});
```
Your application decides whether to notify the user, offer a retry, or take other action.
## Reconciliation details
The transport uses the `x-ably-msg-id` header to match published messages to optimistic inserts. When the client generates a message, it assigns an ID. The server includes this ID when publishing to the channel. When the client receives the published message through its subscription, it matches the ID and promotes the optimistic message to a confirmed one.
A published message that does not match any optimistic insert (for example, a message from another client) is added to the tree normally. The reconciliation logic only applies to messages the current client sent.
## Edge cases and unhappy paths
- A failed POST leaves the optimistic message in the tree. Your application chooses whether to mark it failed, offer retry, or remove it. The transport does not delete optimistic messages automatically.
- A message ID collision (the same ID used twice on the same channel) confuses reconciliation. Use `crypto.randomUUID()` to generate IDs.
- A published message that arrives before the server returns from POST still reconciles correctly. Reconciliation uses the message ID, not request ordering.
- Two clients sending at the same time produce two distinct optimistic messages and two server publishes. Each client only reconciles its own; the other side appears as a normal observer message.
- A server that publishes the message without the `x-ably-msg-id` header is treated as a new message, not a reconciliation. Wire the ID through from your route handler.
## FAQ
### Why do I still need a server when messages are optimistic?
The optimistic insert is a local UI optimisation. The server publishes the canonical message to Ably and runs the LLM. Without the server, no other client sees the message and no LLM responds.
### Does optimistic insertion work for assistant messages?
No. Assistant messages stream from the server through the channel. Optimistic insertion is for user messages that the local client originates.
### What if the server publishes the message but the response never arrives?
The optimistic message reconciles when the publish arrives. If the publish never arrives (server failure, retention expiry, network), the optimistic message stays unreconciled. Handle this through the `error` event.
### Can I roll back an optimistic message?
Yes. Remove it from your application state when you decide the send has failed. The transport does not impose a rollback policy.
### Does this work with branching?
Yes. The optimistic message receives the correct `parent` and `forkOf` headers when reconciled. See [conversation branching](https://ably.com/docs/ai-transport/features/branching.md?source=llms.txt).
## Related features
- [Token streaming](https://ably.com/docs/ai-transport/features/token-streaming.md?source=llms.txt): how the agent's response streams after the user's message.
- [Conversation branching](https://ably.com/docs/ai-transport/features/branching.md?source=llms.txt): edits use optimistic updates for the revised message.
- [Multi-device sessions](https://ably.com/docs/ai-transport/features/multi-device.md?source=llms.txt): optimistic messages reconcile across devices.
## Related Topics
- [Token streaming](https://ably.com/docs/ai-transport/features/token-streaming.md?source=llms.txt): Stream AI-generated tokens to clients in realtime using AI Transport, with support for message-per-response and message-per-token patterns.
- [Cancellation](https://ably.com/docs/ai-transport/features/cancellation.md?source=llms.txt): Cancel AI responses mid-stream with Ably AI Transport. Scoped cancel signals, server-side authorization, and graceful abort handling.
- [Reconnection and recovery](https://ably.com/docs/ai-transport/features/reconnection-and-recovery.md?source=llms.txt): AI Transport streams survive connection drops automatically. Clients reconnect and resume from where they left off with no lost tokens.
- [Multi-device sessions](https://ably.com/docs/ai-transport/features/multi-device.md?source=llms.txt): Share AI conversations across tabs, phones, and laptops with Ably AI Transport. All devices see the same session in real time.
- [History and replay](https://ably.com/docs/ai-transport/features/history.md?source=llms.txt): Load conversation history from Ably channels with AI Transport. Paginated history, gapless continuity, and scroll-back patterns.
- [Conversation branching](https://ably.com/docs/ai-transport/features/branching.md?source=llms.txt): Edit user messages, regenerate AI responses, and navigate branches with Ably AI Transport. The full history is preserved as a tree.
- [Interruption](https://ably.com/docs/ai-transport/features/interruption.md?source=llms.txt): Let users interrupt AI agents mid-stream with Ably AI Transport. Cancel-then-send and send-alongside patterns for responsive AI interactions.
- [Concurrent turns](https://ably.com/docs/ai-transport/features/concurrent-turns.md?source=llms.txt): Run multiple AI turns simultaneously with Ably AI Transport. Independent streams, scoped cancellation, and multi-agent support.
- [Tool calling](https://ably.com/docs/ai-transport/features/tool-calling.md?source=llms.txt): Stream tool invocations and results through Ably AI Transport. Server-executed and client-executed tools with persistent state.
- [Human-in-the-loop](https://ably.com/docs/ai-transport/features/human-in-the-loop.md?source=llms.txt): Add human approval gates to AI agent workflows with Ably AI Transport. Approve tool executions and provide input across devices.
- [Agent presence](https://ably.com/docs/ai-transport/features/agent-presence.md?source=llms.txt): Show agent status in your AI application with Ably Presence. Display streaming, thinking, idle, and offline states in real time.
- [Push notifications](https://ably.com/docs/ai-transport/features/push-notifications.md?source=llms.txt): Notify users when AI agents complete background tasks with Ably Push Notifications. Reach users even when they're offline.
- [Chain of thought](https://ably.com/docs/ai-transport/features/chain-of-thought.md?source=llms.txt): Stream reasoning and thinking content alongside responses with Ably AI Transport. Display chain-of-thought in real time.
- [Double texting](https://ably.com/docs/ai-transport/features/double-texting.md?source=llms.txt): Handle users sending multiple messages while the AI is streaming with Ably AI Transport. Queue or run messages concurrently.
## Documentation Index
To discover additional Ably documentation:
1. Fetch [llms.txt](https://ably.com/llms.txt?source=llms.txt) for the canonical list of available pages.
2. Identify relevant URLs from that index.
3. Fetch target pages as needed.
Avoid using assumed or outdated documentation paths.