Agent skill
letta-api-client
Build applications with the Letta API — a model-agnostic, stateful API for building persistent agents with memory and long-term learning. Covers SDK patterns for Python and TypeScript. Includes 24 working code examples.
Install this agent skill to your Project
npx add-skill https://github.com/letta-ai/skills/tree/main/letta/letta-api-client
SKILL.md
Letta API Client Skill
Build applications on top of the Letta API — a model-agnostic, stateful API for building persistent agents with memory and long-term learning. The Letta API powers Letta Code and the Learning SDK. This skill covers the core patterns for creating agents, managing memory, building custom tools, and handling multi-user scenarios.
When to Use This Skill
- Building applications that need persistent, stateful AI agents
- Creating chatbots, assistants, or autonomous agents with memory
- Integrating Letta into existing web/mobile applications
- Building multi-user applications where each user has their own agent
- Understanding the API layer that Letta Code and Learning SDK are built on
Quick Start
See getting-started.md for first-time setup and common onboarding issues.
SDK Versions Tested
Examples last tested with:
- Python SDK:
letta-client==1.7.1 - TypeScript SDK:
@letta-ai/letta-client@1.7.1
Core Concepts
1. Client Setup
See client-setup.md for initialization patterns:
- Letta Cloud vs self-hosted connections
- Environment variable management
- Singleton patterns for web frameworks
2. Memory Architecture
See memory-architecture.md for memory patterns:
- Core Memory Blocks: Always in-context (persona, human, custom blocks)
- Archival Memory: Large corpus with semantic search
- Conversation History: Searchable message history
- Shared Blocks: Multi-agent coordination
3. Custom Tools
See custom-tools.md for tool creation:
- Simple function tools with auto-generated schemas
- Tools with environment variable secrets
- BaseTool class for complex schemas
- Sandboxed execution requirements
4. Client-Side Tools
See client-side-tools.md for local tool execution:
- Execute tools on your machine while agent runs on Letta API
- How Letta Code runs Bash/Read/Write locally
- Approval-based flow with
type: "tool"responses - Access local files, databases, and private APIs
5. Client Injection & Secrets
See client-injection.md for server-side tool patterns:
- Pre-injected
clientvariable on Letta Cloud - Building custom memory tools that modify agent state
- Agent secrets via
os.getenv() LETTA_AGENT_IDfor self-referential tools
6. Multi-User Patterns
See multi-user.md for scaling:
- One agent per user (personalization)
- Shared agent with Conversations API
- Identity system for user context
7. Streaming
See streaming.md for real-time responses:
- Basic SSE streaming
- Long-running operations with
include_pings - Background execution and resumable streams
8. Conversations
Conversations enable parallel sessions with shared memory:
- Thread-safe concurrent messaging (agents.messages.create is NOT thread-safe)
- Shared memory blocks across all conversations
- Separate context windows per conversation
- Use for: same user with multiple parallel tasks, multi-threaded applications
9. Sleeptime Agents
See sleeptime.md for background memory processing:
- Enable with
enable_sleeptime=True - Background agent refines memory between conversations
- Good for agents that learn over time
10. Agent Files & Folders
See agent-files.md for portability and file access:
- Export/import agents with
.affiles - Attach folders to give agents document access
- Migration checklist for moving agents
11. Tool Rules
See tool-rules.md for constraining tool execution:
InitToolRule- Force a tool to run firstChildToolRule- Control which tools can followTerminalToolRule- End agent turn after tool- Sequential pipelines and approval workflows
Quick Reference
Python SDK
pip install letta-client
from letta_client import Letta
# Cloud
client = Letta(api_key="LETTA_API_KEY")
# Self-hosted
client = Letta(base_url="http://localhost:8283")
TypeScript SDK
npm install @letta-ai/letta-client
import { Letta } from "@letta-ai/letta-client";
// Cloud
const client = new Letta({ apiKey: process.env.LETTA_API_KEY });
// Self-hosted
const client = new Letta({ baseUrl: "http://localhost:8283" });
Examples
See the examples/ directory for runnable code:
Python:
01_basic_client.py- Client initialization02_create_agent.py- Agent creation with memory blocks03_custom_tool_simple.py- Basic custom tool04_custom_tool_secrets.py- Tool with environment variables05_send_message.py- Basic messaging06_send_message_stream.py- Streaming responses07_multi_user.py- Multi-user patterns08_archival_memory.py- Archival memory operations09_shared_blocks.py- Multi-agent shared memory10_conversations.py- Parallel sessions with conversations11_client_injection.py- Custom memory tools with injected client12_tool_rules.py- Constraining tool execution order13_client_side_tools.py- Execute tools locally (like Letta Code)
TypeScript:
01_basic_client.ts- Client initialization02_create_agent.ts- Agent creation03_send_message.ts- Basic messaging04_send_message_stream.ts- Streaming05_nextjs_singleton.ts- Next.js pattern06_multi_user.ts- Multi-user patterns07_conversations.ts- Parallel sessions08_custom_tool.ts- Custom tools with secrets09_archival_memory.ts- Long-term storage10_shared_blocks.ts- Multi-agent shared memory11_client_injection.ts- Custom memory tools12_tool_rules.ts- Tool execution order13_client_side_tools.ts- Execute tools locally (like Letta Code)
Troubleshooting
| Error | Cause | Fix |
|---|---|---|
| 401 Unauthorized | Invalid or missing API key | Check LETTA_API_KEY env var |
| 422 Validation Error | Missing required field | Add model, embedding, or memory_blocks |
| Tool not found | Tool not attached to agent | client.agents.tools.attach(agent_id, tool_id) |
os.getenv() returns None |
Secret not configured | Add to agent via secrets parameter |
| 524 Timeout | Long operation without pings | Add include_pings=True to streaming |
| Agent not responding | Model issue or empty response | Check for assistant_message type in response |
| Memory block not updating | Looking at wrong agent | Verify agent_id matches |
| Import error in tool | Top-level import | Move imports inside function body |
Key Gotchas
- Imports in tools must be inside the function - Tools run in a sandbox without access to top-level imports
- Use
os.getenv()for secrets - Don't pass sensitive data as function arguments - On Cloud, use injected
client- Don't instantiateLetta()inside tools, use the pre-injected client - Memory blocks are character-limited - Use archival memory for large data
- Streaming requires
include_pings=Truefor long operations - Prevents timeout on Cloud - SDK 1.0 uses
.update()not.modify()- Method was renamed LETTA_AGENT_IDis always available - Use it in tools to reference the current agent- Archival tools need
include_base_tools=True- Not attached by default - Use
memory_insertfor shared blocks - Safest for concurrent writes (append-only) - Tool docstrings require Args section - Parameters need descriptions or schema generation fails
TypeScript SDK Notes
// Client initialization uses baseURL (not baseUrl)
const client = new Letta({ apiKey: "...", baseURL: "http://localhost:8283" });
// Block API: positional args changed
client.agents.blocks.attach(blockId, { agent_id }); // blockId is first
client.agents.blocks.retrieve(blockLabel, { agent_id }); // label is first
// Passages.create returns array
const passages = await client.agents.passages.create(agentId, { text: "..." });
const passage = passages[0];
// Content can be string | array - use type guard
const content = typeof msg.content === "string" ? msg.content : JSON.stringify(msg.content);
// Conversations API returns streams by default
const stream = await client.conversations.messages.create(convId, { messages: [...] });
for await (const chunk of stream) { ... }
// Tool rule types
{ type: "run_first", tool_name: "..." } // InitToolRule
{ type: "constrain_child_tools", tool_name: "...", children: [...] } // ChildToolRule
{ type: "exit_loop", tool_name: "..." } // TerminalToolRule
Quick Reference
# Client
client = Letta(api_key=os.getenv("LETTA_API_KEY"))
# Create agent
agent = client.agents.create(
model="anthropic/claude-sonnet-4-5-20250929",
embedding="openai/text-embedding-3-small",
memory_blocks=[{"label": "persona", "value": "..."}],
include_base_tools=True, # archival memory tools
enable_sleeptime=True, # background memory processing
)
# Send message
response = client.agents.messages.create(
agent_id=agent.id,
messages=[{"role": "user", "content": "Hello"}]
)
# Stream response
stream = client.agents.messages.stream(
agent_id=agent.id,
messages=[{"role": "user", "content": "Hello"}],
stream_tokens=True,
include_pings=True, # prevent timeout
)
# Create tool
tool = client.tools.create(source_code="def my_tool(x: str) -> str: ...")
client.agents.tools.attach(agent_id=agent.id, tool_id=tool.id)
# Memory blocks
client.agents.blocks.retrieve(agent_id=agent.id, block_label="persona")
client.agents.blocks.update(agent_id=agent.id, block_label="persona", value="...")
# Folders
folder = client.folders.create(name="docs")
client.folders.files.upload(file=f, folder_id=folder.id)
client.agents.folders.attach(agent_id=agent.id, folder_id=folder.id)
# Conversations (parallel sessions)
conv = client.conversations.create(agent_id=agent.id)
stream = client.conversations.messages.create(conv.id, messages=[...])
# Agent secrets (for tools)
client.agents.update(agent_id=agent.id, secrets={"API_KEY": "..."})
Resources
Platform:
- Letta Cloud (ADE) - Agent Development Environment
- API Keys - Get your API key
Documentation:
- Letta Docs - Full documentation
- Agents Guide - Agent concepts
- Memory Blocks - Memory architecture
- Custom Tools - Tool creation
- Streaming - Real-time responses
- Multi-User - Scaling patterns
SDKs:
- Python SDK -
pip install letta-client - TypeScript SDK -
npm install @letta-ai/letta-client
Examples:
- Chatbot Example - Full app example
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
yelp-search
Search Yelp for local businesses, get contact info, ratings, and hours. Use when finding services (cleaners, groomers, restaurants, etc.), looking up business phone numbers to text, or checking ratings before booking. Triggers on queries about finding businesses, restaurants, services, or "look up on Yelp".
extracting-pdf-text
Extract text from PDFs for LLM consumption. Use when processing PDFs for RAG, document analysis, or text extraction. Supports API services (Mistral OCR) and local tools (PyMuPDF, pdfplumber). Handles text-based PDFs, tables, and scanned documents with OCR.
morph-warpgrep
Integration guide for Morph's WarpGrep (fast agentic code search) and Fast Apply (10,500 tok/s code editing). Use when building coding agents that need fast, accurate code search or need to apply AI-generated edits to code efficiently. Particularly useful for large codebases, deep logic queries, bug tracing, and code path analysis.
obsidian-cli
Work with Obsidian vaults using the official Obsidian CLI. Read, create, append, search, and manage notes, daily notes, properties, tags, tasks, sync, and more from the terminal. Use when the user mentions Obsidian, notes, vault, daily notes, or when working with markdown knowledge bases. Requires Obsidian desktop app running with CLI enabled in Settings > General.
mcp-builder
Guide for creating high-quality MCP (Model Context Protocol) servers that enable LLMs to interact with external services through well-designed tools. Use when building MCP servers to integrate external APIs or services, whether in Python (FastMCP) or Node/TypeScript (MCP SDK).
google-workspace
Connect to Gmail and Google Calendar via OAuth 2.0. Use when users want to search/read emails, create drafts, search calendar events, check availability, or schedule meetings. Triggers on queries about email, inbox, calendar, schedule, or meetings.
Didn't find tool you were looking for?