Prompt templates and chains

Build prompts that stay clean at scale, then compose them into chains with the pipe operator instead of nested function calls.

Prompts as reusable templates

A prompt template is a function from variables to messages. Keeping it separate from the call site means you can version it, test it with different inputs, and reuse it across scripts without copy-paste drift.

from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_openai import ChatOpenAI

prompt = ChatPromptTemplate.from_messages([
    ("system", "You are a terse technical editor. Return the rewritten text only."),
    ("human", "Rewrite for clarity and keep every fact:\n\n{draft}"),
])

chain = prompt | ChatOpenAI(model="gpt-4o-mini", temperature=0) | StrOutputParser()

print(chain.invoke({"draft": "The system does the thing where it retries on failure."}))
MethodReturnsWhen to use
invokeOne resultSingle input, the default call
batchA list of resultsOffline scoring; runs requests concurrently
streamChunks as they arriveAnything a human is waiting on
ainvoke / abatchAwaitable versionsInside async web handlers
with_retryA wrapped runnableFlaky providers; retry with backoff
with_fallbacksA wrapped runnablePrimary model unavailable or rate-limited

The same Runnable interface is implemented by prompts, models, parsers and retrievers, which is what makes | work everywhere. Composition is lazy: nothing runs until you call invoke.

Composing and branching

from langchain_core.runnables import RunnableParallel, RunnablePassthrough, RunnableLambda

clean = RunnableLambda(lambda d: d["text"].strip())

chain = RunnableParallel(
    summary=clean | summary_chain,
    keywords=clean | keyword_chain,
    original=RunnablePassthrough(),          # pass the input through unchanged
)

out = chain.invoke({"text": "  Long report body ...  "})
print(out.keys())                            # dict_keys(['summary', 'keywords', 'original'])
  • Put the variable instruction last in the prompt. Instructions buried above a long document are followed less reliably.
  • Use an explicit output parser (StrOutputParser, JsonOutputParser) rather than reading raw message objects.
  • Keep one chain per responsibility. A chain that retrieves, classifies, writes and emails is untestable.
  • Log the fully rendered prompt in development - most prompt bugs are formatting bugs, not model bugs.
💡
A chain guarantees order, not correctness. If the model must return JSON, parse it and validate against a schema; a well-formed prompt is a request, not an enforced contract.

FAQ

How do I use few-shot examples without bloating the prompt?
Use a few-shot prompt template holding a small, role-tagged example list. Two or three well-chosen examples that cover the hard cases usually beat twenty easy ones.
Do I need LangChain at all?
No. A prompt string and an HTTP call are often enough. It earns its place when you want uniform streaming, batching, retries, fallbacks and tracing across several providers.

Tools and agents Using a model API

Last refreshed 2026-09-18.