The response side: parallel calls and a string you must parse

Lesson 3 of 5 in Function Calling Deep Dive: The Wire Under Tool Use.

When the model decides to act, three things come back together: a stop reason telling you the turn ended in tool use, zero or more blocks of ordinary text, and one or more tool calls. Read the stop reason first — it is the branch in your loop, and treating “the response happened to contain a tool call” as your signal is how people end up dropping the model’s own explanation of what it was about to do.

Then read the calls. Plural, because a single assistant turn can request several tools at once — parallel tool calls — and that changes your executor from a function into a fan-out.

Parallel calls are a latency win and an operational hazard in the same feature.

The win: two independent lookups run concurrently and the model waits once instead of twice. The hazard: you must return a result for every id, and in most dialects you must return them all before the model continues. Return two results for three calls and the request fails or the model reasons over a hole. Fan out with Promise.all/asyncio.gather and you also need per-call timeouts, because the slowest call now sets the turn latency, and one hung tool stalls the whole loop.

There is a second hazard that only shows up in production. Parallel calls arrive with no ordering guarantee and no transaction. The model can perfectly reasonably emit transfer_funds and send_confirmation_email in the same turn; nothing in the protocol says the email waits for the transfer to succeed. Ordering and atomicity are your runtime’s problem — either serialise the tools that need it, or design them so out-of-order execution is safe.

Look again at that second call: "limit": 40, against a schema whose maximum is 20. Which brings us to the part of the wire that most first loops get wrong.

Interactive sorting exercise: Nine things that go wrong on the response side. Sort each one by where it must be handled — because getting this wrong is how a bad call becomes a dead run.

Tool: Trace Debugger — Read real tool-use turns — mis-keyed results, truncated arguments, a parallel fan-out with a missing result — and find the broken message in the Trace Debugger.

Key terms: parallel tool calls, tool result, tool-use id, tool call, least privilege

Interactive checkpoint quiz (2 questions) — open this page in a browser to take it.