Originally created by: yablokolabs
OpenAI-compatible streaming responses can omit tool_calls[].index while still supplying a stable tool_calls[].id. Atomic currently substitutes each SSE event's array position as the index. When a provider emits one distinct tool call per event, every call is therefore assigned index 0 and the stream consumer concatenates their names and arguments into one invalid call.
This was observed during a Gemini OpenAI-compatible run on Atomic Agent v0.1.72 and remains present by inspection on v0.1.73/current main (9d525ef4a004a9106608bea7a01ecd70ab279c2d).
parse-sse-chunk.ts (github.com) falls back to the tool call's position within the current event:
index: typeof toolCall.index === "number" ? toolCall.index : fallbackIndex
openai-stream-consumer.ts (github.com) then reconstructs calls in a Map<number, MutableToolCall> keyed only by that index.
For two events shaped like this:
data: {"choices":[{"delta":{"tool_calls":[{"id":"call_write","type":"function","function":{"name":"os__fs__write","arguments":"{...}"}}]}}]}
data: {"choices":[{"delta":{"tool_calls":[{"id":"call_read","type":"function","function":{"name":"os__fs__read","arguments":"{...}"}}]}}]}
both calls receive fallback index 0. Observed failures included merged names such as:
os.fs.writeos.fs.writeos.fs.writeos.fs.writeos.fs.write
When an SSE tool-call delta has no numeric index but has an id, Atomic should assign and retain a request-scoped stable index for that ID. Distinct IDs must remain distinct calls across separate events.
Keep an ID-to-index map in the stream consumer:
index is absent and the ID has been seen, reuse its assigned index.index is absent and the ID is new, allocate the next unused index.A localhost compatibility adapter using this mapping reconstructed five Gemini calls correctly in the evaluation.