User Message Queue
When the Agent is processing a response, users can continue typing and queue additional messages instead of waiting.Behavior
| Scenario | Behavior |
|---|---|
| Agent is processing + user sends | Message is added to the queue (not sent immediately) |
| Agent completes normally | Next queued message is auto-sent after 100 ms |
| Agent is stopped (truncated) | Queue does not auto-consume; user decides what to send next |
| User clicks Send Now (↑) on a queued item | Stops current generation (if active), then sends that message |
Queue UI
The queue panel appears above the chat input when messages are queued:- Edit (pencil icon) — inline-edit the queued message content
- Send Now (↑ arrow icon) — stop current generation and send this message immediately
- Remove (trash icon) — delete from queue
Truncated Context
When a response is stopped mid-stream, the partial AI content is preserved in the conversation history and used as context for subsequent messages. It is also persisted to the database so it survives page refresh.Conversation & File Rollback
Users can roll back to any previous conversation turn, similar to Cursor’s fork model.Conversation Rollback
- Hover over a user message → click the Rollback button (↺)
- Messages after the rollback point are dimmed (40 % opacity), not deleted
- A fork divider appears with a Cancel Rollback option
- New messages are appended below the divider
- Chat history sent to the backend only includes messages up to the fork point
File Rollback
When the user rolls back, sandbox files modified after the fork point are restored to their earlier state:preRollbackFiles.
File Recovery on Refresh
Sandbox files are restored from database events — not just the live E2B sandbox — so files persist even after the sandbox expires. Content is lazy-loaded: when the user clicks a file tab whose content is empty, the frontend callsGET /api/sandbox/read-file to fetch it from the sandbox on demand.
Event Persistence
RealtimeEventSaver
RealtimeEventSaver is responsible for batch-persisting real-time SSE events to the database:
Configuration
| Setting | Value | Description |
|---|---|---|
| Batch size | 3 events | Triggers a write when the buffer reaches this count |
| Batch interval | 100ms | Flushes on a timer even if the batch is not full |
| Retry count | 3 | Maximum number of retries |
| Retry strategy | Exponential backoff | 1s → 2s → 4s |
| Fallback | LocalStorage | Backup storage after all retries are exhausted |
Message Batching
Frontend Message Merging
The frontend merges rapid successive text updates to avoid excessive re-rendering:| Strategy | Description |
|---|---|
| UI batch flush | Batch updates at ~60fps, merging rapid successive tokens |
| Virtual scrolling | Only renders message cards within the visible viewport |
| Selective persistence | Only persists sessionId and messageIds; message content is loaded on demand |
Chat History Construction
The frontend loads the current session’s message history from the Zustand Store, excludes the message currently being sent, and passes it to the backend. The backend converts it to LangChain message types, limiting to a maximum of 30 messages.Concurrency & Isolation
| Isolation Dimension | Mechanism | Description |
|---|---|---|
| Session | thread_id | Each session has its own independent Checkpointer state |
| Context | session_id | Context Cache is isolated by session_id; resume only restores the corresponding session |
| Tool execution | LangGraph | Tools execute serially within the same session, never concurrently |
| Workspace | user_id | User file systems are fully isolated by user_id |
Session Recovery
The system supports recovery after session interruption:Save Triggers
- After a tool call completes
- After a message is sent
- During HITL interruption (via Checkpointer)
Recovery Flow
Related Docs
Messages
Complete message flow, request parameters, and state management
Retry Policy
Error handling, retry strategies, and fallback mechanisms