AI agents thrive on the ability to retain context, learn from past interactions, and deliver consistent responses over time. Imagine a customer service AI agent employed by a major e-commerce platform. Without persistent memory, this agent would repeatedly request customers to provide their order numbers, shipping preferences, and previous issues during each interaction. Such a scenario would undoubtedly lead to customer frustration, as they would feel unrecognized and burdened with the need to constantly re-establish context. In contrast, with long-term memory capabilities, the agent can effortlessly recall past interactions, grasp customer preferences, and maintain continuity across multiple support sessions, even if those conversations extend over several days or weeks.
Utilizing the Letta Developer Platform, developers can craft stateful agents equipped with advanced context management features, including compaction, context rewriting, and context offloading. The Letta API allows for the creation of agents that are not only long-lived but also capable of executing complex tasks without the concerns of context overflow or model lock-in. Moreover, developers have the option to self-host the Letta API within their own virtual private cloud (VPC) and persist agent states in Amazon Aurora PostgreSQL-Compatible Edition. Letta efficiently stores all state information, encompassing memories, tools, and messages, in normalized tables, facilitating data queries across agents and enabling state portability across various model providers.
In this article, we will guide you through the process of setting up Amazon Aurora Serverless as a scalable and highly available PostgreSQL database repository for Letta’s long-term memory storage. We will detail how to create an Aurora cluster in the cloud, configure Letta for connectivity, and deploy agents that persist their memory to Aurora. Additionally, we will explore methods to query the database directly to inspect agent states.
Solution overview
Letta operates within a Docker™ container on your local machine, establishing a connection to Aurora PostgreSQL over the internet. Aurora is responsible for storing agent configurations, memories, and conversation histories in PostgreSQL tables, utilizing the standard PostgreSQL wire protocol on port 5432.
Aurora PostgreSQL
The integration of Aurora PostgreSQL introduces essential capabilities for production-ready AI agent memory systems. Notably, Aurora PostgreSQL supports the pgvector extension, which facilitates efficient similarity searches across millions of vector embeddings—numerical representations of past conversations. This feature enables AI agents to swiftly retrieve contextually relevant information.
Aurora PostgreSQL boasts sub-second query latency for memory lookups and accommodates up to 15 read replicas, ensuring efficient scaling of memory retrieval operations. Consequently, AI agents can access their memories rapidly, even during peak loads. The database’s storage capacity extends up to 256 TB, providing ample space for extensive memory archives and long-term conversation histories.
Reliability is a hallmark of Aurora, underscored by its comprehensive durability features. The database employs six-way replication across three Availability Zones, significantly mitigating the risk of data loss. Furthermore, agents’ memories are safeguarded by point-in-time recovery capabilities, offering up to 35 days of backup retention. The self-healing storage system continuously conducts data integrity checks, ensuring the consistency of agents’ memory states.
For cost optimization, Aurora Serverless automatically adjusts its capacity based on workload, adeptly managing thousands of concurrent agent connections. Storage scaling is dynamic, expanding from 10 GiB to 256 TB without any downtime, ensuring that agents do not run out of memory space as they learn and interact.
Letta
Letta conceptualizes agents as persistent services, maintaining state server-side and allowing agents to operate independently, communicate with one another, and continue processing even when clients are offline. For production workloads, Letta supports horizontal scaling using Kubernetes, featuring configurable worker processes and database connection pooling. The background execution mode facilitates resumable streams that endure disconnects and enable load balancing by resuming streams initiated by other instances.
Production deployments accommodate multi-tenancy with unlimited agents on Pro and Enterprise plans, rendering Letta suitable for large-scale customer service and multi-user applications. The platform encompasses enterprise features such as SAML/OIDC SSO, role-based access control, and tool sandboxing, alongside telemetry and performance monitoring for tracking system metrics. Although this article illustrates a local setup, production deployments typically leverage cloud platforms with HTTPS access and security controls.
Walkthrough overview
In the subsequent sections, we will outline the steps to construct the following resources:
- An Aurora serverless cluster featuring the pgvector extension for embedding storage
- A security group configuration that permits your IP address to connect on port 5432
- A Letta Docker container configured with
LETTA_PG_URIpointing to Aurora - Functional AI agents that persist all state to Aurora
Our solution utilizes Aurora Serverless with minimal capacity settings, ideal for development and testing environments. While we will use an internet-exposed database for simplicity in this post, best practices in production recommend placing it within a private subnet, accompanied by a security group that restricts connections to your application.
Prerequisites
Before proceeding, ensure you have the following:
Set up Aurora Serverless
This section illustrates how to create an Aurora PostgreSQL cluster configured for external access from your local machine.
Create the Aurora cluster
To establish the Aurora cluster, follow these steps:
- On the Amazon RDS console, navigate to Databases.
- Select Create database.
- For Engine options, choose Aurora (PostgreSQL Compatible).
- For Engine version, select Aurora PostgreSQL (Compatible with PostgreSQL 17.4). This is the default for major version 17, or you may opt for your preferred version.
- Under Templates, select Dev/Test to optimize for lower costs.
- Under Settings, configure the following:
- For DB cluster identifier, enter a name, such as
letta-aurora-cluster. - For Master username, retain the default (
postgres). - For Credentials management, select Self managed.
- For Master password, provide an alphanumeric password.
- For DB cluster identifier, enter a name, such as
- Under Instance configuration, select Serverless v2.
- For Capacity range, set the following:
- Minimum capacity (ACUs): 0.5
- Maximum capacity (ACUs): 1
Aurora Capacity Units (ACUs) measure database compute capacity in Aurora Serverless. Each ACU comprises approximately 2 GiB of memory, along with corresponding CPU and networking capabilities. For instance, 0.5 ACUs provide 1 GiB of memory, while 32 ACUs yield 64 GiB of memory with proportional compute resources. Your Aurora database charges are based on ACU usage per second. For development and testing, starting with 0.5–1 ACU suffices. Production workloads typically necessitate higher ACU ranges based on your application’s memory and processing requirements. Aurora Serverless dynamically adjusts capacity within your specified ACU range based on actual database load, even scaling down to zero ACUs to avoid compute charges during idle periods.
- Under Connectivity, configure the following:
- For Public access, select Yes.
- For VPC security group (firewall), choose Create new.
- For New VPC security group name, enter a name, such as
letta-aurora-sg.
- Select Create database.
While Aurora creates the cluster, you can proceed to configure the security group.
Configure security group access
Aurora clusters necessitate security group configuration to permit external connections. By default, the security group blocks all incoming traffic. This solution creates an Amazon Elastic Compute Cloud (Amazon EC2) security group.
To configure the security group, follow these steps:
- On the Amazon EC2 console, navigate to Network & Security and select Security Groups.
- On the Inbound rules tab, select the security group associated with your Aurora cluster (
letta-aurora-sg). - Select Edit inbound rules.
- Select Add rule and configure the following:
- For Type, select PostgreSQL.
- For Protocol, retain the default (TCP).
- For Port range, keep the default (5432).
- For Source, choose one of the following options:
- My IP: Automatically detects and allows your current IP address (recommended for testing).
- Custom: Enter a specific IP address with a
/32suffix for single IP access.
- Select Save rules.
Your security configuration now permits PostgreSQL connections from your IP address to the Aurora cluster.
Retrieve cluster endpoint
Once the cluster status indicates Available, retrieve the connection endpoint:
- On the Amazon RDS console, navigate to Databases.
- Select your cluster.
- On the Connectivity & security tab, locate the Endpoints section.
- Copy the writer instance endpoint, which resembles
letta-aurora-cluster.cluster-abc123def456.us-east-1.rds.amazonaws.com. This endpoint will be utilized to construct the PostgreSQL connection string.
Install pgvector extension
Letta employs the pgvector extension to store vector embeddings for agent memory. It is necessary to manually enable this extension prior to connecting Letta.
To install pgvector, follow these steps:
- Connect to Aurora using the psql command line tool:
psql -h letta-aurora-cluster.cluster-abc123def456.us-east-1.rds.amazonaws.com -U postgres -d postgres - When prompted, enter the primary password configured during cluster creation. Upon a successful connection, the PostgreSQL prompt will appear:
postgres=> - Create the pgvector extension:
CREATE EXTENSION vector; - Verify the installation:
SELECT extname, extversion FROM pg_extension WHERE extname = 'vector'; -- The output should resemble the following (version number may vary): extname | extversion ---------+------------ vector | 0.8.0 - Exit psql:
Your Aurora cluster is now prepared for Letta connections.
Connect Letta to Aurora
With Aurora configured, you can now execute Letta and connect it to your cluster using the LETTA_PG_URI environment variable. Letta’s Docker image automatically detects the external PostgreSQL connection and performs database migrations upon startup.
Construct connection string
The LETTA_PG_URI follows the standard PostgreSQL connection string format:
postgresql://USERNAME:PASSWORD@ENDPOINT:PORT/DATABASE
Using the values from your Aurora cluster, construct the string as follows:
postgresql://postgres:TestPassword2025@letta-aurora-cluster.cluster-abc123def456.us-east-1.rds.amazonaws.com:5432/postgres
Ensure to replace the endpoint and password with your actual cluster endpoint and password.
Run Letta with Docker
To initiate Letta connected to Aurora, execute the Docker container with your Aurora connection string and OpenAI API key:
docker run -p 8283:8283
-e LETTA_PG_URI='postgresql://postgres:YOUR_PASSWORD@YOUR_CLUSTER_ENDPOINT:5432/postgres'
-e OPENAI_API_KEY='your-openai-api-key'
letta/letta:latest
Substitute your Aurora primary password, cluster endpoint, and OpenAI key accordingly. Monitor the migration output; you should observe the following:
INFO [alembic.runtime.migration] Context impl PostgresqlImpl.
INFO [alembic.runtime.migration] Will assume transactional DDL.
INFO [alembic.runtime.migration] Running upgrade -> 9a505cc7eca9, Create a baseline migrations
This confirms that Letta has detected the PostgreSQL connection and established the necessary database schema. When you see the following output, the server is ready:
INFO: Application startup complete.
INFO: Uvicorn running on http://0.0.0.0:8283
Letta is now operational and connected to Aurora, with agent data persisting to your Aurora cluster instead of local storage.
Create and test an agent
To validate the connection, create an agent and send it a message. Choose either Python or TypeScript based on your preferred programming language.
Using Python
For Python, follow these steps:
- Create a Python virtual environment and install the Letta Python client:
python -m venv venv source venv/bin/activate # On Windows: venv/Scripts/activate pip install letta-client - Create a Python script named
test_aurora_agent.py: - Execute the script:
You should observe output similar to the following:
postgres=>
Using TypeScript
For TypeScript, follow these steps:
- Initialize a Node.js project and install dependencies:
- Update your package.json to utilize ES modules by adding the following:
- Create a TypeScript script named
test_aurora_agent.ts:postgres=> - Run the script:
You should see output similar to the following:
postgres=>
The agent response confirms that Letta successfully created an agent and processed your message. This data is now stored in Aurora.
View agent state in Aurora
Having agents operational and storing data in Aurora allows you to connect directly to the database to examine how Letta organizes agent state, memory, and conversations.
Connect to Aurora
Using the same psql connection from earlier, connect to Aurora:
psql -h letta-aurora-cluster.cluster-abc123def456.us-east-1.rds.amazonaws.com
-U postgres
-d postgres
Explore the database schema
Letta creates 42 tables to manage agents, memory, messages, and associated metadata. To view all tables, execute the following command:
You should see output displaying tables including agents, messages, organizations, users, block, sources, and other details:
postgres=>
The key tables for understanding agent state are:
- agents – Stores agent configuration and metadata
- messages – Contains all conversation messages with full content as JSON
- organizations and users – Manages multi-tenant access control
- block and block_history – Stores memory blocks and their revision history
- sources and source_passages – Contains data sources and their embeddings for retrieval
View agent information
To view all agents in your database, use the following code:
CREATE EXTENSION vector;
View agent messages
To examine the conversation history for a specific agent, utilize the content column, which stores messages as JSON (the text column is currently empty in Letta versions):
CREATE EXTENSION vector;
The following is an example of the output:
CREATE EXTENSION vector;
The messages table retains the complete conversation flow as JSON, enabling you to trace precisely how agents process and respond to user input.
Examine message content structure
Letta organizes message content as JSON. To view the detailed structure of an assistant message, execute the following code:
CREATE EXTENSION vector;
The following is an example of the output:
CREATE EXTENSION vector;
This output reveals the JSON structure of assistant messages, where each message is stored as an array of content objects containing type, text, and optional signature fields. System messages encompass the full agent instructions, while assistant and user messages capture the conversation content.
Understanding the schema for embeddings and data sources
Letta utilizes the pgvector extension to store embedding vectors for semantic memory search and Retrieval Augmented Generation (RAG). The database includes tables specifically designed for vector storage:
CREATE EXTENSION vector;
For a newly created agent with basic conversation history, both tables will initially show 0 records. These tables populate when you perform the following actions:
- Attach documents or files to an agent as data sources
- Utilize archival memory features for long-term storage
- Implement RAG workflows
The source_passages table retains embeddings for external data sources, while archival_passages stores embeddings for the agent’s archival memory system. Both leverage pgvector’s vector data type for efficient similarity searches.
Clean up
Upon completing your exploration of the integration, it is advisable to delete the Aurora cluster and associated resources to prevent ongoing charges.
Delete the Aurora cluster
To remove your Aurora cluster, follow these steps:
- On the Amazon RDS console, navigate to Databases.
- Select your database within the cluster (e.g.,
letta-aurora-cluster-instance-1). - Select Actions, then choose Delete.
- Enter
delete mein the confirmation field. - After the instance is deleted, you can proceed to delete the cluster.
- For Create final snapshot, select No (this is a test environment).
- Enter
delete mein the confirmation field. - Select Delete.
The deletion process may take several minutes.
Delete the security group
Once the cluster is deleted, follow these steps to remove the security group:
- On the Amazon EC2 console, navigate to Security Groups.
- Select the security group you created (e.g.,
letta-aurora-sg). - Select Actions, then choose Delete security groups.
- Select Delete.