I am not a native English speaker; this article was translated by AI.
When integrating diverse models for coding agents, transport quirks are bound to happen.
One recurring issue is when a model, instead of returning structured function calls via the standard tool_calls payload, dumps raw XML markup directly into the text stream (content or output_text.delta).
In certain reasoning models (such as DeepSeek derivatives or proxied gateways), it often looks like this:
<DSML<tool_calls>
<DSML<invoke name="read_file">
<DSML<parameter name="path">"src/main.rs"</DSML</parameter>
</DSML</invoke>
</DSML</tool_calls>If the transport layer simply passes these tokens through to the UI as plain text:
- The agent loop receives zero
tool_callevents, stalling the task. - The user’s screen gets littered with unparsed full-width XML tags.
To handle this cleanly in our runtime, we built a cross-chunk streaming DSML recovery state machine.
flowchart TD
subgraph Ingestion[Streaming Input Token Chunks]
A[Chunk 1: Protocol Prefix] --> B[Chunk 2: invoke name=read_file]
B --> C[Chunk 3: parameter name=path]
C --> D[Chunk 4: Protocol Closing Tag]
end
subgraph StateMachine[DSML Streaming State Machine]
S1[Detect Prefix: <DSML<] --> S2{Is Prompt Example?}
S2 -->|Yes| S3[Disable Recovery / Stream as Text]
S2 -->|No| S4[Capture Mode / Hold Text Output]
S4 --> S5[Buffer Chunks & Assemble Tags]
S5 --> S6{Is Markup Valid & Closed?}
S6 -->|No or Over Limit| S7[Fail-Closed / Emit Safe Error]
S6 -->|Yes| S8[Extract Tool Name & Parameter Pairs]
end
subgraph Dispatch[Protocol Conversion & Dispatch]
S8 --> E1[Validate against Tool Schema & Deserialize]
E1 --> E2[Synthesize ToolCall & ToolUse Events]
E2 --> E3[Agent Loop Executes Real Tool]
end
Ingestion --> StateMachine
1. Where the Complexity Lies #
If you receive a single, complete HTTP response body, extracting the tags via regex or an XML parser is straightforward. But agents require low-latency streaming text, which introduces several constraints:
- Chunk Fragmentation: Output arrives token-by-token. A tag like
<DSML<invokemight arrive fragmented as["<", "DS", "ML<in", "voke"]across four separate network packets. Single-chunk regex matching is ineffective. - Hold Buffers: When receiving a partial prefix (like a standalone
<), we cannot stream it immediately to the client (in case it turns out to be markup). But we also cannot hold it indefinitely; normal text must flush immediately once verified. - User Prompt Examples: If a user is explicitly discussing DSML syntax (e.g., “What does <DSML< mean?”), the state machine must recognize this and disable recovery, rather than attempting to execute quoted examples as real system commands.
- Native vs. DSML Conflicts: If a model returns both native structured tool calls and raw DSML text in the same turn, we fail closed to prevent duplicate executions.
2. State Machine Design & Intermediate Representation #
To support multiple providers (OpenAI-compatible endpoints, Responses APIs), the state machine operates on a decoupled Intermediate Representation:
pub enum DsmlOutcome {
/// Confirmed user-visible text, released for frontend streaming
Text(String),
/// Successfully captured and parsed complete tool invocations
ToolCalls(Vec<DsmlToolCall>),
}
pub struct DsmlToolCall {
pub id: String,
pub name: String,
pub arguments: String, // Normalized standard JSON string
}The provider passes incoming text chunks into the state machine:
- It maintains an internal
capture_buffer. - Once
<DSML<is detected, it switches to capture mode, pausing downstreamTextDeltaemissions. - A
DSML_CAPTURE_LIMIT(256KB) guards against memory exhaustion from malformed output.
3. Schema Validation & Event Synthesis #
When closed tags are parsed, <invoke> and <parameter> nodes are extracted:
- Verify the tool name exists in the current registry.
- Parse non-string parameters into valid JSON values.
- Validate against the tool’s registered JSON Schema.
- Synthesize native
ToolCallStart,ToolInputDelta, andToolUseevents.
From the agent loop’s perspective, this is indistinguishable from standard provider tool calls, routing directly into normal tool execution.
4. Takeaway #
When building agent runtimes against varied model endpoints, output formatting anomalies are inevitable. Absorbing these quirks in the transport adapter layer keeps higher-level agent state machines clean and dependable.