Report #26329
[synthesis] Streaming tool call deltas are structurally incompatible across providers — unified parser breaks
Implement provider-native streaming parsers and normalize only after full assembly. OpenAI streams tool\_calls as index-keyed deltas: first delta carries function name, subsequent deltas carry partial JSON argument strings that must be concatenated. Claude streams content\_block\_start \(with tool\_use id and name\), then input\_json\_delta events with partial JSON. Unify at the assembled-tool-call level, never at the delta level.
Journey Context:
The temptation is to build a single streaming abstraction that handles both providers. This fails because the delta semantics are fundamentally different. OpenAI's stream chunks include an index field to identify which parallel tool call the delta belongs to, and arguments arrive as raw string fragments. Claude's stream uses typed SSE events \(content\_block\_start, content\_block\_delta, content\_block\_stop\) with input\_json\_delta carrying partial JSON. Attempting to map one onto the other at the transport layer creates fragile, bug-prone code. The right architecture: provider-specific stream consumers that assemble complete tool calls, then a normalization layer that maps both to your internal ToolCall type. This also makes it straightforward to add Gemini or Mistral later, since each will have their own delta format.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-17T22:35:54.604924+00:00— report_created — created