tool_choice lets you constrain how a call proceeds, and the exam expects precise recall of all four modes and when each is the right one: {"type": "auto"} for normal open-ended agent behaviour where Claude decides whether and which tool to call (the default when tool_choice is omitted), {"type": "any"} when some tool call is required but the model should pick which one, {"type": "tool", "name": "..."} to force one specific named tool, and {"type": "none"} to suppress tool calls entirely for that turn. Every mode accepts an additional disable_parallel_tool_use: true flag, which caps the response to at most one tool call regardless of how many the model might otherwise have wanted to make in parallel.
Choosing the right mode
Forcing a specific tool ({"type": "tool", "name": "ask_clarifying_question"}) is common right after an ambiguous user turn where you want the model to ask a clarifying question rather than guess and call a real tool — you're not letting the model decide whether to ask, you're guaranteeing it does. any shows up when the entire point of a turn is delegation to some tool and a plain-text answer would be a bug (a routing step in a pipeline that must hand off to exactly one of several specialist tools). none is useful for a final summarisation turn where tools were relevant earlier in the conversation but you want a clean natural-language answer with no risk of another tool call. auto is correct for the overwhelming majority of ordinary agent turns — reaching for any or a forced tool as a default, rather than for a specific narrow reason, tends to produce unnecessary or premature tool calls.
Errors as structured, actionable results
When a tool call fails, the failure should come back as a tool_result the model can reason about — a clear error category and enough detail to decide what to do next — not a generic "something went wrong" string, and not a raw exception or stack trace. Set is_error: true on the tool_result content block so the model knows this result represents a failure rather than a legitimate (if oddly-shaped) success. A structured error — distinguishing, for example, invalid_input from not_found from permission_denied from transient_failure — lets the model choose correctly between retrying, asking the user for missing or corrected information, escalating to a human, or giving up and explaining the failure honestly. Each category implies a different, specific next action; collapsing them into one undifferentiated failure signal takes that choice away from the model.
Matching error categories to recovery behaviour
The categories aren't decorative — each one should map to a distinct, appropriate follow-up. invalid_input (a malformed order ID, a date outside a valid range) should lead the model to ask the user for corrected input, not to retry the same call unchanged. not_found (a record that legitimately doesn't exist) should lead the model to tell the user the thing doesn't exist, not to imply a system fault or keep searching. permission_denied should lead the model to explain the limitation, not to retry with different parameters as if the problem were the input. transient_failure (a timeout, a rate limit, a temporary upstream outage) is the one category where retrying — once, with a brief explanation — is actually the right move, precisely because it's the one category where the same call might succeed a moment later. Building this mapping into the error shape itself, rather than leaving the model to infer intent from a free-text message, is what makes the categorisation useful rather than cosmetic.
Common exam distractor
Returning a bare exception message or stack trace as the tool_result content is a trap answer — it's not actionable for the model, and it can leak implementation detail (internal file paths, database schema, library versions) that shouldn't reach the model or, downstream, the user. A related distractor: fixing a bad error message by retrying the call automatically several times regardless of error category. A not_found or invalid_input result won't change on retry — automatic retry is only appropriate for genuinely transient categories, and applying it universally just wastes calls while delaying the honest answer the user actually needs.
Parallel tool calls and partial failure
When Claude requests multiple tools in parallel and one fails while others succeed, each tool_result is reported independently — the failing call gets is_error: true with its own structured error, the succeeding calls return their normal results, and all of them go back in the same single user message alongside each other. Don't drop the failed one, and don't split the results across multiple messages — Claude needs to see the full batch outcome (which calls worked, which didn't, and why) in one turn to reason about a sensible combined next step, such as proceeding with the two successful lookups while asking the user to correct the input for the one that failed.