Building an AI agent with long memory application

更新时间:
复制 MD 格式

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

image

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

image

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

image

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

run_id

User

All memories across all sessions for a given user; stores factual, episodic, and semantic types

Long-term

Cross-session personalization and preference tracking

user_id, or user_id + run_id for a specific session

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

agent_id, or agent_id + run_id for a specific session

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

messages

Conversation messages to extract memories from

user_id

ID of the user the memories belong to

run_id

Session ID

agent_id

Agent ID

metadata

Optional metadata — supports expiration_date to set memory expiry

memory_type

Memory type; default is null. Set to 'procedural_memory' for agent memories

prompt

Custom extraction prompt; default is null. If customized, format the output as Output: {{"facts": [xxx]}}

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

query

The user's input or the topic to retrieve memories for

filter

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"}