Function/tool calling (recap + depth)
The mechanism that lets a model act on your systems (introduced in Foundations): you expose tools as JSON-Schema definitions; the model emits a structured call; your code executes it and returns the result; the model continues. This is how LLMs query databases, hit APIs, and drive agents.
Doing it well:
- Descriptions are prompts — the model reads them to choose the tool; write them for the model.
- Schemas constrain inputs — types, enums, required fields; validate on your side too.
- Return compact, actionable results — not raw dumps; recoverable error messages.
- Handle the multi-turn loop — a request may trigger several tool calls before a final answer (the agent loop). Match each
tool_result/role:toolmessage to its call id. - Parallel tool calls — modern APIs can request several tools at once; execute independent ones concurrently.
Structured output (machine-consumable responses)
Distinct from tool calling: forcing the model's answer to match a schema. Use provider structured outputs (response_format: json_schema, strict: true) so the API guarantees schema-valid JSON — far more reliable than "please return JSON" + regex. Every field required or explicitly nullable; additionalProperties: false to block hallucinated fields. Then still validate in code and retry on failure.
When to use which
- The model needs to take an action / fetch data → tool/function calling.
- You need the model's answer in a fixed shape for your code → structured output.
- Often both: tools to gather info, structured output for the final result (the Foundations scorer example).
Robustness
Model-driven calls are still model output — authorize the user, not the model, for any tool side effect (AI Security course), validate all inputs and outputs, and cap the tool loop (Agents course). Function calling is powerful precisely because it lets the model act — so guard what it can do.