Skip to main content
As LCEL (LangChain Expression Language) pipelines grow, you frequently need to pass values through unchanged or inject/transform inputs at specific points. RunnablePassthrough is the LCEL primitive for this: it can act as a transparent pipe that forwards data unchanged or as an injector that adds/overrides keys in the runtime input. This document provides concise, corrected examples that illustrate the common patterns for using RunnablePassthrough, plus guidance and best practices.

Overview

  • Purpose: Pass through input unchanged, or inject/modify runtime keys.
  • Typical uses: preserve existing call signatures, insert context/configuration, or compute values before downstream runnables.
  • Works well inside LCEL chains built with prompts, LLMs, and parsers.

Basic prompt -> LLM -> output parser chain

Example showing a simple chain: Prompt → LLM → Output Parser.
Expected truncated example output:

RunnablePassthrough as a no-op passthrough

Inserting a plain RunnablePassthrough() anywhere in the pipeline with no .assign(...) simply forwards the data unchanged. This is useful as a placeholder or to preserve structure when conditionally inserting logic.
Both examples produce the same output as the basic chain above because the passthrough forwards the input unchanged.

RunnablePassthrough as an injector (.assign(...))

RunnablePassthrough can add or override keys in the input dictionary at the point where it is placed in the chain. Use .assign(...) to compute or pin values. The assign mappers receive the runtime input (commonly named x), so you can compute values based on the current state or return constants. Example: build a chain that accepts only question and injects topic = "movies" before the prompt is evaluated.
You can test the effect on the runtime dictionary:

Use cases and quick reference

Why this is useful

RunnablePassthrough is a small but powerful primitive. Use it to:
  • keep pipeline elements as hollow pipes when no transformation is required,
  • inject or compute additional inputs at runtime with .assign(...),
  • pin or hide configuration/context values so external callers don’t need to supply them.

Notes and best practices

  • .assign(...) mappers are evaluated at runtime and merged into the dictionary forwarded to downstream components.
  • The lambda parameter name (often x) is arbitrary; it represents the current runtime input at that stage. If the injected value is constant, you can ignore it (e.g., lambda x: "movies").
  • Instantiate parsers and runnables explicitly (e.g., StrOutputParser()), and prefer clear variable names for readability.
  • Use RunnablePassthrough to preserve external call signatures while adding internal context or configuration.
  • When computing values based on prior steps, ensure the required keys exist to avoid runtime errors — validate or provide fallbacks inside your lambda.

Example patterns

  • Insert configuration or user context only when needed.
  • Replace complex conditional logic in the chain with targeted, testable mappers using .assign(...).
  • Combine multiple .assign(...) calls to coalesce values from different sources (e.g., session, defaults, and request).

Next steps

You can convert arbitrary Python functions into runnable components (for example, using a RunnableLambda) to encapsulate custom logic as first-class LCEL runnables. This lets custom logic participate directly in chains and simplifies testing and reuse.

Watch Video