LCEL & ChainsLesson 7

RunnablePassthrough

Sequential Chains used RunnablePassthrough.assign to keep tag while adding explanation. This lesson covers both forms: RunnablePassthrough() returns the input dict unchanged; .assign(...) runs a sub-chain and merges new keys. The demo also uses passthrough inside RunnableParallel.

Passthrough() and .assign()

RunnablePassthrough() {"tag": "a"} in, same dict out. .assign(explanation=explain_chain) — runs the sub-chain and adds explanation to the dict.

RunnablePassthrough() — input goes in, same dict comes out:

invoke{"tag": "a"}
RunnablePassthrough(){"tag": "a"}

RunnablePassthrough.assign() — adds keys, keeps the rest:

{"tag": "a"}.assign(explanation=…){"tag":"a","explanation":"…"}
RunnablePassthrough() — dict in, same dict out. .assign — dict in, dict out with new keys.

Side by side

Plain passthrough for carrying a dict. Assign when the next prompt needs original keys plus new ones from a chain.

RunnablePassthrough()

passthrough = RunnablePassthrough()
data = passthrough.invoke(
    {"tag": "a"}
)
# {"tag": "a"}  — unchanged

Carry the dict as-is

.assign()

RunnablePassthrough.assign(
    explanation=explain_chain
)
# {"tag": "a", "explanation": "…"}
# original keys kept

Add LLM output as new keys

assign first appeared in Sequential Chains — this lesson shows both forms.

The assign_chain

explain_chain adds explanation. The tip prompt then reads tag and explanation together.

assign_chain = RunnablePassthrough.assign(explanation=explain_chain) | tip_prompt | model | parser

Passthrough + RunnableParallel

One branch runs RunnablePassthrough() so result["original"] is the input dict. The other branch runs explain_chain for result["purpose"].

Passthrough inside RunnableParallel

parallel_chain = RunnableParallel(
    original=RunnablePassthrough(),
    purpose=explain_chain,
)

result = parallel_chain.invoke({"tag": "a"})
# {
#   "original": {"tag": "a"},
#   "purpose":  "The <a> tag creates…"
# }
With RunnableParallel original holds the input dict, purpose holds the model string.

The demo script

runnable_passthrough_demo.py — three sections for a and img.

runnable_passthrough_demo.py
"""runnable_passthrough_demo.py"""
# 1. RunnablePassthrough() — unchanged
# 2. .assign(explanation=…) — add keys
parallel_chain = RunnableParallel(original=RunnablePassthrough(), …)
result = parallel_chain.invoke({"tag": tag})

Download the code

runnable_passthrough_demo.py

passthrough · assign · parallel

Download .py
Save into your langchain-course folder. Needs venv, .env, and packages from Project Setup.

Run it

Activate the venv from Project Setup, then:

python runnable_passthrough_demo.py
PowerShell — (.venv) active
(.venv) PS C:\projects\langchain-course> python runnable_passthrough_demo.py
=== RunnablePassthrough() ===
in: {'tag': 'a'}
out: {'tag': 'a'}
in: {'tag': 'img'}
out: {'tag': 'img'}
=== RunnablePassthrough.assign() ===
Tag: <a>
Tip: Use descriptive link text so users know where the link goes.
Tag: <img>
Tip: Always include an alt attribute to describe the image.
=== Passthrough + RunnableParallel ===
Tag: <a>
original: {'tag': 'a'}
purpose: The <a> tag creates a hyperlink to another page.
Tag: <img>
original: {'tag': 'img'}
purpose: The <img> tag embeds an image in the page.
Three sections in one script — passthrough, assign, parallel combo. Both a and img are in the output.

When to pick each form

  • RunnablePassthrough() — keep the input dict in a parallel branch, as in demo section 3.
  • .assign(key=chain) — add model output as a new key without losing tag or other fields from the input.
  • Official reference: Passthrough runnables.

What's Next

Next: RunnableLambda — custom Python between chain steps.