An agent can read a free-text answer, but code needs to know which fields it contains and what values are valid. A schema defines that contract: field names, types, required or optional fields, and constraints. It lets an LLM produce structured output that an application can validate and use. section 2.2.5
Listing 2.7 Structured output with Pydantic
from pydantic import BaseModel
from litellm import completion
class ExtractedInfo(BaseModel):
name: str
email: str
phone: str | None = None
response = completion(
model="gpt-5-mini",
messages=[{
"role": "user",
"content": "My name is John Smith, my email is john@example.com, and my phone is 555-1234."
}],
response_format=ExtractedInfo
)
result = response.choices[0].message.content
The Pydantic class specifies required name and email strings plus an optional phone number. Passing the class as response_format requests JSON matching that structure. section 2.2.5
A tool schema has another job: it tells the model when to call a function and how to fill its arguments. Make the function name and description explicit, distinguish required parameters from optional ones, and constrain formats and ranges where possible. Validation can then reject malformed requests early rather than leaving the application to guess what the model meant. section 3.2.3
Listing 3.7 Improved: Explicit tool definition
{
"name": "reserve_table",
"description": "Create a restaurant table reservation.",
"parameters": {
"type": "object",
"properties": {
"restaurant_id": {
"type": "string",
"description": "Internal ID, e.g., rst_123"
},
"datetime": {
"type": "string",
"format": "date-time",
"description": "ISO-8601 in the user's local time"
},
"party_size": {
"type": "integer",
"minimum": 1,
"maximum": 20
},
"notes": {
"type": "string",
"description": "Allergies, occasion, etc. Optional."
}
},
"required": ["restaurant_id", "datetime", "party_size"],
}
}
The reservation schema names the action, describes each argument, requires the identifiers, date-time, and party size, and bounds the party size. section 3.2.3
Two design choices prevent avoidable tool-call failures:
- Represent a single state with one enum rather than conflicting on/off Boolean parameters. section 3.2.3
- Keep an identifier already held by code out of the model’s requested arguments; ask the model only for the decision it must make. section 3.2.3
The same contract can govern an agent’s final answer. A dedicated final-answer tool accepts the desired output schema as its input. The agent calls that tool instead of returning free text to be parsed afterward; the result is extracted as a Pydantic model. This reuses the tool-calling path rather than adding a separate formatting mechanism. section 4.7.1
Table 4.2 Changes required to add structured output support to the Agent class
| Method |
Role |
Modification |
|---|---|---|
|
|
Stores configuration |
Adds |
|
|
Prepares available tools |
Creates |
|
|
Packages context for LLM |
Forces tool usage when structured output needed |
|
|
Detects completion |
Checks for |
|
|
Extracts the answer |
Returns Pydantic model from |
The method table locates the schema in the agent’s execution flow: configure an output type, create the final-answer tool, require tool usage, detect completion, and extract the result. section 4.7.1
Schemas also make execution history reusable. A problem-solving memory records the task summary, approach, final answer, correctness, and optional error analysis. The task summary supplies text for vector search, while the other fields remain available after retrieval. A graph schema is a different design problem: deciding which entities and relationships to extract; its construction is not developed here. section 6.4.2 section 5.2.3











































