Chains: Composing Prompts, Models, and Output Parsers with LCEL
A single call to a model is rarely the whole story, real applications format a prompt, send it to a model, then parse the result into something usable. LCEL (LangChain Expression Language) is the syntax for wiring these steps into a single, reusable chain using the | (pipe) operator.
Building a chain with the pipe operator
This needs a real API key, so it's read-only here. prompt | model | parser reads left to right: the input dictionary flows into prompt, its output (a list of chat messages) flows into model, and the model's response object flows into parser, which extracts just the plain text string, result is a str, not a message object you'd need to unwrap yourself.
Why a pipe instead of manual function calls
Every piece in a chain (prompts, models, parsers, and more) implements the same Runnable interface: .invoke(), .stream(), and .batch(). That's what makes | work at all, it's building a new Runnable out of smaller ones, and the composed chain gets .stream() and .batch() for free, without you writing any extra code for them.
Also read-only here, since it calls the model. .batch() runs the whole chain, prompt formatting, model call, and parsing, once per item in the list.
Output parsers beyond plain text
StrOutputParser just extracts text, but parsers can do more structured work, JsonOutputParser validates and parses the model's output straight into a Python object, catching malformed output before it reaches the rest of your application.
NOTE
A chain is just a Runnable built from other Runnables, once you see that, LCEL stops looking like special syntax, prompt | model | parser is exactly as composable as chaining any other typed pipeline stages together.