Match each LCEL Runnable method to the call pattern it is designed for
Drag each answer to line up with its matching prompt
Single input, single output, synchronous. The simplest call shape
.abatch(inputs)
List of inputs processed in parallel up to max_concurrency, results in input order
.stream(input)
Single input yielding incremental output chunks to a synchronous iterator
.invoke(input)
Single input yielding chunks via an async generator suitable for async for
.astream(input)
List of inputs in an async context with the same input order guarantee as batch
.batch(inputs)
Every LCEL Runnable exposes five core call methods on a 2-axis grid: input is single or list; output is sync, async, or streaming chunks; the `a`-prefix marks async.
Think of a coffee shop with one barista. You can place a single order and wait at the counter (invoke). You can hand over a list of five orders to be prepared together (batch). You can ask for a drip coffee where the cup fills sip by sip while you watch (stream). The same three shapes exist in an async version of the shop where you can walk away and come back when notified (astream and abatch). One axis is 'how many drinks am I ordering,' the other is 'do I want it now, or to receive it as it pours.' The five LCEL methods are exactly the cells in that grid.
Concept explanation~2 min read
Everything you need to truly understand this topic: intuition, mechanics, step by step explanation, code, formulas, and worked example. Click to expand.
Concept explanation~2 min read
Everything you need to truly understand this topic: intuition, mechanics, step by step explanation, code, formulas, and worked example. Click to expand.
LangChain Expression Language (LCEL) introduced a uniform call surface across every Runnable in the framework. The five methods asked about here, invoke, batch, stream, astream, abatch, are how application code consumes that uniformity. A chain composed with the pipe operator is a Runnable; a single chat model is a Runnable; a custom Python function wrapped with RunnableLambda is a Runnable. All of them expose the same five methods, which is what makes LangChain compose at all.
This deep dive walks through the 2-axis grid those five methods live on, the ordering and parallelism guarantees, the sync/async distinction, and the cousin methods (astream_events, astream_log) that production observability depends on.
The two-axis grid
The five methods are organised across two orthogonal axes.
Axis 1: input shape
- Single input. You pass one input dict (or one string for chat models) and you get one output. Methods: invoke, stream, ainvoke, astream.
- List of inputs. You pass a list of input dicts; the runtime runs them in parallel up to a configurable concurrency cap and returns a list of outputs in input order. Methods: batch, abatch.
Axis 2: output delivery
- Complete value. The method blocks until the full output is ready, then returns it. Methods: invoke, batch, ainvoke, abatch.
- Incremental chunks. The method returns an iterator (sync) or async generator (async) that yields chunks as they arrive from the underlying provider. Methods: stream, astream.
The async marker
The a prefix means 'async-context version of the same method.' .ainvoke, .abatch, .astream are awaitables or async generators meant to be called inside async def functions. They exist because Python's sync and async worlds are not interchangeable. Calling a sync iterator inside an event loop blocks every other coroutine on that loop, and most production LLM apps live in async land.
Matching the five methods is therefore a name-decomposition exercise. Read the method name, decode the axes, place it in the grid.
Situations where this technique stops working.
2–4 min · Everything important, quickly.
from langchain_anthropic import ChatAnthropic
from langchain_core.prompts import ChatPromptTemplate
prompt = ChatPromptTemplate.from_template("Summarise {topic} in 3 bullets.")
chain = prompt | ChatAnthropic(model="claude-sonnet-4-6")
# 1. Single sync call
result = chain.invoke({"topic": "OpenTelemetry"})
# 2. List of inputs, parallel up to max_concurrency
results = chain.batch([{"topic": t} for t in topics], config={"max_concurrency": 8})
# 3. Sync streaming for a CLI
for chunk in chain.stream({"topic": "vector databases"}):
print(chunk.content, end="", flush=True)
# 4. Async streaming for FastAPI / SSE
async def handler(topic: str):
async for chunk in chain.astream({"topic": topic}):
yield chunk.content| Method | Input shape | Output delivery | Async? | Typical use |
|---|---|---|---|---|
| `.invoke` | Single | Complete value | No | Simple sync call |
| `.batch` | List | List of complete values, in order | No | Parallel sync evaluation |
| `.stream` | Single | Sync iterator of chunks | No | CLI / sync UI streaming |
| `.astream` | Single | Async generator of chunks | Yes | FastAPI SSE / WebSocket |
| `.abatch` | List | List in input order | Yes | Async eval / web batch jobs |
Real products, models, and research that use this idea.
- FastAPI servers commonly expose LCEL chains via `astream` mounted on an SSE endpoint, with each token surfaced to the browser as a Server-Sent Event.
- LangChain's evaluation tooling (LangSmith and the open-source evaluators) defaults to `.abatch` over the eval set so a 1000-example evaluation finishes in roughly `1000 / max_concurrency` per-call latencies.
What an interviewer would ask next. Try answering before peeking at the approach.
QWhat is the difference between `.astream` and `.astream_events`?
.astream yields the final-stage output chunks. .astream_events yields structured events for every step in the chain (on_chain_start, on_llm_stream, on_tool_end, etc.). Useful for debugging and intermediate-state streaming.
Red flags & common mistakes
The phrases that signal junior thinking. Click to expand.
Red flags & common mistakes
The phrases that signal junior thinking. Click to expand.
Calling `.invoke` in a hot loop over a list of inputs when `.batch` would parallelise the same work for free, then debugging 'why is my pipeline slow?'
60 second bullets to scan on the way to the call.
The two axes that organise the call surface (input shape, output delivery)
Naming convention: letter-a prefix for async, batch in the name for list input, stream in the name for chunks
Primary sources. Browse if you want the original framing.
Same topic, related formats. Practice these next.