Set output_schema on a team to constrain its final response to a Pydantic model. The team leader synthesizes member outputs into a validated object.
Basic Usage
from pydantic import BaseModel, Field
from agno.agent import Agent
from agno.models.openai import OpenAIResponses
from agno.team import Team
from agno.tools.hackernews import HackerNewsTools
from agno.tools.yfinance import YFinanceTools
class ResearchReport(BaseModel):
title: str
summary: str = Field(description="Executive summary of findings")
key_insights: list[str] = Field(description="Top 3-5 insights")
recommendation: str
news_agent = Agent(
name="News Researcher",
role="Research tech news and trends",
tools=[HackerNewsTools()]
)
finance_agent = Agent(
name="Finance Analyst",
role="Analyze financial data and stocks",
tools=[YFinanceTools()]
)
team = Team(
name="Research Team",
model=OpenAIResponses(id="gpt-5.2"),
members=[news_agent, finance_agent],
output_schema=ResearchReport,
)
response = team.run("Research NVIDIA - analyze stock performance and recent news")
# response.content is a validated ResearchReport object
report: ResearchReport = response.content
print(report.title)
print(report.summary)
print(report.recommendation)
How It Works
When a team has output_schema set:
- The team leader delegates tasks to members
- Members execute and return their results
- The leader synthesizes all member outputs
- The final response is structured according to your schema
Only the team’s final output is structured. Individual member responses remain unstructured unless those members have their own output_schema.
Per-Run Schema
Override or set the schema at run time:
team = Team(
model=OpenAIResponses(id="gpt-5.2"),
members=[news_agent, finance_agent],
)
# Different schemas for different requests
report = team.run("Analyze AI market", output_schema=MarketReport)
comparison = team.run("Compare NVDA vs AMD", output_schema=StockComparison)
Member and Team Schemas
You can set output_schema on both individual members and the team:
from pydantic import BaseModel, Field
from agno.agent import Agent
from agno.models.openai import OpenAIResponses
from agno.team import Team
from agno.tools.hackernews import HackerNewsTools
from agno.tools.yfinance import YFinanceTools
# Member schemas
class NewsInsights(BaseModel):
headlines: list[str]
sentiment: str = Field(description="positive, negative, or neutral")
class FinanceInsights(BaseModel):
price: float
change_percent: float
recommendation: str
# Team schema
class CombinedReport(BaseModel):
summary: str
market_sentiment: str
stock_outlook: str
final_recommendation: str
news_agent = Agent(
name="News Analyst",
role="Research news",
tools=[HackerNewsTools()],
output_schema=NewsInsights,
)
finance_agent = Agent(
name="Finance Analyst",
role="Analyze stocks",
tools=[YFinanceTools()],
output_schema=FinanceInsights,
)
team = Team(
model=OpenAIResponses(id="gpt-5.2"),
members=[news_agent, finance_agent],
output_schema=CombinedReport,
)
response = team.run("Full analysis of NVDA")
report: CombinedReport = response.content
Member schemas ensure consistent intermediate outputs. The team schema controls the final synthesized response.
Schema Design for Teams
Aggregate Multiple Perspectives
Design schemas that capture synthesized insights:
class CompetitiveAnalysis(BaseModel):
company: str
market_position: str = Field(description="Leader, challenger, or follower")
technical_strengths: list[str] = Field(description="From technical research")
financial_strengths: list[str] = Field(description="From financial analysis")
combined_outlook: str
Include Confidence and Reasoning
class InvestmentRecommendation(BaseModel):
ticker: str
action: str = Field(description="buy, hold, or sell")
price_target: float | None = None
reasoning: str = Field(description="Synthesized reasoning from all analysts")
risk_factors: list[str]
confidence: float = Field(ge=0, le=1)
Structured Comparisons
class CompanyComparison(BaseModel):
companies: list[str]
winner: str
comparison_criteria: list[str]
scores: dict[str, dict[str, int]] # company -> criterion -> score
summary: str
JSON Mode Fallback
For models without native structured output:
team = Team(
model=SomeModel(),
members=[...],
output_schema=MySchema,
use_json_mode=True,
)
JSON mode instructs the model to respond in JSON but doesn’t guarantee schema compliance. Prefer models with native structured output support.