Letta is the platform for building stateful agents: open AI with advanced memory that can learn and self-improve over time.
- Developer Documentation: Learn how to create agents using Python or TypeScript
- TypeScript API Reference: Complete TypeScript SDK documentation
- Agent Development Environment (ADE): A no-code UI for building stateful agents
- Letta Cloud: The fastest way to try Letta
Install the Letta TypeScript SDK:
npm install @letta-ai/letta-clientIn the example below, we'll create a stateful agent with two memory blocks. We'll initialize the human memory block with incorrect information, and correct the agent in our first message - which will trigger the agent to update its own memory with a tool call.
To run the examples, you'll need to get a LETTA_API_KEY from Letta Cloud, or run your own self-hosted server (see our guide)
import { Letta } from "@letta-ai/letta-client";
const client = new Letta({ apiKey: process.env.LETTA_API_KEY });
// const client = new Letta({ baseUrl: "http://localhost:8283" }); // if self-hosting
const agentState = await client.agents.create({
model: "openai/gpt-4.1",
embedding: "openai/text-embedding-3-small",
memory_blocks: [
{
label: "human",
value: "The human's name is Chad. They like vibe coding."
},
{
label: "persona",
value: "My name is Sam, a helpful assistant."
}
],
tools: ["web_search", "run_code"]
});
console.log("Agent created with ID:", agentState.id);
const response = await client.agents.messages.create(agentState.id, {
input: "Hey, nice to meet you, my name is Brad."
});
// the agent will think, then edit its memory using a tool
for (const message of response.messages) {
console.log(message);
}
// The content of this memory block will be something like
// "The human's name is Brad. They like vibe coding."
// Fetch this block's content with:
const human_block = await client.agents.blocks.retrieve("human", { agent_id: agentState.id });
console.log(human_block.value);Letta is built on the MemGPT research paper, which introduced the concept of the "LLM Operating System" for memory management:
- Memory Hierarchy: Agents have self-editing memory split between in-context and out-of-context memory
- Memory Blocks: In-context memory is composed of persistent editable blocks
- Agentic Context Engineering: Agents control their context window using tools to edit, delete, or search memory
- Perpetual Self-Improving Agents: Every agent has a perpetual (infinite) message history
Connect to a local Letta server instead of the cloud:
const client = new Letta({
baseUrl: "http://localhost:8283"
});Run Letta locally with Docker:
docker run \
-v ~/.letta/.persist/pgdata:/var/lib/postgresql/data \
-p 8283:8283 \
-e OPENAI_API_KEY="your_key" \
letta/letta:latestSee the self-hosting guide for more options.
Memory Management (full guide)
Memory blocks are persistent, editable sections of an agent's context window:
// Create agent with memory blocks
const agent = await client.agents.create({
memory_blocks: [
{ label: "persona", value: "I'm a helpful assistant." },
{ label: "human", value: "User preferences and info." }
]
});
// Update blocks manually
await client.agents.blocks.update("human", {
agent_id: agent.id,
value: "Updated user information"
});
// Retrieve a block
const block = await client.agents.blocks.retrieve("human", { agent_id: agent.id });Multi-agent Shared Memory (full guide)
Memory blocks can be attached to multiple agents. All agents will have an up-to-date view on the contents of the memory block -- if one agent modifies it, the other will see it immediately.
Here is how to attach a single memory block to multiple agents:
// Create shared block
const sharedBlock = await client.blocks.create({
label: "organization",
value: "Shared team context"
});
// Attach to multiple agents
const agent1 = await client.agents.create({
memory_blocks: [{ label: "persona", value: "I am a supervisor" }],
block_ids: [sharedBlock.id]
});
const agent2 = await client.agents.create({
memory_blocks: [{ label: "persona", value: "I am a worker" }],
block_ids: [sharedBlock.id]
});Sleep-time Agents (full guide)
Background agents that share memory with your primary agent:
const agent = await client.agents.create({
model: "openai/gpt-4.1",
enable_sleeptime: true // creates a sleep-time agent
});Agent File Import/Export (full guide)
Save and share agents with the .af file format:
import { readFileSync } from 'fs';
// Import agent
const file = new Blob([readFileSync('/path/to/agent.af')]);
const agent = await client.agents.importFile(file);
// Export agent
const schema = await client.agents.exportFile(agent.id);MCP Tools (full guide)
Connect to Model Context Protocol servers:
// First, create an MCP server (example: weather server)
const weatherServer = await client.mcpServers.create({
server_name: "weather-server",
config: {
mcp_server_type: "streamable_http",
server_url: "https://weather-mcp.example.com/mcp",
},
});
// List tools available from the MCP server
const tools = await client.mcpServers.tools.list(weatherServer.id);
// Create agent with MCP tool
const agent = await client.agents.create({
model: "openai/gpt-4.1",
tool_ids: [tool.id]
});Filesystem (full guide)
Give agents access to files:
import { createReadStream } from 'fs';
// Create folder and upload file
const folder = await client.folders.create({
name: "my_folder",
});
await client.folders.files.upload(createReadStream("file.txt"), folder.id);
// Attach to agent
await client.agents.folders.attach(agent.id, folder.id);Long-running Agents (full guide)
Background execution with resumable streaming:
const stream = await client.agents.messages.create(agent.id, {
messages: [
{ role: "user", content: "Analyze this dataset" }
],
background: true
});
let run_id, last_seq_id;
for await (const chunk of stream) {
run_id = chunk.run_id;
last_seq_id = chunk.seq_id;
}
// Resume if disconnected
for await (const chunk of client.runs.stream(run_id, { starting_after: last_seq_id })) {
console.log(chunk);
}Streaming (full guide)
Stream responses in real-time:
const stream = await client.agents.messages.stream(agent.id, {
messages: [
{ role: "user", content: "Hello!" }
]
});
for await (const chunk of stream) {
console.log(chunk);
}Message Types (full guide)
Agent responses contain different message types. Handle them with the message_type discriminator:
const messagesPage = await client.agents.messages.list(agent.id);
for await (const message of messagesPage) {
switch (message.message_type) {
case "user_message":
console.log("User:", message.content);
break;
case "assistant_message":
console.log("Agent:", message.content);
break;
case "reasoning_message":
console.log("Reasoning:", message.reasoning);
break;
case "tool_call_message":
console.log("Tool:", message.tool_call.name);
break;
case "tool_return_message":
console.log("Result:", message.tool_return);
break;
}
}Full TypeScript support with exported types:
import { Letta } from "@letta-ai/letta-client";
const request: Letta.CreateAgentRequest = {
model: "openai/gpt-4.1",
memory_blocks: [...]
};import { LettaError } from "@letta-ai/letta-client";
try {
await client.agents.messages.create(agentId, {...});
} catch (err) {
if (err instanceof LettaError) {
console.log(err.statusCode);
console.log(err.message);
console.log(err.body);
}
}const response = await client.agents.create({...}, {
maxRetries: 3 // Default: 2
});const response = await client.agents.create({...}, {
timeoutInSeconds: 30 // Default: 60
});const response = await client.agents.create({...}, {
headers: {
'X-Custom-Header': 'value'
}
});Letta is an open source project built by over a hundred contributors. There are many ways to get involved in the Letta OSS project!
- Join the Discord: Chat with the Letta devs and other AI developers.
- Chat on our forum: If you're not into Discord, check out our developer forum.
- Follow our socials: Twitter/X, LinkedIn, YouTube
This SDK is generated programmatically. For SDK changes, please open an issue.
README contributions are always welcome!
MIT
Legal notices: By using Letta and related Letta services (such as the Letta endpoint or hosted service), you are agreeing to our privacy policy and terms of service.