# LangChain Core Cheat Sheet
_Runnables, LCEL composition and the streaming interface_
Modern LangChain is one interface — the Runnable — and a pipe operator for composing them. Learning that pair covers most of the library.
> Difficulty: intermediate  
> Version: 1.0  
> Updated: 2025-12-22  
> Categories: LangChain  
> Tags: Embeddings, Openai, Streaming

Source: https://invitationbuddy.com/cheat-sheet/langchain-core-cheat-sheet

---

## The Runnable interface
| Method | Does | Returns |
| --- | --- | --- |
| `invoke(input)` | Runs once  One output |
| `batch(inputs)` | Runs many, in parallel where possible  A list of outputs |
| `stream(input)` | Runs once, yielding as it goes  An iterator of chunks |
| `astream_events(input)` | Streams every internal step  An iterator of typed events |
| `with_retry()` | Wraps with a retry policy  A Runnable |
| `with_fallbacks()` | Adds alternatives on failure  A Runnable |

## Composition
| Construct | Meaning |
| --- | --- |
| `a \| b` | Pipe: a's output becomes b's input |
| `RunnableParallel({"x": a, "y": b})` | Run both on the same input, return a dict |
| `RunnablePassthrough()` | Forward the input unchanged — used to keep the original alongside a result |
| `RunnableLambda(fn)` | Lift any plain function into the chain |
| `RunnableBranch(...)` | Conditional routing |
| `.bind(**kwargs)` | Pin arguments — model parameters, tools — onto a step |

## Composition is what buys streaming
Anything built by piping Runnables gets streaming, batching, async and tracing for free, because every link implements the same interface. Dropping to plain Python inside a step is allowed — but that step becomes a black box that cannot stream, which is usually why a chain "suddenly stopped streaming".

## Code examples
### An LCEL chain that streams
Everything built by piping Runnables inherits streaming, batching and async for free.
```python
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnableParallel, RunnablePassthrough

prompt = ChatPromptTemplate.from_template(
    "Answer using ONLY this context.\n\n{context}\n\nQuestion: {question}"
)

chain = (
    RunnableParallel(
        context=retriever | (lambda docs: "\n\n".join(d.page_content for d in docs)),
        question=RunnablePassthrough(),      # keep the original question
    )
    | prompt
    | model
    | StrOutputParser()
)

for chunk in chain.stream("What changed in the refund policy?"):
    print(chunk, end="", flush=True)
```

## FAQs
**Why did my chain stop streaming?**
Almost always a step that dropped to plain Python. Anything not implementing the Runnable interface is a black box the streaming machinery cannot see through.

**Do I need LangChain at all?**
For a single model call, no — the provider SDK is simpler. It earns its place when you want composition, retries, fallbacks and tracing across many steps without writing that layer yourself.

---
_Generated from https://invitationbuddy.com/cheat-sheet/langchain-core-cheat-sheet_
