Return Structured Output

Validate Claude and Codex responses with a Pydantic model or JSON Schema.

Set output_schema on either harness agent or override it for a run. The schema must describe an object at its root.

from agno.agents.claude import ClaudeAgent
from agno.run.base import RunStatus
from pydantic import BaseModel

class ShippingAnswer(BaseModel):
    fee: int
    explanation: str

agent = ClaudeAgent(
    model="claude-sonnet-5-5",
    tools=[],
    output_schema=ShippingAnswer,
)
result = agent.run(
    "Shipping is free for orders of 100 dollars or more. What is the fee for a 100 dollar order?"
)
if result.status != RunStatus.completed:
    raise RuntimeError(str(result.content))
assert isinstance(result.content, ShippingAnswer)
print(result.content.fee)

CodexAgent(model="gpt-5.6-luna", output_schema=ShippingAnswer) uses the same Agno contract. A per-run output_schema=... overrides the agent default. Both run and arun support it.

Use JSON Schema over HTTP

curl -X POST http://127.0.0.1:7777/agents/support-agent/runs \
  -F 'message=Return the shipping fee as 0.' \
  -F 'stream=false' \
  -F 'output_schema={"type":"object","properties":{"fee":{"type":"integer"}},"required":["fee"],"additionalProperties":false}'

On successful structured generation, content contains the decoded object. In streamed requests, inspect RunCompleted.content; partial text is not a validated object.

The adapter validates the final result against the Pydantic model or JSON Schema. Missing or invalid structured output produces an ERROR run with metadata.error_type=output_validation_error and metadata.retryable=false. Raw output, tool results and usage remain available for diagnosis; the adapter does not rerun the turn just to repair JSON. Streaming emits RunError instead of RunCompleted for that failure.

Malformed media/schema request fields and invalid schema definitions return 422 before SDK execution. HTTP schema constraints are preserved even when AgentOS converts the schema to a Pydantic model internally. Schemas must be object-rooted and self-contained: local references are resolved, while external references are rejected. Partial text is provisional and should not drive business operations.

Combine output with tools

Configure your business tools normally. The final structured response is separate from tool arguments and results. Claude's internal StructuredOutput delivery call is hidden from Agno's public tool history; actual business and native tool calls remain visible.

Arrays and scalar root schemas are rejected. Wrap a list in an object field when needed. See the structured-output tool cookbook for streamed and nonstreamed examples.