letta/letta-api-client/SKILL.md
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.
npx skillsauth add letta-ai/skills letta-api-clientInstall 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.
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.
See getting-started.md for first-time setup and common onboarding issues.
Examples last tested with:
letta-client==1.7.1@letta-ai/[email protected]See client-setup.md for initialization patterns:
See memory-architecture.md for memory patterns:
See custom-tools.md for tool creation:
See client-side-tools.md for local tool execution:
type: "tool" responsesSee client-injection.md for server-side tool patterns:
client variable on Letta Cloudos.getenv()LETTA_AGENT_ID for self-referential toolsSee multi-user.md for scaling:
See streaming.md for real-time responses:
include_pingsConversations enable parallel sessions with shared memory:
See sleeptime.md for background memory processing:
enable_sleeptime=TrueSee agent-files.md for portability and file access:
.af filesSee tool-rules.md for constraining tool execution:
InitToolRule - Force a tool to run firstChildToolRule - Control which tools can followTerminalToolRule - End agent turn after toolpip 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")
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" });
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)| 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 |
os.getenv() for secrets - Don't pass sensitive data as function argumentsclient - Don't instantiate Letta() inside tools, use the pre-injected clientinclude_pings=True for long operations - Prevents timeout on Cloud.update() not .modify() - Method was renamedLETTA_AGENT_ID is always available - Use it in tools to reference the current agentinclude_base_tools=True - Not attached by defaultmemory_insert for shared blocks - Safest for concurrent writes (append-only)// 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
# 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": "..."})
Platform:
Documentation:
SDKs:
pip install letta-clientnpm install @letta-ai/letta-clientExamples:
tools
Test any GUI app or change on a Daytona Windows remote desktop sandbox. Use to launch a GUI program, sync a local project, take a screenshot, record a video, or share a clickable live-desktop link with a teammate. Generic — the only dependency is Daytona. For Linux, use remote-desktop-testing-linux.
tools
Test any GUI app or change on a Daytona Linux (Ubuntu xfce4 + noVNC) remote desktop sandbox. Use to launch a GUI program, sync a local project, take a screenshot, record a video, or share a clickable live-desktop link with a teammate. Generic — the only dependency is Daytona. For Windows, use remote-desktop-testing-windows.
testing
Configures Letta agents' own runtime behavior, including model, context window, system prompt, reasoning, conversation overrides, compaction settings, and compaction prompts. Use when an agent or user asks to self-modify, tune summarization/compaction, change identity/system instructions, adjust model settings, or test conversation-scoped overrides.
development
Sets Letta Desktop and Letta Code agent profile images by writing profile.png into an agent MemFS repository. Use when the user asks to add, change, generate, or fix an agent avatar, profile picture, profile image, or Desktop agent photo.