Message Types
A field-by-field reference for every message class in LangChain — HumanMessage, AIMessage, SystemMessage, ToolMessage, AIMessageChunk, RemoveMessage, and legacy types. Know what each field does, what breaks when you get it wrong, and how providers differ.
Quick Reference
- →Six types: SystemMessage, HumanMessage, AIMessage, ToolMessage, AIMessageChunk, RemoveMessage
- →FunctionMessage is legacy — use ToolMessage with tool_call_id
- →AIMessage.tool_calls is a list of dicts — always check before iterating
- →ToolMessage.tool_call_id must exactly match AIMessage.tool_calls[i]['id']
- →AIMessageChunk is addable — accumulate with: full = chunk if full is None else full + chunk
- →usage_metadata only arrives on the final chunk when streaming
- →RemoveMessage is a LangGraph-only type — not a chat role, it signals state deletion
The Complete Type Hierarchy
Every message class in LangChain extends BaseMessage. BaseMessage provides four fields that all types inherit: content (the payload), id (auto-assigned UUID), name (optional label for multi-agent tracing), and additional_kwargs (provider-specific overflow). Concrete types add role-specific fields on top.
All message types extend BaseMessage. FunctionMessage is legacy — use ToolMessage.
| Type | role value | Unique fields | Who creates it |
|---|---|---|---|
| SystemMessage | system | — | You, before conversation starts |
| HumanMessage | user | — | You, from user input |
| AIMessage | assistant | tool_calls, usage_metadata, response_metadata, text (v1), content_blocks (v1) | model.invoke() return value |
| ToolMessage | tool | tool_call_id, artifact, status | You, after executing a tool |
| AIMessageChunk | assistant | same as AIMessage (partial) | model.stream() yield value |
| RemoveMessage | remove | id (the message to delete) | You, in LangGraph reducers only |
| ChatMessage | any string | role | You, for custom role strings |
| FunctionMessage (legacy) | function | name | Legacy — superseded by ToolMessage |
FunctionMessage was created for OpenAI's original function-calling API before tool_call_id existed. It has no tool_call_id, so you cannot correlate results when the model calls multiple tools in parallel. Use ToolMessage instead. FunctionMessage still exists in langchain_core for backwards compatibility but should not appear in new code.