Chat Message Lifecycle
This page summarizes the current chat message lifecycle after the durable queued-turn refactor. Canonical product requirements still live in docs/features/chat/.
What This Covers
Section titled “What This Covers”- Which layer owns executed transcript history versus queued turn state.
- How direct sends, queued sends, and active-turn interrupts behave.
- What phase 1 intentionally does not do yet.
Current Model
Section titled “Current Model”- Mastra memory remains the canonical store for executed branch transcript history.
- The API app owns branch lineage, active-branch selection, queued-turn persistence, share sanitization, feedback, HITL policy, and interrupt behavior.
- Each new send creates a
ChatTurnRequest. - If the thread is idle, that turn request is claimed and streamed immediately through the existing AI SDK SSE path.
- If the thread already has an active turn, the new send becomes a persisted queued turn request instead of being rejected.
- Thread detail exposes queue state through
turnQueue.activeTurnand orderedturnQueue.items. - Queued items render outside
chatClient.messagesin a sticky Queue Dock above the composer. - Stopping an active turn is a server interrupt, not only a browser abort.
Stop & sendon the queued head interrupts the active server turn, stops the local stream, waits for the active lock to clear, and then claims that queued head.- The
Stop & sendclaim passes a non-visible model instruction that the prior assistant turn was interrupted and the queued message is now the user’s priority. That lets the model treat the queued message as clarification, correction, or added context for the interrupted request when appropriate, answer the revised original request from scratch when the interrupted draft is incomplete, and keep ordinary clarification wording separate from attempts to reveal or change hidden instructions. - The Send now handoff is covered by the deterministic
chat-queue-interrupt-ciMastra eval profile, including add-context, clarification, operational-priority clarification, and subject-change queued messages. - If visible assistant text already streamed, that partial reply remains in the transcript and its activity ends as interrupted.
- Plain
Stopdoes not cancel or delete queued turns; after the active interrupt settles, the queue head becomes eligible again if no HITL blocker remains.
Current Limits
Section titled “Current Limits”- Phase 1 queue draining is viewer-claimed. Queued turns do not auto-run in the background when no chat viewer is attached.
- The queue is capped at five queued turns per thread, excluding the currently running turn.
- Only the queue head can
Send noworStop & send. - Queued-turn editing happens in place inside the Queue Dock; the main composer is disabled during that edit state.
- Failed queue heads do not auto-skip. The user must edit or delete them before later queued work can continue.
- Pending HITL blocks queued-turn execution until the request resolves terminally.
- Queue state is owner-only thread state and is not exposed in shared-chat snapshots.
Manual QA Smoke
Section titled “Manual QA Smoke”For branch-editing checks, use one new private chat thread:
- Send an initial user message, edit it into a new version, and confirm the original branch is not mutated.
- Switch between the original and edited versions and confirm each version shows only its own descendant assistant reply.
- Continue from the edited branch, then delete the latest user turn. The delete should remove only that branch tail and leave the sibling branch intact.
- Reload while a non-root branch is selected and confirm the active branch and version controls persist.
Canonical Sources
Section titled “Canonical Sources”docs/features/chat/spec.mddocs/features/chat/stories/chat-queued-turns-and-interrupts.stories.mddocs/features/chat/tests/chat-queue.featuredocs/features/chat/decisions/ADR-009-chat-turn-request-and-queue-execution.mdapps/api/src/chats/apps/web/app/pages/chat/[id].vue
Official Docs
Section titled “Official Docs”- Mastra memory reference:
Memory.cloneThread()andMemory.deleteMessages() - Mastra agent streaming and abort-signal guidance
- AI SDK chat streaming and stop/abort handling