> ## Documentation Index
> Fetch the complete documentation index at: https://spacesail.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Input and Output

> Learn how to use structured input and output with Teams for reliable, production-ready systems.

Agno Teams support various forms of input and output, from simple string-based interactions to structured data validation using Pydantic models.

The most standard pattern is to use `str` input and `str` output:

```python theme={null}
from agno.models.openai import OpenAIChat
from agno.team import Team

team = Team(
    members=[],
    model=OpenAIChat(id="gpt-5-mini"),
    description="You write movie scripts.",
)

response = team.run("Write movie script about a girl living in New York")
print(response.content)
```

## Structured Output

One of our favorite features is using Teams to generate structured data (i.e. a pydantic model). This is generally called "Structured Output". Use this feature to extract features, classify data, produce fake data etc. The best part is that they work with function calls, knowledge bases and all other features.

Structured output makes teams reliable for production systems that need consistent, predictable response formats instead of unstructured text.

Let's create a Stock Research Team to generate a structured `StockReport` for us.

<Steps>
  <Step title="Structured Output example">
    ```python structured_output_team.py theme={null}
    from pydantic import BaseModel
    from agno.agent import Agent
    from agno.models.openai import OpenAIChat
    from agno.team import Team
    from agno.tools.duckduckgo import DuckDuckGoTools
    from agno.utils.pprint import pprint_run_response


    class StockAnalysis(BaseModel):
        symbol: str
        company_name: str
        analysis: str

    class CompanyAnalysis(BaseModel):
        company_name: str
        analysis: str

    stock_searcher = Agent(
        name="Stock Searcher",
        model=OpenAIChat("gpt-5-mini"),
        output_schema=StockAnalysis,
        role="Searches for information on stocks and provides price analysis.",
        tools=[
            DuckDuckGoTools()
        ],
    )

    company_info_agent = Agent(
        name="Company Info Searcher",
        model=OpenAIChat("gpt-5-mini"),
        role="Searches for information about companies and recent news.",
        output_schema=CompanyAnalysis,
        tools=[
            DuckDuckGoTools()
        ],
    )

    class StockReport(BaseModel):
        symbol: str
        company_name: str
        analysis: str

    team = Team(
        name="Stock Research Team",
        model=OpenAIChat("gpt-5-mini"),
        members=[stock_searcher, company_info_agent],
        output_schema=StockReport,
        markdown=True,
    )

    # This should delegate to the stock_searcher
    response = team.run("What is the current stock price of NVDA?")
    assert isinstance(response.content, StockReport)
    pprint_run_response(response)
    ```
  </Step>

  <Step title="Run the example">
    Install libraries

    ```shell theme={null}
    pip install openai agno ddgs
    ```

    Export your key

    ```shell theme={null}
    export OPENAI_API_KEY=xxx
    ```

    Run the example

    ```shell theme={null}
    python structured_output_team.py
    ```
  </Step>
</Steps>

The output is an object of the `StockReport` class, here's how it looks:

```python theme={null}
StockReport(
│   "symbol": "NVDA",                                                                                                                                     │
│   "company_name": "NVIDIA Corp",                                                                                                                        │
│   "analysis": "NVIDIA Corp (NVDA) remains a leading player in the AI chip market, ..."
)
```

<Tip>
  Some LLMs are not able to generate structured output. Agno has an option to tell the model to respond as JSON. Although this is typically not as accurate as structured output, it can be useful in some cases.

  If you want to use JSON mode, you can set `use_json_mode=True` on the Agent.

  ```python theme={null}
  team = Team(
    model=OpenAIChat(id="gpt-5-mini"),
    members=[stock_searcher, company_info_agent],
    description="You write stock reports.",
    output_schema=StockReport,
    use_json_mode=True,
  )
  ```
</Tip>

### Streaming Structured Output

Streaming can be used in combination with `output_schema`. This returns the structured output as a single `RunContent` event in the stream of events.

<Steps>
  <Step title="Streaming Structured Output example">
    ```python streaming_structured_output_team.py theme={null}
    import asyncio
    from typing import Dict, List

    from agno.agent import Agent
    from agno.models.openai.chat import OpenAIChat
    from pydantic import BaseModel, Field


    class MovieScript(BaseModel):
        setting: str = Field(
            ..., description="Provide a nice setting for a blockbuster movie."
        )
        ending: str = Field(
            ...,
            description="Ending of the movie. If not available, provide a happy ending.",
        )
        genre: str = Field(
            ...,
            description="Genre of the movie. If not available, select action, thriller or romantic comedy.",
        )
        name: str = Field(..., description="Give a name to this movie")
        characters: List[str] = Field(..., description="Name of characters for this movie.")
        storyline: str = Field(
            ..., description="3 sentence storyline for the movie. Make it exciting!"
        )
        rating: Dict[str, int] = Field(
            ...,
            description="Your own rating of the movie. 1-10. Return a dictionary with the keys 'story' and 'acting'.",
        )


    # Team that uses structured outputs with streaming
    structured_output_team = Team(
        members=[],
        model=OpenAIChat(id="gpt-5-mini"),
        description="You write movie scripts.",
        output_schema=MovieScript,
    )

    structured_output_team.print_response(
        "New York", stream=True, stream_events=True
    )
    ```
  </Step>

  <Step title="Run the example">
    Install libraries

    ```shell theme={null}
    pip install openai agno ddgs
    ```

    Export your key

    ```shell theme={null}
    export OPENAI_API_KEY=xxx
    ```

    Run the example

    ```shell theme={null}
    python streaming_structured_output_team.py
    ```
  </Step>
</Steps>

## Structured Input

A team can be provided with structured input (i.e a pydantic model) by passing it in the `Team.run()` or `Team.print_response()` as the `input` parameter.

<Steps>
  <Step title="Structured Input example">
    ```python structured_input_team.py theme={null}
    from typing import List

    from agno.agent import Agent
    from agno.models.openai import OpenAIChat
    from agno.team.team import Team
    from agno.tools.duckduckgo import DuckDuckGoTools
    from agno.tools.hackernews import HackerNewsTools
    from pydantic import BaseModel, Field


    class ResearchProject(BaseModel):
        """Structured research project with validation requirements."""

        project_name: str = Field(description="Name of the research project")
        research_topics: List[str] = Field(
            description="List of topics to research", min_items=1
        )
        target_audience: str = Field(description="Intended audience for the research")
        depth_level: str = Field(
            description="Research depth level", pattern="^(basic|intermediate|advanced)$"
        )
        max_sources: int = Field(
            description="Maximum number of sources to use", ge=3, le=20, default=10
        )
        include_recent_only: bool = Field(
            description="Whether to focus only on recent sources", default=True
        )


    # Create research agents
    hackernews_agent = Agent(
        name="HackerNews Researcher",
        model=OpenAIChat(id="gpt-5-mini"),
        tools=[HackerNewsTools()],
        role="Research trending topics and discussions on HackerNews",
        instructions=[
            "Search for relevant discussions and articles",
            "Focus on high-quality posts with good engagement",
            "Extract key insights and technical details",
        ],
    )

    web_researcher = Agent(
        name="Web Researcher",
        model=OpenAIChat(id="gpt-5-mini"),
        tools=[DuckDuckGoTools()],
        role="Conduct comprehensive web research",
        instructions=[
            "Search for authoritative sources and documentation",
            "Find recent articles and blog posts",
            "Gather diverse perspectives on the topics",
        ],
    )

    # Create team with input_schema for automatic validation
    research_team = Team(
        name="Research Team with Input Validation",
        model=OpenAIChat(id="gpt-5-mini"),
        members=[hackernews_agent, web_researcher],
        instructions=[
            "Conduct thorough research based on the validated input",
            "Coordinate between team members to avoid duplicate work",
            "Ensure research depth matches the specified level",
            "Respect the maximum sources limit",
            "Focus on recent sources if requested",
        ],
    )

    research_request = ResearchProject(
        project_name="Blockchain Development Tools",
        research_topics=["Ethereum", "Solana", "Web3 Libraries"],
        target_audience="Blockchain Developers",
        depth_level="advanced",
        max_sources=12,
        include_recent_only=False,
    )

    research_team.print_response(input=research_request)
    ```
  </Step>

  <Step title="Run the example">
    Install libraries

    ```shell theme={null}
    pip install openai agno ddgs
    ```

    Export your key

    ```shell theme={null}
    export OPENAI_API_KEY=xxx
    ```

    Run the example

    ```shell theme={null}
    python structured_input_team.py
    ```
  </Step>
</Steps>

<Note>
  Structured input is only available for the team leader. Structured input on member agents (when used in a Team) is not yet supported.
</Note>

### Validating the input

You can set `input_schema` on the Team to validate the input.  If you then pass the input as a dictionary, it will be automatically validated against the schema.

<Steps>
  <Step title="Validating the input example">
    ```python validating_input_team.py theme={null}
    from typing import List

    from agno.agent import Agent
    from agno.models.openai import OpenAIChat
    from agno.team.team import Team
    from agno.tools.duckduckgo import DuckDuckGoTools
    from agno.tools.hackernews import HackerNewsTools
    from pydantic import BaseModel, Field


    class ResearchProject(BaseModel):
        """Structured research project with validation requirements."""

        project_name: str = Field(description="Name of the research project")
        research_topics: List[str] = Field(
            description="List of topics to research", min_items=1
        )
        target_audience: str = Field(description="Intended audience for the research")
        depth_level: str = Field(
            description="Research depth level", pattern="^(basic|intermediate|advanced)$"
        )
        max_sources: int = Field(
            description="Maximum number of sources to use", ge=3, le=20, default=10
        )
        include_recent_only: bool = Field(
            description="Whether to focus only on recent sources", default=True
        )


    # Create research agents
    hackernews_agent = Agent(
        name="HackerNews Researcher",
        model=OpenAIChat(id="gpt-5-mini"),
        tools=[HackerNewsTools()],
        role="Research trending topics and discussions on HackerNews",
        instructions=[
            "Search for relevant discussions and articles",
            "Focus on high-quality posts with good engagement",
            "Extract key insights and technical details",
        ],
    )

    web_researcher = Agent(
        name="Web Researcher",
        model=OpenAIChat(id="gpt-5-mini"),
        tools=[DuckDuckGoTools()],
        role="Conduct comprehensive web research",
        instructions=[
            "Search for authoritative sources and documentation",
            "Find recent articles and blog posts",
            "Gather diverse perspectives on the topics",
        ],
    )

    # Create team with input_schema for automatic validation
    research_team = Team(
        name="Research Team with Input Validation",
        model=OpenAIChat(id="gpt-5-mini"),
        members=[hackernews_agent, web_researcher],
        input_schema=ResearchProject,
        instructions=[
            "Conduct thorough research based on the validated input",
            "Coordinate between team members to avoid duplicate work",
            "Ensure research depth matches the specified level",
            "Respect the maximum sources limit",
            "Focus on recent sources if requested",
        ],
    )

    research_team.print_response(
        input={
            "project_name": "AI Framework Comparison 2024",
            "research_topics": ["LangChain", "CrewAI", "AutoGen", "Agno"],
            "target_audience": "AI Engineers and Developers",
            "depth_level": "intermediate",
            "max_sources": 15,
            "include_recent_only": True,
        }
    )
    ```
  </Step>

  <Step title="Run the example">
    Install libraries

    ```shell theme={null}
    pip install openai agno ddgs
    ```

    Export your key

    ```shell theme={null}
    export OPENAI_API_KEY=xxx
    ```

    Run the example

    ```shell theme={null}
    python validating_input_team.py
    ```
  </Step>
</Steps>

## Typesafe Teams

For complete type safety with both input and output validation, Teams work similarly to Agents. You can combine `input_schema` and `output_schema` to create fully typesafe teams that validate inputs and guarantee structured outputs.

For detailed examples and patterns of typesafe implementations, see the [Agent Input and Output documentation](/concepts/agents/input-output#typesafe-agents), which demonstrates the same concepts that apply to Teams.

## Using a Parser Model

You can use a different model to parse and structure the output from your primary model.
This approach is particularly effective when the primary model is optimized for reasoning tasks, as such models may not consistently produce detailed structured responses.

```python theme={null}
team = Team(
    model=Claude(id="claude-sonnet-4-20250514"),  # The main processing model
    members=[...],
    description="You write movie scripts.",
    output_schema=MovieScript,
    parser_model=OpenAIChat(id="gpt-5-mini"),  # Only used to parse the output
)
```

<Tip>
  Using a parser model can improve output reliability and reduce costs since you can use a smaller, faster model for formatting while keeping a powerful model for the actual response.
</Tip>

You can also provide a custom `parser_model_prompt` to your Parser Model to customize the model's instructions.

## Using an Output Model

You can use a different model to produce the run output of the team.
This is useful when the primary model is optimized for image analysis, for example, but you want a different model to produce a structured output response.

```python theme={null}
team = Team(
    model=Gemini(id="gemini-2.0-flash-001"),  # The main processing model
    description="You write movie scripts.",
    output_schema=MovieScript,
    output_model=OpenAIChat(id="gpt-5-mini"),  # Only used to parse the output
    members=[...],
)
```

You can also provide a custom `output_model_prompt` to your Output Model to customize the model's instructions.

<Tip>
  Gemini models often reject requests to use tools and produce structured output
  at the same time. Using an Output Model is an effective workaround for this.
</Tip>

## Developer Resources

* View the [Team schema](/reference/teams/team)
* View [Cookbook](https://github.com/agno-agi/agno/tree/main/cookbook/teams/structured_input_output)
