Skip to content
  • Auto
  • Light
  • Dark
DiscordForumGitHubSign up
View as Markdown
Copy Markdown

Open in Claude
Open in ChatGPT

Integrating external memory storage with Letta

By default, Letta agents store memories in Letta’s built-in storage system. However, you can integrate external memory providers to store and retrieve agent memories in your own infrastructure. This gives you complete control over memory storage, search capabilities, and data persistence.

In this guide, we’ll build a conversational assistant that stores its memories in external databases. We’ll implement custom tools for five different memory providers: MongoDB, Graphiti, Weaviate, Mem0, and Zep.

To follow this tutorial, you need:

  • A free Letta account for accessing the agent development platform
  • Python (version 3.8 or later) or Node.js (version 18 or later) and a code editor
  • A free account for one of the following memory providers:

You also need API keys for Letta and your chosen memory provider.

Create a Letta Account

If you don’t have one, sign up for a free account at letta.com.

Navigate to API keys

Once logged in, click on API keys in the sidebar.

Create and copy your key

Click + Create API key, give it a descriptive name, and click Confirm. Copy the key and save it somewhere safe.

Letta API Key Navigation

Create a MongoDB Atlas account

Sign up for a free account at mongodb.com/cloud/atlas/register.

Create a free cluster

Click Build a Cluster and select the Free tier. Choose your preferred cloud provider and region and click Create Deployment. Create MongoDB Cluster

Set up database access

Next, set up connection security.

  1. On the security quickstart create a database user, then click Finish and Close.
  2. On the cluster creation card click Connect.
  3. Choose Drivers to connect to your application, and select Python as the driver.
  4. Copy the entire connection string, including the query parameters at the end. It will look like this:
mongodb+srv://<username>:<password>@cluster0.xxxxx.mongodb.net/?retryWrites=true&w=majority&appName=Cluster0

MongoDB Connection String

Configure network access (IP whitelist)

By default, MongoDB Atlas blocks all outside connections. You must grant access to the services that need to connect.

  1. Navigate to Database and Network Access in the left sidebar.
  2. On the IP Access List tab, click + ADD IP ADDRESS.
  3. For local development and testing, select Allow Access From Anywhere. This adds the IP address 0.0.0.0/0.
  4. Click Confirm.

MongoDB IP Configuration

Once you have these credentials, create a .env file in your project directory and save them as environment variables:

Terminal window
LETTA_API_KEY="..."
MONGODB_URI="mongodb+srv://username:[email protected]/?retryWrites=true&w=majority&appName=Cluster0"
MONGODB_DB_NAME="letta_memories"

First, we need to prepare the external database to store agent memories. Each provider requires different setup steps.

Before you begin, set up your development environment:

Terminal window
# Create a Python virtual environment to keep dependencies isolated
python -m venv venv
source venv/bin/activate # On Windows, use: venv\Scripts\activate

Create a requirements.txt file that lists the necessary packages for your chosen provider:

requirements.txt
letta-client
pymongo
certifi
dnspython
python-dotenv

Install the packages with the following command:

Terminal window
pip install -r requirements.txt

If your provider requires you to set up the infrastructure, initialize your database with the following code:

Create a setup.py or setup.ts file to add the code:

import os
import pymongo
import certifi
from dotenv import load_dotenv
load_dotenv()
def main():
mongodb_uri = os.getenv("MONGODB_URI")
db_name = os.getenv("MONGODB_DB_NAME")
if not all([mongodb_uri, db_name]):
print("Error: MONGODB_URI and MONGODB_DB_NAME not set")
return
print("Connecting to MongoDB...")
client = pymongo.MongoClient(mongodb_uri, tlsCAFile=certifi.where())
db = client[db_name]
collection = db["agent_memories"]
print("Creating indexes...")
collection.create_index("agent_id")
collection.create_index("user_id")
collection.create_index([("agent_id", pymongo.ASCENDING), ("timestamp", pymongo.DESCENDING)])
collection.create_index([("memory_text", "text")])
print(f"\nSetup complete!")
print(f"Database: {db_name}")
print(f"Collection: agent_memories")
client.close()
if __name__ == "__main__":
main()

Run the setup script:

Terminal window
python setup.py

A Letta tool is a Python function that your agent can call. We’ll create two tools for each provider:

  • insert_memory: Stores new memories with agent ID, user ID, and content
  • search_memory: Retrieves relevant memories filtered by agent and user

Letta automatically generates JSON schemas from your function signatures and docstrings, making these tools available to your agent. The agent can then decide when to call these functions based on the conversation.

Create a new file named tools.py or tools.ts with the implementation for your chosen provider:

import os
def insert_memory(memory_text: str, memory_agent_id: str, user_id: str = "default_user") -> str:
"""
Store a memory in MongoDB for a specific agent and user.
Args:
memory_text: The memory content to store
memory_agent_id: The ID of the agent storing this memory
user_id: The ID of the user this memory relates to
Returns:
Confirmation message with the inserted memory ID
"""
import pymongo
import certifi
from datetime import datetime
try:
mongodb_uri = os.getenv("MONGODB_URI")
db_name = os.getenv("MONGODB_DB_NAME")
if not all([mongodb_uri, db_name]):
return "Error: MongoDB credentials not configured"
client = pymongo.MongoClient(mongodb_uri, tlsCAFile=certifi.where(), serverSelectionTimeoutMS=5000)
db = client[db_name]
collection = db["agent_memories"]
memory_doc = {
"memory_text": memory_text,
"agent_id": memory_agent_id,
"user_id": user_id,
"timestamp": datetime.utcnow(),
"created_at": datetime.utcnow().isoformat()
}
result = collection.insert_one(memory_doc)
client.close()
return f"Memory stored with ID: {result.inserted_id}"
except Exception as e:
return f"Error storing memory: {str(e)}"
def search_mongodb_memory(query: str, memory_agent_id: str, limit: int = 5) -> str:
"""
Search for memories in MongoDB using text search.
Args:
query: The search query to find relevant memories
memory_agent_id: The ID of the agent whose memories to search
limit: Maximum number of results to return
Returns:
Formatted string containing matching memories
"""
import pymongo
import certifi
try:
limit = int(limit) if limit else 5
mongodb_uri = os.getenv("MONGODB_URI")
db_name = os.getenv("MONGODB_DB_NAME")
if not all([mongodb_uri, db_name]):
return "Error: MongoDB credentials not configured"
client = pymongo.MongoClient(mongodb_uri, tlsCAFile=certifi.where(), serverSelectionTimeoutMS=5000)
db = client[db_name]
collection = db["agent_memories"]
# Search using text search
results = collection.find(
{
"$and": [
{"agent_id": memory_agent_id},
{"$text": {"$search": query}}
]
},
{"score": {"$meta": "textScore"}}
).sort([("score", {"$meta": "textScore"})]).limit(limit)
memories = []
for doc in results:
memory_text = doc.get("memory_text", "")
timestamp = doc.get("created_at", "Unknown time")
memories.append(f"[{timestamp}] {memory_text}")
client.close()
# Fall back to recent memories if no text search results
if not memories:
client = pymongo.MongoClient(mongodb_uri, tlsCAFile=certifi.where(), serverSelectionTimeoutMS=5000)
db = client[db_name]
collection = db["agent_memories"]
results = collection.find(
{"agent_id": memory_agent_id}
).sort("timestamp", pymongo.DESCENDING).limit(limit)
for doc in results:
memory_text = doc.get("memory_text", "")
timestamp = doc.get("created_at", "Unknown time")
memories.append(f"[{timestamp}] {memory_text}")
client.close()
if not memories:
return "No memories found"
return "\n\n".join(memories)
except Exception as e:
return f"Error searching memories: {str(e)}"

The insert_memory function stores memories as documents in MongoDB with timestamps and metadata. The search_mongodb_memory function uses MongoDB’s text search index to find relevant memories, with a fallback to returning recent memories if no text matches are found.

Step 3: Configure an agent with custom memory

Section titled “Step 3: Configure an agent with custom memory”

Now we’ll create an agent and attach our custom memory tools to it. You need to do the following:

  • Register the tools: Upload your memory functions to Letta’s tool registry.
  • Define the agent’s persona: Provide instructions on when to store and retrieve memories.
  • Create the agent: Link the tools and configure environment variables for database access.

The agent’s persona guides its behavior, instructing it to proactively store important information and retrieve relevant context when needed.

Create a file named create_agent.py or create_agent.ts:

import os
from letta_client import Letta
from dotenv import load_dotenv
from tools import insert_memory, search_mongodb_memory
load_dotenv()
def main():
letta_api_key = os.getenv("LETTA_API_KEY")
if not letta_api_key:
print("Error: LETTA_API_KEY not found")
return
client = Letta(api_key=letta_api_key)
print("Creating memory tools...")
insert_tool = client.tools.create_from_function(
func=insert_memory,
pip_requirements=[
{"name": "pymongo"},
{"name": "certifi"},
{"name": "dnspython"}
]
)
print(f"Created tool: {insert_tool.name}")
search_tool = client.tools.create_from_function(
func=search_mongodb_memory,
pip_requirements=[
{"name": "pymongo"},
{"name": "certifi"},
{"name": "dnspython"}
]
)
print(f"Created tool: {search_tool.name}")
persona = """You are a helpful assistant with persistent memory.
- Store important information using insert_memory
- Retrieve past information using search_mongodb_memory
- Be proactive about remembering user preferences and details"""
print("Creating agent...")
agent = client.agents.create(
name="MongoDB Memory Assistant",
description="An assistant that stores memories in MongoDB",
model="openai/gpt-4o-mini",
embedding="openai/text-embedding-3-small",
memory_blocks=[{"label": "persona", "value": persona}],
tools=[insert_tool.name, search_tool.name],
include_base_tools=False,
secrets={
"MONGODB_URI": os.getenv("MONGODB_URI"),
"MONGODB_DB_NAME": os.getenv("MONGODB_DB_NAME")
}
)
print(f"\nAgent created: {agent.name}")
print(f"Agent ID: {agent.id}")
print(f"\nUse this agent ID in chat.py")
if __name__ == "__main__":
main()

Run this script once to create the agent:

Terminal window
python create_agent.py

You have now fully configured your agent with custom memory tools and environment variables.

Now we’ll interact with the agent to test memory storage and retrieval.

Create a file named chat.py:

import os
from letta_client import Letta
from dotenv import load_dotenv
load_dotenv()
def main():
letta_api_key = os.getenv("LETTA_API_KEY")
if not letta_api_key:
print("Error: LETTA_API_KEY not found")
return
letta_client = Letta(api_key=letta_api_key)
AGENT_ID = input("Enter your agent ID: ").strip()
if not AGENT_ID:
print("Error: Agent ID required")
return
print("\nMongoDB Memory Assistant")
print("Type 'exit' to quit\n")
while True:
user_input = input("You: ").strip()
if user_input.lower() in ['exit', 'quit']:
break
if not user_input:
continue
try:
response = letta_client.agents.messages.create(
agent_id=AGENT_ID,
messages=[{"role": "user", "content": user_input}]
)
for message in response.messages:
if message.message_type == 'assistant_message':
print(f"\nAssistant: {message.content}\n")
except Exception as e:
print(f"Error: {str(e)}\n")
if __name__ == "__main__":
main()

Run the chat script with your agent ID:

Terminal window
python chat.py

Try these example conversations to test memory functionality:

First conversation:

You: My name is James and I love Python programming
Assistant: Nice to meet you, James! I've stored that you love Python programming...
You: I'm working on a machine learning project
Assistant: That's exciting! I've noted that you're working on a machine learning project...

Second conversation (new session):

You: What do you remember about me?
Assistant: Let me search my memories... You're James, and you love Python programming. You're also working on a machine learning project.

The agent stores memories in your external database and retrieves them across sessions, demonstrating persistent memory storage.

You can inspect your agent’s behavior and see the memory tool calls in the Letta Agent Development Environment (ADE):

Navigate to the ADE

Log in to letta.com and click on Agents in the sidebar to view your agents.

Open your agent

Click Open in ADE on your agent to open it in the playground.

Letta Agents List

View tool calls

As you chat with your agent, expand the message details to see the tool calls being made. You’ll see when the agent calls insert_memory to store information and when it calls your provider’s search function to retrieve memories.

Tool Calls in ADE

The ADE provides visibility into your agent’s decision-making process, showing you exactly when and how it uses your custom memory tools.

Now that you’ve integrated external memory storage with Letta, you can expand on this foundation:

Custom tools

Learn more about creating custom tools for your agents.

Agent configuration

Explore advanced agent configuration options.

RAG with Letta

Build retrieval-augmented generation systems with Letta.

Multi-agent systems

Create systems with multiple specialized agents.