Using Structured Output
Most of the time you need results from an agent in a specific format. Agents results can return structured json in two ways:
- output_cls– a Pydantic model to use as a schema for the output
- structured_output_fn– For more advanced use cases, supply a custom function that validates or rewrites the agent’s conversation into any model you want.
Both single-agents like FunctionAgent and ReActAgent, as well as multi-agent AgentWorkflow workflows, support these options - let’s explore the possibilities:
Use output_cls
Section titled “Use output_cls”from llama_index.core.agent.workflow import FunctionAgent, AgentWorkflowfrom llama_index.llms.openai import OpenAIfrom pydantic import BaseModel, Field
llm = OpenAI(model="gpt-4.1")
## define structured output format  and toolsclass MathResult(BaseModel):    operation: str = Field(description="the performed operation")    result: int = Field(description="the result of the operation")
def multiply(x: int, y: int):    """Multiply two numbers"""    return x * y
## define agentagent = FunctionAgent(    tools=[multiply],    name="calculator",    system_prompt="You are a calculator agent who can multiply two numbers using the `multiply` tool.",    output_cls=MathResult,    llm=llm,)
response = await agent.run("What is 3415 * 43144?")print(response.structured_response)print(response.get_pydantic_model(MathResult))This also works with mutl-agent workflows:
## define structured output format  and toolsclass Weather(BaseModel):    location: str = Field(description="The location")    weather: str = Field(description="The weather")
def get_weather(location: str):    """Get the weather for a given location"""    return f"The weather in {location} is sunny"
## define single agentsagent = FunctionAgent(    llm=llm,    tools=[get_weather],    system_prompt="You are a weather agent that can get the weather for a given location",    name="WeatherAgent",    description="The weather forecaster agent.",)main_agent = FunctionAgent(    name="MainAgent",    tools=[],    description="The main agent",    system_prompt="You are the main agent, your task is to dispatch tasks to secondary agents, specifically to WeatherAgent",    can_handoff_to=["WeatherAgent"],    llm=llm,)
## define multi-agent workflowworkflow = AgentWorkflow(    agents=[main_agent, agent],    root_agent=main_agent.name,    output_cls=Weather,)
response = await workflow.run("What is the weather in Tokyo?")print(response.structured_response)print(response.get_pydantic_model(Weather))Use structured_output_fn
Section titled “Use structured_output_fn”The custom function should take as input a sequence of ChatMessage objects produced by the agent workflow and returns a dictionary (that can be turned into a BaseModel subclass):
import jsonfrom llama_index.core.llms import ChatMessagefrom typing import List, Dict, Any
class Flavor(BaseModel):    flavor: str    with_sugar: bool
async def structured_output_parsing(    messages: List[ChatMessage],) -> Dict[str, Any]:    sllm = llm.as_structured_llm(Flavor)    messages.append(        ChatMessage(            role="user",            content="Given the previous message history, structure the output based on the provided format.",        )    )    response = await sllm.achat(messages)    return json.loads(response.message.content)
def get_flavor(ice_cream_shop: str):    return "Strawberry with no extra sugar"
agent = FunctionAgent(    tools=[get_flavor],    name="ice_cream_shopper",    system_prompt="You are an agent that knows the ice cream flavors in various shops.",    structured_output_fn=structured_output_parsing,    llm=llm,)
response = await agent.run(    "What strawberry flavor is available at Gelato Italia?")print(response.structured_response)print(response.get_pydantic_model(Flavor))Streaming the Structured Output
Section titled “Streaming the Structured Output”You can get the structured output while the workflow is running by using the AgentStreamStructuredOutput event:
from llama_index.core.agent.workflow import (    AgentInput,    AgentOutput,    ToolCall,    ToolCallResult,    AgentStreamStructuredOutput,)
handler = agent.run("What strawberry flavor is available at Gelato Italia?")
async for event in handler.stream_events():    if isinstance(event, AgentInput):        print(event)    elif isinstance(event, AgentStreamStructuredOutput):        print(event.output)        print(event.get_pydantic_model(Weather))    elif isinstance(event, ToolCallResult):        print(event)    elif isinstance(event, ToolCall):        print(event)    elif isinstance(event, AgentOutput):        print(event)    else:        pass
response = await handlerAnd you can parse the structured output in the agent’s response accessing it directly as a dictionary or loading it as a BaseModel subclass by using the get_pydantic_model method:
print(response.structured_response)print(response.get_pydantic_model(Flavor))