letta/conversations/SKILL.md
Guide for using the Letta Conversations API to manage isolated message threads on agents. Use when building multi-user chat applications, session management, or any scenario requiring separate conversation contexts on a single agent.
npx skillsauth add letta-ai/skills Letta Conversations APIInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
The Conversations API allows multiple isolated message threads on a single agent. Each conversation maintains its own message history while sharing the agent's memory blocks and tools.
| Concept | Description |
|---------|-------------|
| Conversation | An isolated message thread on an agent (conv-xxx ID) |
| Isolation | Each conversation has separate message history |
| Shared State | Memory blocks and tools are shared across conversations |
| In-Context Messages | Messages currently in the conversation's context window |
from letta_client import Letta
client = Letta(base_url="https://api.letta.com", api_key="your-key")
conversation = client.conversations.create(agent_id="agent-xxx")
# conversation.id -> "conv-xxx"
stream = client.conversations.messages.create(
conversation_id=conversation.id,
messages=[{"role": "user", "content": "Hello!"}],
)
for msg in stream:
if hasattr(msg, "message_type") and msg.message_type == "assistant_message":
print(msg.content)
messages = client.conversations.messages.list(
conversation_id=conversation.id,
limit=50, # Optional: default 100
after="message-xxx", # Optional: cursor for pagination
before="message-yyy", # Optional: cursor for pagination
)
conversations = client.conversations.list(
agent_id="agent-xxx",
limit=50, # Optional
after="conv-xxx", # Optional: cursor for pagination
)
conv = client.conversations.retrieve(conversation_id="conv-xxx")
# conv.in_context_message_ids -> list of message IDs in context window
| Method | Endpoint | Description |
|--------|----------|-------------|
| POST | /v1/conversations?agent_id=xxx | Create a conversation |
| GET | /v1/conversations?agent_id=xxx | List conversations |
| GET | /v1/conversations/{conversation_id} | Get a conversation |
| GET | /v1/conversations/{conversation_id}/messages | List messages |
| POST | /v1/conversations/{conversation_id}/messages | Send message (streams response) |
| POST | /v1/conversations/{conversation_id}/stream | Resume a background stream |
# Create conversation
curl -X POST "https://api.letta.com/v1/conversations?agent_id=agent-xxx" \
-H "Authorization: Bearer $LETTA_API_KEY" \
-H "Content-Type: application/json"
# Send message (streaming response)
curl -X POST "https://api.letta.com/v1/conversations/conv-xxx/messages" \
-H "Authorization: Bearer $LETTA_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: text/event-stream" \
-d '{"messages": [{"role": "user", "content": "Hello!"}]}'
class Conversation:
id: str # "conv-xxx"
agent_id: str # Associated agent ID
created_at: datetime # Creation timestamp
summary: Optional[str] # Optional conversation summary
in_context_message_ids: List[str] # Message IDs in context window
# Each user gets their own conversation
user_conversations = {}
def get_or_create_conversation(user_id: str, agent_id: str) -> str:
if user_id not in user_conversations:
conv = client.conversations.create(agent_id=agent_id)
user_conversations[user_id] = conv.id
return user_conversations[user_id]
def send_user_message(user_id: str, agent_id: str, message: str):
conv_id = get_or_create_conversation(user_id, agent_id)
return client.conversations.messages.create(
conversation_id=conv_id,
messages=[{"role": "user", "content": message}],
)
def get_all_messages(conversation_id: str):
all_messages = []
after = None
while True:
batch = client.conversations.messages.list(
conversation_id=conversation_id,
limit=100,
after=after,
)
if not batch:
break
all_messages.extend(batch)
after = batch[-1].id
return all_messages
messages.create endpoint always streams responsesafter/before cursors for efficient pagination, not offsetsThis skill includes two example scripts in the scripts/ directory:
conversations_demo.py - Comprehensive demo showing all API features
conversations_cli.py - Interactive TUI for managing conversations
# Run the demo script
LETTA_API_KEY=your-key uv run letta/conversations/scripts/conversations_demo.py
# Run the interactive CLI
LETTA_API_KEY=your-key uv run letta/conversations/scripts/conversations_cli.py
# CLI with specific agent
LETTA_API_KEY=your-key uv run letta/conversations/scripts/conversations_cli.py --agent agent-xxx
.items to access the list: client.agents.list().itemsapi_key, not token: Letta(base_url=..., api_key=...)list()) to complete the requesttesting
Navigates archived ChatGPT or Claude-style conversation exports and a MemFS reference archive on demand. Use when recalling what a past assistant knew, searching old conversations, rendering specific chats, seeding reference memory from export sidecars, or mining historical context without doing a full import.
testing
Migrates deprecated Letta Filesystem folders/files to MemFS using markdown document corpora, chunking, local lexical search, and QMD semantic search via the memfs-search skill. Use when replacing folders.files.upload, working with PDFs or document QA, or emulating open_file, grep_file, and search_file behavior.
data-ai
Configures Letta agent compaction settings and custom summarization prompts. Use when a user asks to change an agent's compaction prompt, improve summaries after context eviction, tune sliding-window or all-message compaction, or design companion/coding-agent continuity summaries.
development
Semantic search over agent memory files. Use when you need to find conceptually related memory blocks, discover forgotten reference files, check what you already know before creating new memory, or search beyond exact keyword matching. Currently supports QMD (local, no API keys).