LangChainLangChain 1.4 · Python 3.10+
0%
1
Curious builder0 XP earned · 300 to level 2
0 daysFinish a lesson to begin
Badge collection0 of 6 unlocked
46 small wins to finish your pathNext lesson →

Structured output with response_format

response_format is a create_agent option that asks the agent for an answer shaped like a Pydantic class and returns it as structured_response, so your code reads fields instead of parsing a sentence.

Last updated: 27 Sep, 2026 · LangChain 1.4

The shop's ticket system wants two fields for every question, the order id and its status, not a sentence to pick apart. You describe the shape with a Pydantic class.

The response_format option

python
agent = create_agent(model, tools=[...], response_format=Ticket)   # Ticket is a Pydantic class
result = agent.invoke(inputs)
result["structured_response"]   # a Ticket instance, ready for code

Defining the Ticket class

Define the shape as a Pydantic class with the fields your code wants.

Exampleticket.py
from pydantic import BaseModel


class Ticket(BaseModel):
    """A support ticket for one order."""
    order_id: str
    status: str

Given a schema, create_agent picks a strategy. If the model supports structured output natively, as OpenAI's and Anthropic's do, it asks the provider for it. Otherwise it uses ToolStrategy: it adds one more tool, named after the class, and requires the model to call a tool on every turn. The arguments of that final call are the answer.

What one model call carries, and what comes back
The requestThe replythe conversation so farsystem promptthe tools, from bind_toolsresponse_format, a schemaruntime context, hiddenThe chat modelyours, or a hosted onetext: the answertool_calls: run thesea call to the schema toolusage_metadata, tokens
Hover or tap a piece to see what it is and which lesson built it.
Follow one call

Pick one to watch it run, step by step.

Making the model fill Ticket

This small stand-in model has no native support, so it gets the extra tool and needs to know what to do with it. When it would answer in words and a tool called Ticket is bound, it splits its answer into an order id and a status and calls that tool instead.

Exampleticket_model.py
from langchain.messages import AIMessage
from shop_model import ShopModel


class TicketModel(ShopModel):
    def decide(self, messages):
        reply = super().decide(messages)
        if reply.tool_calls or "Ticket" not in [t.name for t in self.tools]:
            return reply
        order_id, status = reply.text.rstrip(".").split(" ", 1)
        args = {"order_id": order_id, "status": status}
        return AIMessage("", tool_calls=[{"name": "Ticket", "args": args, "id": "call_ticket"}])

Wiring in response_format

Wire the class in with response_format.

Exampleagent.py
from langchain.agents import create_agent
from ticket import Ticket
from ticket_model import TicketModel
from tools import lookup_order

agent = create_agent(TicketModel(), tools=[lookup_order], response_format=Ticket)

The structured answer on one question

Ask one question and read both the structured response and the messages behind it.

Example
result = agent.invoke({"messages": [{"role": "user", "content": "Where is my order A17?"}]})

print(repr(result["structured_response"]))
for message in result["messages"]:
    print(f"{message.type:<6} {message.text or message.tool_calls[0]['name']}")

What structured_response held

  • structured_response is a Ticket object, ready for code to use.
  • The conversation shows how it got there: the lookup, then a call to the Ticket tool, then a tool message that ends the loop by returning the ticket.
  • Because this stand-in model has no native structured output, create_agent added the Ticket tool and required a tool call each turn; the arguments of the final call became the answer.

A sentence vs response_format

Plain answerresponse_format
What you get backText in result["messages"]A Ticket in result["structured_response"]
Your code thenParses the sentenceReads fields
If a field is missingYou notice lateThe class can require it

When to use structured output

  • Feeding an answer into another system: a ticket, a row in a database, a form.
  • Any time code, not a person, reads what the agent produced.
Watch out. With ToolStrategy the class name becomes a tool name, so the model must call it to finish. If your prompt or model never calls that tool, the run has no structured_response to return.
Try it yourself
  • Add a field customer: str = "unknown" to Ticket and print the response again.
  • Ask about B22 and read the status the ticket gets.
  • Print result["structured_response"].model_dump() to get a plain dictionary.

Little by little, you're building something great.