LangChain/Prompts & Output
Intermediate12 min

Output Parsers

LangChain has four ways to get structured output — and three of them are the wrong choice most of the time. This article maps the decision: when to use with_structured_output(), when JsonOutputParser is still the right tool, and what to do with the legacy parsers you inherited.

Quick Reference

  • with_structured_output() is the default for typed extraction — uses native tool calling, fails loudly, no prompt engineering required
  • create_agent(response_format=...) is the v1 agent-level equivalent — ToolStrategy or ProviderStrategy, not parsers
  • StrOutputParser extracts .content as a plain string — not deprecated, use it for every text-output chain
  • JsonOutputParser is the only parser worth reaching for in new code — streaming partial JSON from models without tool calling
  • PydanticOutputParser is legacy — moved to langchain-classic, prompt-injected format instructions, fails silently
  • Tool calling fails loudly (schema validation error); prompt-based parsing fails silently (wrong shape, no exception)
  • JsonOutputParser has a diff=True mode that yields JSONPatch operations — useful for diffing incremental UI updates
  • Output parsers are Runnables — compose them with | in LCEL chains

The Four Ways to Get Structured Output

LangChain v1 has four distinct mechanisms for getting structured data out of a model. They are not interchangeable — each targets a different situation, and using the wrong one in production will cost you debugging time you don't have.

MechanismWhat it doesStatusUse when
with_structured_output()Wraps the model with a schema; uses native tool calling or provider JSON modeCurrent — preferredYou need typed output from any modern model
create_agent(response_format=...)Structured output baked into the agent loop — ToolStrategy or ProviderStrategyCurrent — v1 agents onlyBuilding an agent that must return a typed response
JsonOutputParserParses model text as JSON; streams partial objects incrementallyCurrent — limited scopeStreaming partial JSON from models without tool calling
StrOutputParserExtracts .content as a plain stringCurrent — always validAny chain that returns text
PydanticOutputParserInjects format instructions into the prompt; parses text responseLegacy — langchain-classicMaintaining old code; model doesn't support tool calling

The reason three of these exist at all is history, not design. Output parsers predate tool calling. When GPT-3 was the frontier model, the only way to get JSON was to ask nicely and hope. Tool calling changed that — models now have a native JSON output path that is schema-validated and far more reliable. LangChain v1 codifies this: structured output strategies are first-class, parsers are backward compatibility.

LLM Output NeededJust needplain text?YesStrOutputParserlangchain_core.output_parsersNoModel supportstool calling?Yeswith_structured_output()or create_agent response_formatNoNeed streamingpartial JSON?YesJsonOutputParserstreaming partial JSONNoPydanticOutputParserlegacy — use langchain-classic

Start at the top — exit at the first match