You've just learned how to prompt the model to return structured JSON by including a schema in your system prompt. Now you're ready to take the next step: using OpenAI's native tool-calling feature, which provides stronger guarantees and implements Factor 4 (Tools are just structured outputs) of the 12-Factor Agents methodology directly. By the end of this lesson, you'll be able to define tool schemas, require their use, and handle the structured output reliably.
A tool schema is a formal definition of a function that the model can "call" by returning structured data. You define the function's name, what it does, and what parameters it expects. The schema follows JSON Schema conventions, which means you specify types, descriptions, and which fields are required.
The schema is a dictionary that defines the interface between your code and the model. It contains several key fields that tell the model exactly how the tool should be used:
type: For tool definitions, this is always set to"function".name: The identifier your code will use to recognize this tool—in this case,"final_answer".description: A natural language explanation that helps the model understand when it is appropriate to use this tool.
With your tool schema defined, you can keep your system prompt simple since the tools parameter will handle the structured output definition. You no longer need to describe JSON schemas in the prompt itself.
Notice how much simpler this is than before, where you had to explicitly show the JSON schema in the prompt. The tool-calling feature handles that structure for you, so your system prompt can focus on the assistant's role and behavior rather than output format details.
Now you pass the tool schema to the model via the tools parameter. The critical addition is the tool_choice parameter, which controls whether the model must use a tool.
The tools parameter receives your list of tool schemas, making them available to the model. The tool_choice="required" parameter is critical: it tells the model that it must respond by calling one of the provided tools rather than sending back a regular text message. This enforcement is what provides a stronger guarantee compared to prompting alone. If you omitted tool_choice or set it to "auto", the model might decide to respond conversationally instead of calling a tool, which would break your structured output expectation. With this setup, you're ready to handle the structured response.
Before parsing specific data, it is incredibly useful to see the "raw" response object sent back by the API. The response object can be converted to a dictionary using .model_dump(). When we print it, we can see exactly how the platform packages any reasoning metadata/summary (if available) and the tool call together.
The output will look similar to this:
Looking at this raw output reveals that the output field is a list. It may contain a reasoning item with reasoning metadata/summary (depending on model and settings) and a function_call item. The function_call contains the name of the tool and the arguments as a JSON string. This structure is what we will navigate to extract the final answer.
When the model responds with a tool call, you look for items with type == "function_call" in the output list.
You iterate through the output list and verify that item.name matches the tool you're expecting. This routing logic is essential for systems that provide multiple different tools to the agent.
Once you've identified the function call, you extract the arguments. These are provided as a JSON string, which you must parse into a Python dictionary.
Running this logic against the model's response results in the following output:
Because the platform enforced your schema, you can confidently access args['answer'] knowing it will be there and will be a string.
You've now implemented the complete pattern for native tool-calling: defining a formal schema, requiring tool use, inspecting the raw response, and parsing validated arguments. This implements Factor 4 directly by treating tools as structured outputs enforced by the model provider. In the practice exercises, you'll define your own tool schemas and gain hands-on experience with this robust workflow.
