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-client
In 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 { LettaClient } from '@letta-ai/letta-client';
const client = new LettaClient({ token: "LETTA_API_KEY" });
// const client = new LettaClient({ baseUrl: "http://localhost:8283" }); // if self-hosting
const agentState = await client.agents.create({
model: "openai/gpt-4o-mini",
embedding: "openai/text-embedding-3-small",
memoryBlocks: [
{
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(agentState.id);
// agent-d9be...0846
const response = await client.agents.messages.create(agentState.id, {
messages: [
{
role: "user",
content: "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(agentState.id, "human");
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 LettaClient({
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:latest
See 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({
memoryBlocks: [
{ label: "persona", value: "I'm a helpful assistant." },
{ label: "human", value: "User preferences and info." }
]
});
// Modify blocks manually
await client.agents.blocks.modify(agent.id, "human", {
value: "Updated user information"
});
// Retrieve a block
const block = await client.agents.blocks.retrieve(agent.id, "human");
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({
memoryBlocks: [{ label: "persona", value: "I am a supervisor" }],
blockIds: [sharedBlock.id]
});
const agent2 = await client.agents.create({
memoryBlocks: [{ label: "persona", value: "I am a worker" }],
blockIds: [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-4o-mini",
enableSleeptime: 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.importAgentSerialized(file);
// Export agent
const schema = await client.agents.exportAgentSerialized(agent.id);
MCP Tools (full guide)
Connect to Model Context Protocol servers:
// Add tool from MCP server
const tool = await client.tools.addMcpTool("weather-server", "get_weather");
// Create agent with MCP tool
const agent = await client.agents.create({
model: "openai/gpt-4o-mini",
toolIds: [tool.id]
});
Filesystem (full guide)
Give agents access to files:
import { createReadStream } from 'fs';
// Get an available embedding config
const embeddingConfigs = await client.embeddingModels.list();
// Create folder and upload file
const folder = await client.folders.create({
name: "my_folder",
embeddingConfig: embeddingConfigs[0]
});
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.createStream(agent.id, {
messages: [{ role: "user", content: "Analyze this dataset" }],
background: true
});
let runId, lastSeqId;
for await (const chunk of stream) {
runId = chunk.runId;
lastSeqId = chunk.seqId;
}
// Resume if disconnected
for await (const chunk of client.runs.stream(runId, { startingAfter: lastSeqId })) {
console.log(chunk);
}
Streaming (full guide)
Stream responses in real-time:
const stream = await client.agents.messages.createStream(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 messageType
discriminator:
const messages = await client.agents.messages.list(agent.id);
for (const message of messages) {
switch (message.messageType) {
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.toolCall.name);
break;
case "tool_return_message":
console.log("Result:", message.toolReturn);
break;
}
}
Full TypeScript support with exported types:
import { Letta } from "@letta-ai/letta-client";
const request: Letta.CreateAgentRequest = {
model: "openai/gpt-4o-mini",
memoryBlocks: [...]
};
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'
}
});
const controller = new AbortController();
const response = await client.agents.create({...}, {
abortSignal: controller.signal
});
controller.abort();
const { data, rawResponse } = await client.agents
.create({...})
.withRawResponse();
console.log(rawResponse.headers['X-My-Header']);
const client = new LettaClient({
fetcher: yourCustomFetchImplementation
});
Works in:
- Node.js 18+
- Vercel
- Cloudflare Workers
- Deno v1.25+
- Bun 1.0+
- React Native
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.