Messages
Messages are the fundamental units of communication in the CAIP Agents SDK. They represent individual interactions between users and agents within a conversation thread.
What is a Message?
A Message is a single piece of communication in a conversation. Each message has:
- Role: Who sent the message (user, assistant, system, tool)
- Content: The actual text or data of the message
- Metadata: Additional information about the message
- Timestamps: When the message was created
┌─────────────────────────────────────────────────────────┐
│ Message │
│ ┌───────────────────────────────────────────────────┐ │
│ │ role: "user" │ │
│ │ content: [{ type: "text", text: "Hello!" }] │ │
│ │ metadata: { source: "web_chat" } │ │
│ │ createdAt: "2025-10-09T10:15:00+00:00" │ │
│ └───────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
Message Properties
| Property | Type | Description |
|---|---|---|
messageId | string | Unique identifier for the message |
threadId | string | Associated thread ID |
role | MessageRole | Role of the sender |
content | list[MessageContent] | Message content (supports multiple parts) |
metadata | object (optional) | Custom metadata |
createdAt | datetime | Creation timestamp |
model | string (optional) | Model used for generating the message |
usage | MessageUsage (optional) | Token usage information |
Message Roles
| Role | Description | Use Case |
|---|---|---|
user | Message from the user | User input, questions |
assistant | Response from the AI agent | Agent responses |
system | System-level instructions | Initial prompts, context |
tool | Output from a tool call | Tool execution results |
Message Content Structure
Messages use a structured content format that supports multiple content types:
content = [
{
"type": "text",
"text": "Your message text here"
}
]
Automatic Message Storage
When you use agent.run() or agent.stream(), the SDK automatically stores both user messages and agent responses in the backend:
# This single call stores TWO messages:
# 1. User message: "What's the weather?"
# 2. Assistant message: The agent's response
response = await agent.run("What's the weather?")
You don't need to manually create messages when using the agent - it's handled automatically.
Retrieving Messages
List Messages from a Thread
Use agent.list_messages() to retrieve conversation history:
# Get messages from a thread
messages = await agent.list_messages(
thread_id="thread-id-here",
limit=20
)
print("messages: ", messages)
Using Messages for Context
The agent does not automatically load previous messages for context. You need to:
- Retrieve messages using
list_messages() - Pass them as
message_historytorun()orstream()
Building Message History
# Retrieve stored messages
messages = await agent.list_messages(
thread_id=thread_id,
limit=10
)
# Pass as message history for context
response = await agent.run(
"What did we discuss earlier?",
message_history=messages
)
Complete Context Flow
import asyncio
from caip_agents_sdk import CAIPAgentsClient
async def chat_with_context():
client = CAIPAgentsClient()
agent = client.create_agent(framework="langchain", agent_id="your-agent-id")
await agent.initialize()
# Create thread
thread = await client.create_thread(
agent_id="your-agent-id",
thread_data={"title": "Context Demo"}
)
agent.thread_id = thread.threadId
# First message (no history needed)
response1 = await agent.run("Your first message")
print(f"Agent: {response1}")
# Get message history
messages = await agent.list_messages(
thread_id=thread.threadId,
limit=10
)
# Second message WITH history
response2 = await agent.run(
"Your follow-up question",
message_history=messages
)
print(f"Agent: {response2}") # Agent remembers context
Message Content Types
Text Content
The most common content type:
content = [
{
"type": "text",
"text": "Your message text"
}
]
Message Metadata
Messages can include custom metadata for tracking and filtering:
# Messages created by the SDK include metadata automatically
{
"role": "user",
"content": [{"type": "text", "text": "Your message"}],
"metadata": {
"source": "langchain_client" # or "pydantic_ai_client"
},
"model": "gpt-4"
}
Common Metadata Fields
| Field | Description | Example |
|---|---|---|
source | Origin of the message | "web_chat", "api", "langchain_client" |
priority | Message priority | "high", "normal", "low" |
user_id | User identifier | "your-user-id" |
session_id | Session tracking | "your-session-id" |
Token Usage Tracking
For assistant messages, the SDK can track token usage:
{
"role": "assistant",
"content": [{"type": "text", "text": "Response..."}],
"usage": {
"prompt_tokens": 150,
"completion_tokens": 75,
"total_tokens": 225
}
}
Accessing Content Information
messages = await client.get_messages(
agent_id=agent_id,
thread_id=thread_id,
limit=10
)
for msg in messages:
if msg.role == "assistant" and msg.content:
print(f"Tokens used: {msg.content}")
Best Practices
1. Always Check Content Exists
# ❌ Bad - May fail if content is empty
text = msg.content[0].text
# ✅ Good - Safe access
text = msg.content[0].text if msg.content else ""
2. Handle Different Roles Appropriately
for msg in messages:
if msg.role == "user":
# Handle user input
pass
elif msg.role == "assistant":
# Handle agent response
pass
elif msg.role == "tool":
# Handle tool output
pass