What is ChatPromptTemplate?
ChatPromptTemplate is the LangChain primitive for building role-aware prompts for chat models. Where PromptTemplate produces a single string, ChatPromptTemplate produces an ordered list of messages — system, human, AI, and tool roles — each with {variable} placeholders that are filled at invoke time. This is the right abstraction for chat models, which expect a structured message list rather than one flat string.
You usually build it with the from_messages classmethod, passing tuples like ('system', '...') and ('human', '{input}'), or message objects directly. Because it is a Runnable, it composes with the pipe operator: prompt | model | parser is the canonical LCEL chain. Calling invoke with a dict of variables returns a ChatPromptValue you can pass straight to a chat model. For conversation memory, drop in a MessagesPlaceholder so prior turns are spliced into the message list at render time.
ChatPromptTemplate lives in langchain-core, so it has no provider dependency and works identically across ChatOpenAI, ChatAnthropic, and every other chat model. Two gotchas dominate real bugs: literal curly braces in the template must be escaped by doubling them ({{ and }}), otherwise they are read as variables; and partial_variables lets you pre-fill values such as the current date or format instructions so callers only supply the dynamic input.
When to Use
You're building chat applications. Use ChatPromptTemplate for composing multi-role prompts with variables.
Use Cases
- • Chat model prompts
- • Multi-turn templates
- • Few-shot examples
- • RAG prompts
- • Agent instructions
- • Dynamic context injection
Key Features
- ✓ Role-based messages
- ✓ Variable interpolation
- ✓ Message composition
- ✓ History support
- ✓ Dynamic system prompts
- ✓ Flexible templates
When NOT to Use
For non-chat models—use PromptTemplate.
Notes
Escape literal curly braces
Any { } that is not a variable must be doubled to {{ }}. This bites hardest when your prompt contains JSON examples or code — an unescaped brace is parsed as a template variable and raises a KeyError at invoke time. Double every literal brace or pass the content as a variable instead of inlining it.
MessagesPlaceholder for chat history
To inject prior turns, add MessagesPlaceholder(variable_name) where the history should go, then pass a list of BaseMessage objects under that key. This is how memory-backed chatbots and RememberHistory wrappers splice past messages in without flattening them into a single string.
It is a Runnable — pipe it
ChatPromptTemplate composes with the pipe operator: prompt | model | parser. invoke returns a ChatPromptValue, and to_messages() gives the raw message list for debugging. Prefer the LCEL chain over manually calling format_messages and passing the result around.
Pre-fill with partial_variables
Use .partial(...) or partial_variables to bake in values that never change per call — the current date, output-format instructions, or a fixed persona — so callers only supply the truly dynamic inputs. This keeps invoke payloads small and avoids repeating boilerplate at every call site.
Import
from langchain_core.prompts import ChatPromptTemplate
Key Parameters
| Parameter | Type | Default | Purpose |
|---|---|---|---|
| messages | List | None | List of message tuples |
Code Examples
Build a system + human prompt
from langchain_core.prompts import ChatPromptTemplate
template = ChatPromptTemplate.from_messages([
('system', 'You are a helpful assistant'),
('human', '{input}'),
])
result = template.invoke({'input': 'Hi there'})
print(result.to_messages())
Pipe into a model for a RAG chain
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
prompt = ChatPromptTemplate.from_messages([
('system', 'Answer using only this context:\n{context}'),
('human', '{question}'),
])
chain = prompt | ChatOpenAI(model='gpt-4o')
answer = chain.invoke({'context': docs, 'question': 'What changed in v0.2?'})
Inject conversation history with MessagesPlaceholder
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
prompt = ChatPromptTemplate.from_messages([
('system', 'You are a support agent.'),
MessagesPlaceholder('history'),
('human', '{input}'),
])
value = prompt.invoke({'history': past_messages, 'input': 'And my refund?'})
Common Mistakes
❌ Use ChatPromptTemplate for non-chat models
✅ Use PromptTemplate for text models
Alternatives
| Class | When to Use |
|---|---|
| PromptTemplate | For simple text templates without roles |
Related LangChain References
Browse the full LangChain API reference index to explore more classes, methods, and decorators, or start with the LangChain introduction tutorial for end-to-end context on building with ChatPromptTemplate and the wider framework.
ChatPromptTemplate FAQ
What is ChatPromptTemplate in LangChain?
Create chat prompts with role-based messages. ChatPromptTemplate is the LangChain primitive for building role-aware prompts for chat models. Where PromptTemplate produces a single string, ChatPromptTemplate produces an ordered list of messages — system, human, AI, and tool roles — each with {variable} placeholders that are filled at invoke time. This is the right abstraction for chat models, which expect a structured message list rather than one flat string. You usually build it with the from_messages classmethod, passi…
Which package provides ChatPromptTemplate?
DevShelfHub documents ChatPromptTemplate from the langchain-core package. Pin your installed LangChain version and match imports to the snippet on this page.
When should I use ChatPromptTemplate?
You're building chat applications. Use ChatPromptTemplate for composing multi-role prompts with variables.
When should I avoid using ChatPromptTemplate?
For non-chat models—use PromptTemplate.
How do I import ChatPromptTemplate in Python?
from langchain_core.prompts import ChatPromptTemplate
Where can I explore more LangChain API reference pages?
Open the LangChain API reference index on DevShelfHub to browse classes, methods, and decorators, each with runnable examples, parameters, common mistakes, and cross-links.