Tool definitions, tool_choice, and strict
Three fields, and the exam's favourite move in this whole domain is asking which object each one hangs off. Get the placement wrong and everything else you know is worth nothing.
It is the same class of knowledge as remembering that strict in a tsconfig goes under compilerOptions and not at the root. Nobody finds that interesting, everybody has been bitten by it, and being wrong about it invalidates a file that is otherwise perfect. Placement is not trivia. It is the difference between a request that works and a request that silently does not do what you meant.
The tool definition
Name, description, and an input_schema in JSON Schema. That is the contract.
The description is not documentation, it is the routing logic. The model chooses tools by reading descriptions, so a vague one is a bug, and "gets weather" versus "use when the user asks about conditions right now" is the difference between a tool that fires correctly and one that fires whenever anybody mentions the sky.
tool_choice, and what it forces
Four shapes:
auto: the model decides whether to use a tool at all. The default when tools are present.any: it must call some tool, its pick.toolwith aname: it must call that tool.none: no tool calls this turn, even though the definitions are right there in the request.
none is the one people forget and it is quietly the most useful in a workflow. It leaves the model aware that the capability exists while forbidding it on this turn, which is exactly what you want on a summarisation step at the end of a run.
any and tool are how you convert a chat model into a structured-output machine: force a call, and the arguments are your parsed object.
strict, and the placement trap
strict: true goes on the tool definition. Next to name, next to description, next to input_schema.
And the second half of the same fact: strict is not available on mcp_toolset. Tools arriving through the MCP connector do not get strict tool use. Not "set it somewhere else", not "on by default": the capability is not there. That is a real constraint on architecture, not exam trivia, because it means moving a tool from your own definitions into an MCP server can silently cost you a guarantee you were relying on.
Parallel tool use, and its off switch
The model can request several tools in one turn, and it is on by default. Your loop handles it the way Lesson 2 said: one user message, several tool_result blocks, ids matched.
To turn it off you set disable_parallel_tool_use, and it lives on tool_choice.
Which is the placement fact worth writing down: tool_choice controls two different things. Whether a tool must be called, and whether more than one may be called at once. It does not control strict. If you remember only "strict on the definition, disable_parallel_tool_use on tool_choice", you have the whole lesson.
Try it yourself
Where strict goes
You want guaranteed schema conformance on one of your tools. Where does strict: true actually go?
One field, wrong object
One field in this request is on the wrong object. The tool description is also weak, but that is not what this card is testing.
{
"tools": [
{
"name": "create_invoice",
"description": "Create an invoice",
"input_schema": {
"type": "object",
"properties": { "amount": { "type": "number" } }
}
}
],
"tool_choice": { "type": "any", "strict": true }
}
The tool_choice values
Four shapes, and one of them is the least obvious but most useful in a workflow.
Name the tool_choice options and say what each one forces.
strict on an MCP tool
You liked strict so much you want it on the tools coming in through an mcp_toolset.
Turning parallel tool use off
A small placement fact, and placement facts are what this whole lesson is about.
Parallel tool use is on by default. Which object carries the switch that turns it off?
Write one definition, and place both fields
Two minutes in a scratch file, no network. This is placement practice rather than schema practice, because placement is what the marks hang on.
Tick every step to confirm you did it.