What Are LangChain Runnables? #
If you are learning LangChain, one of the most important concepts you will come across is Runnables.
A Runnable is a unit of work that takes an input, processes it, and produces an output.
You can think of Runnables as Lego blocks. Each block performs a particular task, and multiple blocks can be connected together to build an LLM application.
Why Were Runnables Introduced? #
An LLM application usually contains multiple steps. For example:
Runnables provide a common interface that makes it easier to connect these components together.
Using LangChain Expression Language (LCEL), you can write:
chain = prompt | llm | parser
The | operator means that the output of one component
is passed to the next component.
Why Use Runnables? #
01. Standardization #
Different components can use a common interface such as
invoke(), batch(), and
stream().
02. Easy Composition #
Components can be connected easily using the pipe operator.
prompt | llm | parser
03. Parallel Processing #
Independent tasks can be executed using
RunnableParallel.
04. Custom Logic #
Normal Python functions can be added to workflows using
RunnableLambda.
05. Conditional Workflows #
Different paths can be selected using
RunnableBranch.
Runnable Execution Methods #
Runnables provide a common way to execute LangChain components.
| Method | Purpose |
|---|---|
invoke() |
Process a single input |
batch() |
Process multiple inputs |
stream() |
Stream output progressively |
ainvoke() |
Asynchronous execution |
abatch() |
Asynchronous batch processing |
astream() |
Asynchronous streaming |
1. invoke() #
Use invoke() when you want to process one input.
result = chain.invoke(input)
Example #
from langchain_core.runnables import RunnableLambda
square = RunnableLambda(lambda x: x ** 2)
result = square.invoke(5)
print(result)
25
2. RunnableSequence #
RunnableSequence executes multiple Runnables
one after another.
The most common way to create a sequence is with the pipe operator:
chain = prompt | llm | parser
This syntax is part of LangChain Expression Language (LCEL).
Example: Prompt → LLM → Parser #
from langchain_ollama import ChatOllama
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
llm = ChatOllama(model="gemma3:1b")
prompt = ChatPromptTemplate.from_template(
"Explain {topic} in simple words."
)
parser = StrOutputParser()
chain = prompt | llm | parser
result = chain.invoke({
"topic": "LangChain"
})
print(result)
Important: A Chain Is Also a Runnable #
This is one of the most important concepts to understand.
chain = prompt | llm | parser
The resulting chain is itself a Runnable.
Therefore, you can use the same Runnable methods:
chain.invoke(...)
chain.batch(...)
chain.stream(...)
You can even connect this chain to another Runnable:
new_chain = chain | another_runnable
3. RunnableParallel #
RunnableParallel is used when multiple independent
tasks need to run using the same input.
Example #
from langchain_ollama import ChatOllama
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnableParallel
llm = ChatOllama(model="gemma3:1b")
summary_prompt = ChatPromptTemplate.from_template(
"Give a short explanation of {topic}"
)
question_prompt = ChatPromptTemplate.from_template(
"Create 3 interview questions about {topic}"
)
summary_chain = summary_prompt | llm
question_chain = question_prompt | llm
parallel_chain = RunnableParallel(
summary=summary_chain,
questions=question_chain
)
result = parallel_chain.invoke({
"topic": "LangChain"
})
print("SUMMARY:")
print(result["summary"].content)
print("QUESTIONS:")
print(result["questions"].content)
RunnableParallel returns the results using the
keys you provide.
result["summary"].content
result["questions"].content
4. RunnablePassthrough #
RunnablePassthrough passes the input forward
without changing it.
from langchain_core.runnables import RunnablePassthrough
passthrough = RunnablePassthrough()
result = passthrough.invoke("Hello")
print(result)
Hello
Example with RunnableParallel #
from langchain_core.runnables import (
RunnableParallel,
RunnableLambda,
RunnablePassthrough
)
chain = RunnableParallel(
original=RunnablePassthrough(),
uppercase=RunnableLambda(lambda x: x.upper())
)
result = chain.invoke("hello")
print(result)
{
"original": "hello",
"uppercase": "HELLO"
}
5. RunnableLambda #
RunnableLambda allows you to use your own Python
functions inside a LangChain workflow.
from langchain_core.runnables import RunnableLambda
word_counter = RunnableLambda(
lambda x: len(x.split())
)
result = word_counter.invoke(
"LangChain makes LLM applications easier"
)
print(result)
6
Why Use RunnableLambda? #
- Data cleaning
- Text preprocessing
- Calculations
- Validation
- Formatting
- Custom business logic
6. RunnableBranch #
RunnableBranch is used when your workflow needs
conditional logic.
Think of it as the LangChain equivalent of an
if/else decision.
Example #
from langchain_core.runnables import (
RunnableBranch,
RunnableLambda
)
long_text = RunnableLambda(
lambda x: "The text is long."
)
short_text = RunnableLambda(
lambda x: "The text is short."
)
branch = RunnableBranch(
(
lambda x: len(x) > 20,
long_text
),
short_text
)
result = branch.invoke(
"This is a very long sentence"
)
print(result)
If the condition len(x) > 20 is true,
the first path is executed. Otherwise, the default path runs.
7. batch() #
Use batch() when you want to process multiple
inputs using the same Runnable.
from langchain_core.runnables import RunnableLambda
double = RunnableLambda(lambda x: x * 2)
results = double.batch([1, 2, 3, 4])
print(results)
[2, 4, 6, 8]
This is useful when processing many independent inputs.
8. Streaming with stream() #
LLM responses can take some time to generate. With
stream(), output can be received progressively.
for chunk in chain.stream(input):
print(chunk, end="")
Streaming is especially useful for:
- Chatbots
- AI assistants
- Interactive applications
- Real-time user interfaces
Runnables in RAG #
Runnables are particularly useful when building RAG (Retrieval-Augmented Generation) applications.
A simplified RAG Runnable pipeline can look like:
from langchain_core.runnables import RunnablePassthrough
rag_chain = (
{
"context": retriever,
"question": RunnablePassthrough()
}
| prompt
| llm
| parser
)
Here, the retriever generates the context while
RunnablePassthrough() keeps the original question.
Runnable Types at a Glance #
| Runnable | What It Does | Example |
|---|---|---|
RunnableSequence |
Executes steps in order | Prompt → LLM → Parser |
RunnableParallel |
Executes independent paths | Summary + Questions |
RunnablePassthrough |
Keeps the input unchanged | Preserve original question |
RunnableLambda |
Runs custom Python logic | Word counting |
RunnableBranch |
Selects a path conditionally | If/else routing |
Easy Way to Remember Runnables #
Final Takeaway #
You don’t need to memorize every Runnable class when you are just starting with LangChain.
Remember These Three Ideas #
Input → Runnable → Output
| = Connect Components
prompt | llm | parser
Sequence → Parallel → Lambda → Branch
Once you understand Runnables, you will have a much easier time understanding advanced LangChain concepts such as RAG pipelines, chatbots, agents, and multi-step LLM workflows.
Quiz #
Q.1 In the context of LangChain's history, what was a primary issue with using specific chain classes like 'LLMChain' or 'RetrievalQA'?
The sheer number of specific chains led to a heavy code base and a steep learning curve.
They were too computationally expensive to run on standard hardware.
They could only handle single-step tasks and were incapable of being combined.
They were only compatible with OpenAI models and could not use open-source alternatives.
Explanation
LangChain originally included many specialized chain classes. This increased the library’s complexity, made it harder to maintain, and created a steeper learning curve for developers.
Q.2 Which standard method is implemented across all Runnables to allow them to process a single input and return an output?
format
predict
invoke
execute
Explanation
Every Runnable implements the invoke() method, which accepts a single input and returns the corresponding output, providing a consistent interface across LangChain components.
Q.3 How does 'RunnableParallel' handle the input it receives?
It sends the exact same input to every internal Runnable simultaneously.
It splits the input into chunks and sends one chunk to each internal Runnable.
It modifies the input based on the requirements of each specific component before sending it.
It passes the input to the first Runnable and then passes that output to the next one.
Explanation
RunnableParallel broadcasts the same input to multiple Runnables at the same time, allowing them to execute independently and return their results together.
Q.4 What is the primary purpose of the 'RunnablePassThrough' primitive?
To filter out unnecessary metadata from the LLM response.
To convert a standard Python function into a format compatible with LangChain.
To output the input exactly as it was received without any processing.
To automatically retry a failed API call in a sequential chain.
Explanation
RunnablePassThrough simply forwards the input unchanged. It is useful when you need to preserve or reuse the original input while other processing occurs in the chain.
Q.5 When using 'RunnableBranch', what happens if none of the defined conditions are met?
A default Runnable, provided as the last argument, is executed.
The input is passed directly to the next component in the sequence.
The chain throws an error and stops execution.
It randomly selects one of the existing branches to execute.
Explanation
RunnableBranch works like an if-else statement. If none of the specified conditions match, the default Runnable provided as the final argument is executed.
Q.6 What is the main benefit of converting a Python function into a 'RunnableLambda'?
It allows the custom logic within the function to be seamlessly piped into a LangChain sequence.
It automatically translates the Python code into JavaScript for cross-platform use.
It encrypts the function's logic to protect sensitive intellectual property.
It makes the function run 10× faster by using the LangChain runtime.
Explanation
RunnableLambda wraps a normal Python function as a Runnable so it can be combined with other LangChain components using LCEL operators like the pipe (|).
Q.7 Which LCEL (LangChain Expression Language) operator is used to create a 'RunnableSequence'?
The Ampersand operator (&)
The Arrow operator (->)
The Pipe operator (|)
The Plus operator (+)
Explanation
The pipe (|) operator connects Runnables into a RunnableSequence, where the output of one component becomes the input of the next.
Q.8 Which of the following best describes 'Task-Specific Runnables'?
They are temporary runnables that only exist during the debugging phase of development.
They are runnables specifically designed to manage hardware resources like GPU memory.
They are core LangChain components, like models or parsers, that have been standardized as runnables.
They are the building blocks that define how other runnables interact.
Explanation
Task-specific Runnables are standard LangChain components such as chat models, prompt templates, retrievers, output parsers, and tools that all implement the Runnable interface.
Q.9 According to the analogy provided in the source material, why are Runnables like Lego blocks?
Because they are inexpensive and easy to replace if a better version is released.
Because every block has a specific purpose and uses a standard interface to connect to any other block.
Because they come in different colors to help organize the code visually.
Because they are designed primarily for educational purposes and not for professional applications.
Explanation
Like Lego blocks, every Runnable has a specific role but follows the same interface, allowing developers to combine different components together in flexible and reusable workflows.
Q.10 If you wanted to calculate the number of words in an LLM's response using a custom Python function inside a chain, which primitive would you use?
RunnableLambda
RunnableParallel
RunnablePassThrough
RunnableSequence
Explanation
RunnableLambda is designed to wrap custom Python functions so they can participate in LangChain pipelines alongside prompts, models, retrievers, and other Runnables.