Skip to main content
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:
  1. The team leader delegates tasks to members
  2. Members execute and return their results
  3. The leader synthesizes all member outputs
  4. 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.