Structured AI Agents
Return type-safe, validated outputs from agents using Pydantic models
Structured outputs give agents predictable, validated data. When a Task sets output_pydantic or output_json, PraisonAI fails the task if the model can’t produce a value matching the schema — no silent None.
from praisonaiagents import Agent
from pydantic import BaseModel
class TopicList(BaseModel):
topics: list[str]
agent = Agent(name="TopicAgent", llm="gpt-4o-mini")
result = agent.chat("List 3 AI topics", output_pydantic=TopicList)
print(result.topics)The user asks for structured data; the agent returns validated Pydantic output for downstream code.
Quick Start
- Simple Usage
Define a Pydantic model and pass it to
output_pydantic:python from praisonaiagents import Agent from pydantic import BaseModel class AnalysisReport(BaseModel): title: str findings: str summary: str agent = Agent( name="Analyst", instructions="Return concise structured analysis.", ) result = agent.chat( "Summarise recent AI agent trends", output_pydantic=AnalysisReport, ) print(result.title, result.summary) - Multi-Agent Task
Use
Taskwithoutput_pydanticinside anAgentTeam:python from praisonaiagents import Agent, Task, AgentTeam from pydantic import BaseModel class ResearchReport(BaseModel): topic: str findings: str sources: list[str] researcher = Agent( name="Researcher", instructions="Research and return structured findings.", ) task = Task( description="Research quantum computing developments", expected_output="Structured research report", agent=researcher, output_pydantic=ResearchReport, ) team = AgentTeam(agents=[researcher], tasks=[task], process="sequential") result = team.start() print(result.pydantic.topic)
How It Works
| Phase | What happens |
|---|---|
| 1. Request | You pass a Pydantic model to output_pydantic |
| 2. Generate | The agent produces a response |
| 3. Validate | The response is parsed and checked against your schema |
| 4. Return | On success a typed object flows back; on failure the task retries then fails |
Failure Handling
Structured tasks fail-closed — success is False and error carries the schema name plus the parse error when the model can’t match your schema.
from praisonaiagents import Agent, Task, AgentTeam
from pydantic import BaseModel
class Fact(BaseModel):
title: str
detail: str
agent = Agent(name="F", llm="gpt-4o-mini")
task = Task(
description="Give one fact about the ocean",
agent=agent,
output_pydantic=Fact,
max_retries=2, # optional — see Task Retry Policy
)
team = AgentTeam(agents=[agent], tasks=[task])
team.start()
# Success — pydantic is guaranteed populated
if task.result.success:
print(task.result.pydantic.title)
else:
print("Failed:", task.result.error) # includes schema name + validation error
print("Raw text was:", task.result.raw) # kept for debugging| Case | success | pydantic / json_dict | error | raw |
|---|---|---|---|---|
| Model returns valid JSON matching schema | True | populated instance | None | JSON text |
| Model returns invalid / freeform prose | False | None | Schema name + parse error | Preserved for debugging |
Model returns valid falsey JSON ({}, [], false, 0) with output_json | True | the falsey value | None | JSON text |
| No structured output requested + non-empty prose | True | n/a | None | prose |
Pick the option that matches what your downstream code needs:
Native Structured Output
PraisonAI auto-detects models that support native response_format with JSON schema (GPT-4o, Claude 3.5, Gemini 2.0). Unsupported models fall back to prompt injection.
from praisonaiagents import Agent
from pydantic import BaseModel
class TopicList(BaseModel):
topics: list[str]
# Auto-detect (default)
agent = Agent(name="TopicAgent", llm="gpt-4o-mini")
result = agent.chat("List 3 AI topics", output_pydantic=TopicList)
# Force native mode
agent = Agent(name="TopicAgent", llm="custom-model", native_structured_output=True)
# Disable native — use text injection fallback
agent = Agent(name="TopicAgent", llm="gpt-4o-mini", native_structured_output=False)| Option | Type | Default | Description |
|---|---|---|---|
output_pydantic | BaseModel | None | Return a validated Pydantic object |
output_json | bool / BaseModel | None | Return structured JSON; task fails if not parseable |
native_structured_output | bool | auto | Force native response_format on/off |
YAML Configuration
framework: praisonai
process: sequential
agents:
analyst:
instructions: Expert in data analysis.
goal: Provide structured insights
role: Data Analyst
tasks:
analysis_task:
description: Analyse recent AI developments.
expected_output: Structured analysis report.
output_structure:
type: pydantic
model:
title: str
findings: str
summary: strRun with praisonai agents.yaml.
Best Practices
Keep models small and explicit
Define only the fields you need. Smaller schemas validate faster and reduce model confusion.
Prefer output_pydantic for Python apps
Use output_pydantic when you want a typed object; use output_json when you only need serialisable dicts.
Let native mode auto-detect
Leave native_structured_output unset unless you know your model needs forcing — the SDK picks the cleanest path.
Check task.result.success for structured tasks
pydantic is guaranteed populated on success. On failure, read task.result.error for the schema name plus validation error, and task.result.raw for the model text that failed.
Use max_retries for flaky models
Soft models may need a couple of retries to hit the schema. Combine output_pydantic with Task(max_retries=2) from Task Retry Policy.