Parallel Tool Calls & is_error
The previous lesson handled one tool call. But modern models ask for several at once: parallel tool use is on by default, so a single assistant turn can contain three or four tool_use blocks ("get the weather AND look up the order AND check inventory"). If your code only runs the first one, the model waits for results that never come and the turn stalls.
"Parallel" here describes the model's REQUEST, not your execution: the model asked for several tools in one turn. You can simply run them one after another and send all the results back together, no threads or async required.
The contract is precise: run every tool_use block, then send back one user message whose content is a list of tool_result blocks, one per call, each echoing its own tool_use_id.
{"content": [
{"type": "tool_use", "id": "t1", "name": "get_weather", "input": {"city": "Paris"}},
{"type": "tool_use", "id": "t2", "name": "add", "input": {"a": 2, "b": 5}}],
"stop_reason": "tool_use"}The second new idea is failure isolation. If one tool raises, you do NOT crash the whole turn and lose the other results. You return that block's tool_result with "is_error": True and the error text as its content, so the model can see what went wrong and recover. A hallucinated tool name (not in your registry) is just another error: report it as is_error, never run something you did not register.
Build run_tool_calls(resp, tools) returning the single follow-up user message. On success a tool_result has exactly type, tool_use_id, and content (the result via str(...)); on failure it ALSO carries "is_error": True. Press Run to answer a two-call turn.
Write run_tool_calls(resp, tools) that runs EVERY tool_use block in resp["content"] (ignore other block types) and returns one user message {"role": "user", "content": [ ...tool_result blocks... ]}, one result per call in order. Each success result is {"type": "tool_result", "tool_use_id": <id>, "content": str(result)}. If a tool raises OR its name is not in tools, that result instead carries "is_error": True with the error text as content, and the other tools still run.
This lesson is locked
Lessons open one at a time. Finish the previous lesson to unlock this one.