Building an AI agent with long memory application
LLMs are stateless by default — they don't remember previous conversations. AnalyticDB for PostgreSQL solves this with a built-in long-term memory layer that extracts, stores, and retrieves memories automatically across sessions, so your AI agent can personalize responses based on what users have shared before.
This guide covers the memory system's architecture, how memory retrieval and updates work, and the SQL interfaces for adding, searching, and deleting memories.
Use cases
Customer support chatbots: Recall customer preferences and past interactions to skip repetitive questions.
Personal AI tutors: Track student progress and adapt to individual learning patterns over time.
Healthcare assistants: Maintain patient history and deliver contextually relevant recommendations.
Enterprise knowledge management: Accumulate institutional knowledge from ongoing agent interactions.
Personalized AI assistants: Learn user preferences and adjust responses across conversations.
Prerequisites
Before you begin, make sure you have:
An AnalyticDB for PostgreSQL 7.0 instance with a kernel version that meets one of the following requirements:
Version 7.2 with kernel version 7.2.1.4 or later
Version 7.3.2.0 or later
View the minor version on the Basic Information page in the AnalyticDB for PostgreSQL console. If your instance doesn't meet the version requirements, update the minor version.
An API key for an LLM service. Get one from Alibaba Cloud Model Studio.
Public network access configured via a NAT Gateway for the VPC where your AnalyticDB instance runs, so it can reach external LLM services.
Service architecture
The system has three core components:
AnalyticDB for PostgreSQL LLM Memory Manager — Runs on the AnalyticDB for PostgreSQL coordinator node. It receives user queries, retrieves relevant memories, constructs prompts, calls the LLM, and returns results. After each conversation turn, it automatically extracts new memories and updates the Vector Store or Graph Store.
AI service — Provides LLM and embedding services. The LLM handles query responses, memory extraction, conflict resolution, and memory updates. The embedding model converts memories into vectors for retrieval.
AnalyticDB for PostgreSQL — Persists memories as vectors, text blocks, and knowledge graphs.
Key capabilities
Capability | Description |
Automatic memory extraction | The LLM extracts and stores important information from every conversation turn without manual intervention. |
Conflict resolution | When new information contradicts existing memories, the system resolves the conflict automatically using a timestamp-priority strategy. |
Dual storage architecture | Combines a Vector Store for semantic memory retrieval and a Graph Store for relationship tracking between entities. |
Smart retrieval | Ranks results by semantic relevance, importance, and recency using a combination of semantic search and graph queries. |
Multimodal input | Extracts memories from text, images, and other data formats. Provide the data URL directly — the LLM parses the content and the memory module stores the result. The LLM must support multimodal processing. |
How it works
Memory retrieval
1. Query processing
The LLM extracts key information from the user's query and generates filter conditions (such as category or time range) to narrow the search.
2. Vector retrieval
The system creates an embedding from the refined query, runs a semantic search against the Vector Store, sorts results by relevance, and applies any specified filters (user, agent, or metadata).
3. Result processing
Results from multiple search conditions are merged and re-ranked by relevance, importance, and recency. Each result includes a relevance score, metadata, and a timestamp.
A single search call triggers this entire pipeline — no manual orchestration needed.
Memory update
1. Information extraction
The LLM analyzes the conversation context to extract relevant memories, identifies key entities, and maps the relationships between them for the knowledge graph.
2. Conflict resolution
The system compares new memories against existing ones. If a conflict is detected (same entity, different attribute), it resolves it automatically. The current strategy is timestamp priority — the most recent information wins.
Conflict resolution triggers when new information contradicts an existing memory entry in terms of entities, relationships, or attributes. The system uses three strategies:
Timestamp priority (current default)
Prioritizes the memory with the most recent timestamp.
Applicable when users update attributes in conversation (e.g., correcting an address or date)
Example:
Existing: "User's birthday is 1995" (2023-01-01)
New: "User's birthday is 1996" (2023-10-05)
Result: Updates birthday to 1996
Confidence scoring
Prioritizes based on the credibility of the information source (user role, data source, contextual detail).
Example:
Existing: "User's occupation is teacher" (confidence 0.7)
New: "User's occupation is engineer" (confidence 0.9)
Result: Updates to "engineer" and records the conflict history
Context merging
Merges contradictory information into a single, context-aware description when both states may be valid at different times.
Example:
Existing: "User likes coffee" (2022-05)
New: "User doesn't like coffee" (2023-11)
Result: "User used to like coffee (2022-05), but now doesn't (2023-11)"
3. Memory storage
The Vector Store saves the actual memory content. The Graph Store saves entity relationships. Memory content updates automatically with each conversation turn.
A single add call triggers this entire pipeline — no manual orchestration needed.
Memory types and scenarios
Memory types
AnalyticDB for PostgreSQL supports four memory types, modeled after cognitive science classifications:
Memory type | Description |
Factual memory | User preferences, personal attributes, and domain-specific knowledge |
Episodic memory | Past interactions and experiences |
Semantic memory | Conceptual understanding and relationships between ideas |
Procedural memory | Techniques, processes, and task execution steps — primarily used in AI agent scenarios |
Choose a memory scenario
Use the following table to decide which ID parameter to use when calling the memory interfaces.
Scenario | Scope | Lifetime | Best for | Retrieval parameter |
Session | Memories from a single conversation session; no cross-session reference | Persistent until explicitly deleted | Short-term, single-session personalization |
|
User | All memories across all sessions for a given user; stores factual, episodic, and semantic types | Long-term | Cross-session personalization and preference tracking |
|
Agent | Procedural memories from agent-LLM interactions (subtask actions and results); AnalyticDB for PostgreSQL uses a specific prompt to extract the interaction history between the agent and LLM, forming memories stored in the Vector Store | Long-term | AI agent workflows that need to recall past execution steps |
|
Quick guide: Use run_id when you only need memories from the current session. Use user_id for personalization that spans sessions. Use agent_id when building agents that need to remember how they performed subtasks.
SQL interface reference
The following examples use:
LLM: Tongyi Qianwen qwen3-32b
Embedding model: text-embedding-v3 (text-embedding-v4 is also supported), an upgraded version of text-embedding-v2 with high performance, low cost, and support for 50+ languages and long text
Storage: AnalyticDB for PostgreSQL Vector Store
Configure the memory service
adbpg_llm_memory.config(config json)
Call this function to set up the LLM, embedding model, and Vector Store before running any other memory operations.
This configuration is session-scoped. All subsequent memory operations (add,search,get_all,delete_all) must run in the same session. If you're using DMS to test these examples, run all SQL statements in the same SQL Console tab.
Replace the api_key, user, password, and dbname values before running:
select adbpg_llm_memory.config(
$$
{
"llm": {
"provider": "qwen",
"config": {
"model": "qwen3-32b",
"qwen_base_url": "https://dashscope-intl.aliyuncs.com/compatible-mode/v1",
"api_key": "sk-xxxxxxx"
}
},
"embedder": {
"provider": "openai",
"config": {
"model": "text-embedding-v3",
"embedding_dims": "256",
"api_key": "sk-xxxxxx",
"openai_base_url": "https://dashscope-intl.aliyuncs.com/compatible-mode/v1"
}
},
"vector_store": {
"provider": "adbpg",
"config": {
"user": "username",
"password": "password",
"dbname": "testdb",
"hnsw": "True",
"embedding_model_dims": "256"
"port": 3029
}
}
}
$$
);Expected output:
{"message": "Configuration set successfully"}Add memories
adbpg_llm_memory.add(messages json, user_id text, run_id text, agent_id text, metadata json, memory_type text, prompt text)
The LLM extracts key facts from the conversation and stores each one as a separate memory entry.
Parameter | Description |
| Conversation messages to extract memories from |
| ID of the user the memories belong to |
| Session ID |
| Agent ID |
| Optional metadata — supports |
| Memory type; default is |
| Custom extraction prompt; default is |
SELECT adbpg_llm_memory.add($$
[
{"role": "user", "content": "Hi, I'm Zhang San. I like hiking, but I don't like intense exercise,"},
{"role": "assistant", "content": "Hello, Zhang San! Hiking is a great hobby. I'll remember your preferences. If you have any questions about hiking route planning, equipment recommendations, or scenic spots along the way, feel free to ask anytime."}
]
$$, 'test_u', null, null, $${"expiration_date": "2025-08-01"}$$, null, null);Expected output:
{
"results": [
{
"id": "e6d241f9-634f-43e4-925c-0ed70974****",
"memory": "Name is Zhang San",
"event": "ADD"
},
{
"id": "9efbb099-a20b-483e-99ef-3cc1e85e****",
"memory": "Likes hiking",
"event": "ADD"
},
{
"id": "6fc474d5-1e77-48ec-a5f2-8cb9ec50****",
"memory": "Dislikes intense exercise",
"event": "ADD"
}
]
}Get all memories for a user or agent
adbpg_llm_memory.get_all(user_id text, run_id text, agent_id text)
Returns all stored memories for the specified user or agent in JSON format.
SELECT adbpg_llm_memory.get_all('test_u', null, null);Expected output:
{
"results": [
{
"id": "1cf1e872-5f78-41d0-b1ab-370eee82****",
"memory": "Name is Zhang San",
"hash": "d6f327d1ea38b8387927810bdcd3****",
"metadata": {"expiration_date": "2025-08-01"},
"created_at": "2025-06-25T15:45:58.687949+08:00",
"updated_at": null,
"user_id": "test_u"
},
{
"id": "5806ab99-9764-4f31-bbda-29b77e8b****",
"memory": "Likes hiking",
"hash": "5f8275169192f1a1a4564149c3d1****",
"metadata": {"expiration_date": "2025-08-01"},
"created_at": "2025-06-25T15:45:58.700653+08:00",
"updated_at": null,
"user_id": "test_u"
},
{
"id": "55babe14-2605-40fa-9b32-e5ccefc3****",
"memory": "Dislikes intense exercise",
"hash": "18fa10d79b6d2b0ec7f271817095****",
"metadata": {"expiration_date": "2025-08-01"},
"created_at": "2025-06-25T15:45:58.704473+08:00",
"updated_at": null,
"user_id": "test_u"
}
]
}Search memories by query
adbpg_llm_memory.search(query text, user_id text, run_id text, agent_id text, filter json)
Retrieves memories semantically related to a given query. Use this to find relevant context before calling your LLM.
Parameter | Description |
| The user's input or the topic to retrieve memories for |
| Optional filter conditions to narrow results (e.g., by metadata) |
SELECT adbpg_llm_memory.search(
'Can you recommend some exercise activities and locations for this weekend?',
'test_u', null, null, null
);Expected output — each result includes a score indicating semantic relevance:
{
"results": [
{
"id": "5806ab99-9764-4f31-bbda-29b77e8b****",
"memory": "Likes hiking",
"hash": "5f8275169192f1a1a4564149c3d1****",
"metadata": {"expiration_date": "2025-08-01"},
"score": 0.4617832899093628,
"created_at": "2025-06-25T15:45:58.700653+08:00",
"updated_at": null,
"user_id": "test_u"
},
{
"id": "55babe14-2605-40fa-9b32-e5ccefc3****",
"memory": "Dislikes intense exercise",
"hash": "18fa10d79b6d2b0ec7f271817095****",
"metadata": {"expiration_date": "2025-08-01"},
"score": 0.48010164499282837,
"created_at": "2025-06-25T15:45:58.704473+08:00",
"updated_at": null,
"user_id": "test_u"
},
{
"id": "1cf1e872-5f78-41d0-b1ab-370eee82****",
"memory": "Name is Zhang San",
"hash": "d6f327d1ea38b8387927810bdcd3****",
"metadata": {"expiration_date": "2025-08-01"},
"score": 0.6027468977721387,
"created_at": "2025-06-25T15:45:58.687949+08:00",
"updated_at": null,
"user_id": "test_u"
}
]
}Delete all memories for a user or agent
adbpg_llm_memory.delete_all(user_id text, run_id text, agent_id text)
Deletes all memories associated with the specified user, session, or agent.
SELECT adbpg_llm_memory.delete_all('test_u', null, null);Expected output:
{"message": "All relevant memories deleted"}