Skip to content
Forward Deployed

Forward Deployed
Lessons and contents
LCEL, Runnables & ChainsLesson 1 of 7
7 lessons
Learn

LCEL, Runnables & Chains: overview

Source
From the RAG & Agents Engineering course
By
Sourav Banerjee
Last updated
8 Nov 2026

Report an issue

LCEL is how LangChain 1.x composes work: prompts, models, parsers and retrievers snap together with |, and the result runs with the same methods as each piece. Every RAG chain from T5.1 onwards is one of these pipes. The T4.2 notebooks build on four ideas: the one interface every component shares, the pipe that joins components into a sequence, the parallel and branching shapes a pipe can take, and map-reduce for documents longer than one prompt.

The running example is the Larkspur Cloud handbook used from T5.1 onwards: a support assistant that answers refund and outage questions, triages tickets, and summarises handbook sections. The lab summarises three handbook documents of 1,111, 1,833 and 2,746 characters.

In short

  • A Runnable has one interface: invoke for one input, batch for a list, stream for chunks, and an async twin of each. Prompts, models, parsers, retrievers and whole chains all have it.
  • a | b is Python's __or__ returning a RunnableSequence. A dict inside a pipe becomes a RunnableParallel, so {"context": retriever | format_docs, "question": RunnablePassthrough()} | prompt | llm | parser is a complete RAG chain.
  • RunnableParallel runs its branches on the same input at once: notebook 03a's description, pros and cons chains plus a merge chain make 4 model calls in 2 rounds. RunnableBranch runs the first branch whose condition is true.
  • LLMChain, RetrievalQA and load_summarize_chain now live in langchain-classic, deprecated with removal set for 2.0.0. Each rewrites as a short pipe.
  • Map-reduce trades calls for a small prompt. In the lab the whole handbook at chunk_size=400 is 10 chunks: map-reduce makes 11 calls in 4 rounds at max_concurrency=4, refine makes 10 calls in 10 rounds, and stuff makes 1 call that reads all 2,746 characters.

Mental model

The LCEL RAG chain A question enters a dict that runs two branches at once: the retriever with format_docs, and a passthrough. Their outputs form one dict with context and question, which flows through the prompt, the chat model and the string parser to an answer string. RunnableParallel, the dict Question How long does a refund take? retriever | format_docs Passthrough chunks, joined question, unchanged dict context, question Prompt ChatPromptValue Model AIMessage Parser str
  1. A customer asks “How long does a refund take?” The string is the chain’s only input.
  2. The dict runs both branches on the same string at once. The retriever finds handbook chunks and format_docs joins them into one string.
  3. The two results come back as one dict with the keys context and question.
  4. The prompt fills its two variables and returns a ChatPromptValue.
  5. The chat model reads the messages and returns an AIMessage.
  6. StrOutputParser takes the message text and returns a plain string.
  7. The caller gets the answer string. The whole pipe is one Runnable, called with invoke.

This is the RAG chain from notebook 04a, and every box in it is a Runnable. The dict fans the question out to two branches and hands one dict to the prompt; each later step takes the previous step's output as its only input. Because the whole pipe is also a Runnable, the chain you build here can sit inside a bigger pipe, a RunnableBranch or a LangGraph node without changes.

Interactive lab

Stuff, map-reduce or refine: open the file in a browser. Pick Whole handbook and slide the chunk size from 1200 down to 200: refine's rounds climb from 3 to 21 while map-reduce stays at 2 to 7. Then set max_concurrency to 1 and watch map-reduce take one round more than refine. Finally pick Refunds section to see the router send a short document to stuff.

How it connects

  • Before: T4.1 covers the pieces this module pipes together: chat models, prompt templates and output parsers.
  • Next: T4.3 and T4.4 move control flow into LangGraph, where a Runnable can be a node. T5.1 composes its baseline RAG chain as exactly this pipe (notebook 05a), and T5.3 explains the splitter the map step depends on. T7.3 turns RunnableParallel into the parallelisation workflow pattern, and T13.1 applies recursive summarisation to a whole corpus.

Key Takeaways

  • Every component and every chain shares one interface, so test each step alone with .invoke() before you pipe it.
  • Build data flow with dicts: a dict fans one input out, and RunnablePassthrough.assign() adds a key while keeping the rest.
  • Write new chains as pipes. Treat langchain_classic imports as a staging post for old code, never as a destination.
  • Choose a summarisation strategy by length and latency: stuff when it fits, map-reduce when it does not, refine only when order should matter.

Rate your confidence and keep notes on the module page.