If you’ve been looking for a framework that gives your AI agents persistent, stateful memory, then this guide to Getting Started with Letta: A Beginner’s Guide to Building AI Agents is exactly what you need. Letta (formerly known as MemGPT) is an open-source framework purpose-built for creating agents that remember — not just within a single session, but across many interactions. Whether you’ve already experimented with frameworks like LangChain or are brand new to agentic AI, Letta introduces a compelling model that’s worth understanding from the ground up.
What is Letta and Why Use It?
Most AI agents are stateless — every conversation starts fresh, with no memory of what was said before. This works fine for simple Q&A bots, but quickly becomes a limitation when you need agents that can build context over time, remember user preferences, or maintain a working knowledge base.
Letta solves this with a concept called memory blocks: structured, persistent key-value stores that live inside your agent and survive between sessions. Instead of stuffing everything into a context window and hoping for the best, Letta gives agents an explicit, manageable memory architecture.
Here’s why developers choose Letta:
- Persistent memory by design — agents remember across sessions without any custom database wiring
- Tool-augmented reasoning — agents can use tools like web search or page fetching natively
- First-class SDK support — official TypeScript and Python SDKs with clean, modern APIs
- Formerly MemGPT — backed by a strong research foundation from Stanford’s MemGPT paper
Note: If you encounter documentation or community posts referring to “MemGPT,” they are describing the same project under its previous name. Letta is the current, actively maintained identity.
If you’re evaluating Letta against other multi-agent frameworks, it occupies a different niche than orchestration-first tools. Where CrewAI focuses on role-based agent collaboration and AutoGen excels at conversational multi-agent workflows, Letta’s core differentiator is its memory model for individual stateful agents.
Setting Up Your Development Environment
Letta offers three primary ways to interact with it: a CLI tool for local use, a TypeScript SDK for Node.js applications, and a Python SDK for Python-based pipelines.
Prerequisites
- Node.js 18 or higher (required for the CLI; check with
node --version) - A Letta API key (set as an environment variable)
- Python 3.8+ (if using the Python SDK)
Installing the CLI
The CLI tool is the fastest way to explore Letta locally:
npm install -g @letta-ai/letta-code
Verify the installation:
letta --version
Installing the TypeScript SDK
For building applications in Node.js or TypeScript:
npm install @letta-ai/letta-client
Installing the Python SDK
If you prefer Python:
pip install letta-client
Setting Your API Key
Both SDKs authenticate via an API key. The standard approach is to set it as an environment variable so it never appears in your source code:
# Linux / macOS
export LETTA_API_KEY="your-api-key-here"
# Windows (Command Prompt)
set LETTA_API_KEY=your-api-key-here
# Windows (PowerShell)
$env:LETTA_API_KEY="your-api-key-here"
For persistent configuration in a project, use a .env file (and make sure it’s in your .gitignore):
# .env
LETTA_API_KEY=your-api-key-here
Building Your First “Hello, World” Agent
With the SDK installed and your API key configured, you can create your first Letta agent in just a few lines.
TypeScript Example
import { Letta } from "@letta-ai/letta-client";
async function main() {
// Step 1: Initialize the client
const client = new Letta({ apiKey: process.env.LETTA_API_KEY });
// Step 2: Create an agent with a model, memory, and tools
const agent = await client.agents.create({
model: "gpt-4o",
memory_blocks: [
{
label: "persona",
value: "You are a helpful assistant with a friendly, concise tone.",
},
{
label: "human",
value: "The user is a developer learning about Letta.",
},
],
tools: [],
});
console.log("Agent created with ID:", agent.id);
// Step 3: Send a message to the agent
const response = await client.agents.messages.create(agent.id, {
input: "Hello! Can you introduce yourself?",
});
console.log("Agent response:", response);
}
main();
Run it:
npx ts-node index.ts
Python Example
import os
from letta_client import Letta
def main():
# Step 1: Initialize the client
client = Letta(api_key=os.environ["LETTA_API_KEY"])
# Step 2: Create an agent
agent = client.agents.create(
model="gpt-4o",
memory_blocks=[
{"label": "persona", "value": "You are a helpful assistant with a friendly, concise tone."},
{"label": "human", "value": "The user is a developer learning about Letta."},
],
tools=[],
)
print(f"Agent created with ID: {agent.id}")
# Step 3: Send a message
response = client.agents.messages.create(
agent.id,
input="Hello! Can you introduce yourself?"
)
print(f"Agent response: {response}")
if __name__ == "__main__":
main()
Run it:
python main.py
Both examples follow the same three-step pattern: initialize the client → create the agent → send a message. This pattern is the backbone of every Letta application you’ll build.
Core Letta Concepts: Agents, Tasks, and Tools
Understanding the three fundamental building blocks will help you design more capable agents.
Agents
An agent is the primary stateful object in Letta. When you call client.agents.create(), Letta returns an agent state that includes:
- A unique agent ID used for all subsequent interactions
- The assigned model (e.g., GPT-4o, Claude, etc.)
- The initial memory blocks you configured
- The tools the agent has access to
Critically, once an agent is created, its ID persists. You can store this ID in a database and resume conversations with the same agent days or weeks later — its memory will still be intact.
Memory Blocks
Memory blocks are labeled key-value pairs injected into the agent’s context at creation time. Common patterns include:
| Label | Purpose |
|---|---|
persona | The agent’s identity and behavioral guidelines |
human | Information about the user the agent is talking to |
facts | A knowledge base the agent should always have access to |
system_notes | Internal operational instructions |
Unlike a simple system prompt, memory blocks are designed to be updated over time. As the agent learns new things about the user or accumulates knowledge, those blocks can evolve — giving you a foundation for genuinely adaptive agents.
Tools
Tools are pre-defined capabilities you grant to an agent at creation time. They’re specified as string names in the tools array. For example:
const agent = await client.agents.create({
model: "gpt-4o",
memory_blocks: [
{ label: "persona", value: "You are a research assistant." },
],
tools: ["web_search", "fetch_webpage"],
});
An agent with web_search can query the internet during a conversation. An agent with fetch_webpage can retrieve and read the content of a URL. Tools transform your agent from a pure language model into an entity that can take real-world actions.
This tool-augmentation pattern is conceptually similar to how tool-calling works in other frameworks — if you’ve used AutoGen, the mental model will feel familiar.
Messages
Messages are how you interact with a running agent. Each call to client.agents.messages.create() sends user input to the agent and returns one or more response messages. The agent’s internal reasoning, tool calls, and final reply are all delivered through this message interface.
Running and Testing Your Agent
Persisting Agent IDs
A key practice when working with Letta is saving your agent ID after creation. Since agents are stateful, you typically create them once and reuse them:
import os
import json
from letta_client import Letta
AGENT_CONFIG_FILE = "agent_config.json"
def get_or_create_agent(client):
# Load existing agent ID if available
if os.path.exists(AGENT_CONFIG_FILE):
with open(AGENT_CONFIG_FILE, "r") as f:
config = json.load(f)
print(f"Resuming agent: {config['agent_id']}")
return config["agent_id"]
# Otherwise, create a new agent
agent = client.agents.create(
model="gpt-4o",
memory_blocks=[
{"label": "persona", "value": "You are a persistent assistant that remembers past conversations."},
{"label": "human", "value": "The user is a developer."},
],
tools=["web_search"],
)
# Save the agent ID for future sessions
with open(AGENT_CONFIG_FILE, "w") as f:
json.dump({"agent_id": agent.id}, f)
print(f"Created new agent: {agent.id}")
return agent.id
def main():
client = Letta(api_key=os.environ["LETTA_API_KEY"])
agent_id = get_or_create_agent(client)
# Interactive loop
while True:
user_input = input("You: ").strip()
if user_input.lower() in ("exit", "quit"):
break
response = client.agents.messages.create(agent_id, input=user_input)
print(f"Agent: {response}\n")
if __name__ == "__main__":
main()
This pattern is the foundation of a production-ready Letta application: create once, interact many times, resume anytime.
Common Mistakes to Avoid
Wrong package for the job. There are two distinct NPM packages:
@letta-ai/letta-code— the CLI tool for local exploration@letta-ai/letta-client— the SDK for building applications
They are not interchangeable. If you’re writing application code, you want letta-client.
Missing API key. The SDK will fail silently or throw an authentication error if LETTA_API_KEY is not set. Always validate your environment variable is present before running:
echo $LETTA_API_KEY
Node.js version. The CLI requires Node.js 18+. If it fails to run, check your version:
node --version
Frequently Asked Questions
What is Letta, and how is it different from MemGPT?
Letta is the current name of the project formerly known as MemGPT. The framework was rebranded to Letta while maintaining the same core architecture — persistent, memory-augmented AI agents. If you see older tutorials referencing MemGPT, they are describing the same underlying system. All new development should use the Letta packages and documentation.
Do I need to use the CLI, or can I just use the SDK?
They serve different purposes. The CLI (@letta-ai/letta-code) is useful for quick local testing and exploration without writing code. The SDK (@letta-ai/letta-client or letta-client for Python) is for building applications that create and interact with agents programmatically. Most production use cases will rely on the SDK.
How does Letta’s memory differ from just using a long system prompt?
A long system prompt passes everything to the model on every request, which is expensive and limited by the context window. Letta’s memory blocks are structured and labeled, making them easier to update selectively. As agents accumulate knowledge, only the relevant memory blocks need to change — you don’t have to rewrite the entire prompt. This scales far better for long-running agents.
Can I use Letta with models other than GPT-4o?
The model parameter in client.agents.create() accepts different model identifiers, so yes — you can specify other supported models. The exact list of supported models depends on your Letta API plan and configuration. Check the official Letta documentation for the current model roster.
Is Letta suitable for multi-agent systems?
Letta’s primary strength is stateful individual agents, not multi-agent orchestration. If you need multiple agents collaborating on tasks, you may want to combine Letta with an orchestration layer, or consider a framework like CrewAI for role-based agent workflows. Letta and orchestration frameworks are complementary rather than competing.