Message Types
When you interact with a Letta agent and retrieve its message history using client.agents.messages.list(), you’ll receive various types of messages that represent different aspects of the agent’s execution. This guide explains all message types and how to work with them.
Overview
Letta uses a structured message system where each message has a specific message_type field that indicates its purpose. Messages are returned as instances of LettaMessageUnion, which is a discriminated union of all possible message types.
Message Type Categories
User and System Messages
user_message
Messages sent by the user or system events packaged as user input.
Structure:
Special User Message Subtypes:
User messages can contain JSON with a type field indicating special message subtypes:
-
login- User login events -
user_message- Standard user messages -
system_alert- System notifications and alerts
system_message
Messages generated by the system, typically used for internal context.
Structure:
Note: System messages are never streamed back in responses; they’re only visible when paginating through message history.
Agent Reasoning and Responses
reasoning_message
Represents the agent’s internal reasoning or “chain of thought.”
Structure:
Fields:
reasoning- The agent’s internal thought processsource- Whether this was generated by a model with native reasoning (like o1) or via promptingsignature- Optional cryptographic signature for reasoning verification (for models that support it)
hidden_reasoning_message
Represents reasoning that has been hidden from the response.
Structure:
Fields:
state: "redacted"- The provider redacted the reasoning contentstate: "omitted"- The API chose not to include reasoning (e.g., for o1/o3 models)
assistant_message
The actual message content sent by the agent.
Structure:
Tool Execution Messages
tool_call_message
A request from the agent to execute a tool.
Structure:
Example:
tool_return_message
The result of a tool execution.
Structure:
Fields:
tool_return- The formatted return value from the toolstatus- Whether the tool executed successfullystdout/stderr- Captured output from the tool execution (useful for debugging)
Human-in-the-Loop Messages
approval_request_message
A request for human approval before executing a tool.
Structure:
See Human-in-the-Loop for more information on this experimental feature.
approval_response_message
The user’s response to an approval request.
Structure:
Working with Messages
Listing Messages
Filtering Messages by Type
Pagination
Messages support cursor-based pagination:
Message Metadata Fields
All message types include these common fields:
id- Unique identifier for the messagedate- ISO 8601 timestamp of when the message was createdmessage_type- The discriminator field identifying the message typename- Optional name field (varies by message type)otid- Offline threading ID for message correlationsender_id- The ID of the sender (identity or agent ID)step_id- The step ID associated with this messageis_err- Whether this message is part of an error step (debugging only)seq_id- Sequence ID for orderingrun_id- The run ID associated with this message
Best Practices
1. Use Type Discriminators
Always check the message_type field to safely access type-specific fields:
2. Handle Special User Messages
When displaying conversations to end users, filter out internal messages:
3. Track Tool Execution
Match tool calls with their returns using tool_call_id:
See Also
- Human-in-the-Loop - Using approval messages
- Streaming Responses - Receiving messages in real-time
- API Reference - Full API documentation