Runnables, LCEL composition and the streaming interface
Modern LangChain is one interface — the Runnable — and a pipe operator for composing them. Learning that pair covers most of the library.
| Method | Does | Returns |
|---|---|---|
invoke(input) |
Runs once | One output |
batch(inputs) |
Runs many, in parallel where possible | A list of outputs |
stream(input) |
Runs once, yielding as it goes | An iterator of chunks |
astream_events(input) |
Streams every internal step | An iterator of typed events |
with_retry() |
Wraps with a retry policy | A Runnable |
with_fallbacks() |
Adds alternatives on failure | A Runnable |
| Construct | Meaning |
|---|---|
a | b |
Pipe: a's output becomes b's input |
RunnableParallel({"x": a, "y": b}) |
Run both on the same input, return a dict |
RunnablePassthrough() |
Forward the input unchanged — used to keep the original alongside a result |
RunnableLambda(fn) |
Lift any plain function into the chain |
RunnableBranch(...) |
Conditional routing |
.bind(**kwargs) |
Pin arguments — model parameters, tools — onto a step |
Everything built by piping Runnables inherits streaming, batching and async for free.
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnableParallel, RunnablePassthrough
prompt = ChatPromptTemplate.from_template(
"Answer using ONLY this context.\n\n{context}\n\nQuestion: {question}"
)
chain = (
RunnableParallel(
context=retriever | (lambda docs: "\n\n".join(d.page_content for d in docs)),
question=RunnablePassthrough(), # keep the original question
)
| prompt
| model
| StrOutputParser()
)
for chunk in chain.stream("What changed in the refund policy?"):
print(chunk, end="", flush=True)
Almost always a step that dropped to plain Python. Anything not implementing the Runnable interface is a black box the streaming machinery cannot see through.
For a single model call, no — the provider SDK is simpler. It earns its place when you want composition, retries, fallbacks and tracing across many steps without writing that layer yourself.