Structured output

LangChain · Practical · 12 min

Extraction, classification and routing need reliable fields, not free text you parse with regexes.

model.with_structured_output(schema) returns a runnable that outputs data matching schema instead of an AIMessage. The schema can be:

  • a Pydantic model (you get a validated instance),
  • a TypedDict or JSON Schema dict (you get a dict).

Field descriptions and docstrings are sent to the model, so write them as instructions.

class Ticket(BaseModel):
    category: Literal["billing", "bug", "other"]
    urgency: int = Field(description="1 (low) to 5 (critical)")

extractor = model.with_structured_output(Ticket)
extractor.invoke("I was charged twice!!")   # Ticket(category='billing', urgency=4)

Under the hood LangChain uses the provider's native structured output (JSON schema mode) or tool calling, chosen per provider; method="json_schema" or "function_calling" overrides it. include_raw=True returns the raw message and any parsing error alongside the parsed value, so you can handle failures without exceptions.

In agents, pass response_format=Schema to create_agent; the final structured answer appears in the result's structured_response.

Keep schemas small and flat where possible, use Literal or enums for categories, and add descriptions for anything ambiguous. Validation errors usually mean the schema or instructions are unclear rather than that the model is incapable.

Example

from typing import Literal
from pydantic import BaseModel, Field
from langchain.chat_models import init_chat_model

class Ticket(BaseModel):
    # Support ticket extracted from a customer message.
    category: Literal["billing", "bug", "feature", "other"]
    urgency: int = Field(ge=1, le=5, description="1 = low, 5 = critical")
    summary: str = Field(description="One short sentence")

model = init_chat_model("openai:gpt-5-mini", temperature=0)
extractor = model.with_structured_output(Ticket)

t = extractor.invoke("You charged my card twice this month, fix it now!")
print(type(t).__name__, t.category, t.urgency)   # Ticket billing 4 (or 5)

safe = model.with_structured_output(Ticket, include_raw=True)
out = safe.invoke("hello")
print(out.keys())   # dict_keys(['raw', 'parsed', 'parsing_error'])

Remember

  • with_structured_output(PydanticModel) returns validated objects
  • Field descriptions guide the model; use Literal/enums for categories
  • include_raw=True exposes parsing errors; agents use response_format

Watch out for

  • Asking for JSON in the prompt and parsing it with json.loads, which breaks on markdown fences and missing fields.

Check yourself

  1. What do you get from model.with_structured_output(MyPydanticModel).invoke(text)?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: docs.langchain.com/oss/python/langchain/structured-output

Builds on

Unlocks

Nothing builds on this yet.