Skip to main content

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

PropertyTypeDescription
messageIdstringUnique identifier for the message
threadIdstringAssociated thread ID
roleMessageRoleRole of the sender
contentlist[MessageContent]Message content (supports multiple parts)
metadataobject (optional)Custom metadata
createdAtdatetimeCreation timestamp
modelstring (optional)Model used for generating the message
usageMessageUsage (optional)Token usage information

Message Roles

RoleDescriptionUse Case
userMessage from the userUser input, questions
assistantResponse from the AI agentAgent responses
systemSystem-level instructionsInitial prompts, context
toolOutput from a tool callTool 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:

  1. Retrieve messages using list_messages()
  2. Pass them as message_history to run() or stream()

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

FieldDescriptionExample
sourceOrigin of the message"web_chat", "api", "langchain_client"
priorityMessage priority"high", "normal", "low"
user_idUser identifier"your-user-id"
session_idSession 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

Next Steps

  • Tools - Add custom capabilities to your agents
  • Examples - See messages in real applications