LLM Context Message Sequence Dispatch: Role Boundaries, Tool Turns, and Reassembly After Interruptions
Fitting context into the window does not make the message sequence valid. This article binds roles, tool calls/results, serialized requests, and streaming blocks into one dispatch manifest so partial tool arguments or stale streams cannot leak into the next turn.
Key Points
- Topic Focus: 大模型、AI Agent、DevOps
- Suitable for: indie hackers, full-stack engineers, AI application developers
- Core value: quickly understand background, practical paths, common pitfalls, and engineering advice
Even when context selection and token counting are both correct, the final request can still be invalid: two tool calls receive only one result; streaming JSON is executed after only half of it has arrived; after a disconnection, partial text is appended to the history. Agent Memory Consolidation Lineage handles facts across sessions; this article controls only the message sequence and response commit for a single dispatch.
Providers use different structures for messages, content blocks, tool calls, and continuation handles. The gateway needs a finite internal representation from which versioned adapters generate requests. Role rules must not be reused across APIs.
Build the message graph before rendering the provider array
MessageSequence.v1 is built only from committed turns. Each block stores a stable ID, role, kind, digest, trust label, and ordering; each tool edge stores its callId, schema digest, argument state, and result ID. Blocks of different kinds must not first be concatenated into a string and have their boundaries guessed afterward.
{
"conversationRevision": 81,
"sequenceDigest": "sha256:41d0...",
"blocks": [
{"id":"u-80","role":"user","kind":"text","digest":"sha256:a1..."},
{"id":"a-81-c1","role":"assistant","kind":"tool_call","callId":"call-7"},
{"id":"t-81-r1","role":"tool","kind":"tool_result","callId":"call-7"}
],
"adapterDigest": "sha256:91f2...",
"toolsetDigest": "sha256:7c13...",
"modelRevision": "provider/model@2026-07",
"maxOutputTokens": 1600
}
The validator checks that call IDs are unique within a turn. Before provider rendering, every emitted call must have exactly one terminal success/error/cancel result envelope. If a call is pending, the sequence remains in WAITING and no request is generated. The result's tool, argument digest, and generation must match the call. Planned calls must not masquerade as committed blocks, and unknown kinds, orphaned or duplicate results, and incomplete arguments are all rejected. Parallel results are positioned according to the target API's rules. MCP Tool Schemas govern argument contracts; this protocol governs only turn ownership.
Compression artifacts and retrieved snippets are merely scoped input blocks. The dispatcher must not let them cross system/user/tool boundaries or treat assistant: text as a real role. Context Token Admission counts the final sequence so that tool instructions added by the adapter do not push it beyond the context window.
The dispatch manifest fixes the exact bytes sent
After the adapter produces its output, the gateway creates a DispatchManifest.v1 that binds the sequence, adapter, provider, model, toolset, policy, request digest, and operation ID. Before external I/O, a conditional CAS on (conversationRevision, cancelGeneration, PREPARED) allocates an attemptGeneration, persists the request digest and idempotency key, and transitions the operation to DISPATCHING; this is the send acceptance point. From there, the only valid path is SENT -> STREAMING -> COMMITTED or UNKNOWN. The provider handle is immediately bound to the manifest digest.
A crash-recovered operation left in DISPATCHING must first transition to UNKNOWN. When handles or idempotency keys are supported, query, resume, or replay the same generation; otherwise, do not advance to a new generation until the old attempt is confirmed terminated. The canonical CAS must also match the active generation, and late blocks go only to a quarantine log. Only after the complete response becomes canonical may its tool calls enter the execution ledger defined by MCP Timeouts, Retries, and Idempotency.
Streaming blocks can be committed only when complete
The stream assembler deduplicates by response handle, generation, block index, and delta sequence. Text deltas may exist only as PREVIEW; tool arguments remain in a private buffer until the block stop has arrived and JSON parsing, schema validation, and call ID validation have all passed. An incomplete string or missing stop reason must never dispatch a tool or be written to the conversation.
LLM Streaming Protocols govern SSE events, while the Browser Long-Stream Parser governs client recovery. This protocol controls the server-side commit boundary: a successfully parsed network event is still only a candidate block, and the final output must satisfy the message graph invariants.
After a disconnection, if the stream can be resumed from its handle, deduplicate from the last acknowledged sequence. Otherwise, discard the partial candidates and create a new attempt from the original manifest. Partially displayed text must never become history for the next turn, because doing so would alter the role graph and repeat tool calls. The UI must distinguish revocable previews from committed messages.
Validate with reordering, replay, and truncated arguments
Tests construct orphaned results, two results targeting the same call, reordered parallel calls, tool arguments truncated at arbitrary bytes, duplicated block deltas, missing stop events, provider handles bound to the wrong manifest, old streams resuming after new ones, and adapter upgrades that change role ordering. Assert zero sends for invalid sequences, zero partial tool dispatches, and at most one canonical assistant turn per conversation revision.
Metrics include sequence-validator rejections, orphaned or duplicate tool results, age of UNKNOWN dispatches, handle recovery rate, late blocks, preview retractions, canonical CAS conflicts, and partial tool dispatches. Begin rollout by generating manifests only and comparing them with legacy requests through byte-level and semantic diffs. Then enable the protocol for requests without tools, and finally expand it to tool turns. Rolling back to the old adapter must still read the same internal message graph; if the old adapter does not recognize a new block kind, pause the conversation instead of degrading to string concatenation. Structured Output remains responsible for the final business schema; this protocol guarantees that the response sent for validation is complete, unique, and validly ordered.
Further reading
Related
Related Content
Article
From Copilot to Codex: AI Coding Tools Enter the Agent Era
Technical trends, engineering practices, and indie-developer perspectives around AI, AI Agents, and Vibe Coding.
Article
Why Does MCP Matter? Understanding the AI Tool Protocol
Technical trends, engineering practices, and an independent developer perspective on MCP and AI Agents.
Article
Core Architecture of AI Agents: Planning, Memory, Tools, and Execution
Technical trends, engineering practices, and independent developer perspectives around AI Agents and large language models.
Article
Complete Technology Stack Analysis for LLM Application Development
Covers tech trends, engineering practices, and indie developer perspectives around large models, RAG, and AI.