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 outputstructured_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 handler
And 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))