Managing agent memories v7

Manage agent memory directly from Postgres with the aidb_memory SQL functions: add conversation turns, check processing status, and search, list, and delete memories.

To read a conversation back in order, see Using session memory.

Prerequisites

Choosing identifiers

Every call identifies whose memory it touches with a namespace, an actor, and optionally an agent and a session. You don't register or look up the actor, agent, or session values, because your application defines them as strings. Use the same value for the same user, agent, or conversation every time, because the aidb_memory.add, aidb_memory.search, aidb_memory.list_memories, aidb_memory.status, and aidb_memory.delete functions use these values as filters. The namespace must already exist. To see the namespaces that an operator created, run:

SELECT name FROM aidb_memory.namespaces;
ParameterPurposeRecommended practice
namespaceGroups a memory configuration and storage backend.See Scoping memory with namespaces.
actor_idIdentifies whose memory is stored or retrieved.Use a stable application identifier, not a display name. Always pass it, because filters are the only isolation between actors.
agent_idIdentifies the agent or application component.Pass it consistently so that searches and deletions are scoped to the right agent.
session_idIdentifies a conversation, ticket, workflow, or run.Include it when memory should be scoped to one interaction.
idempotency_keyDeduplicates repeated aidb_memory.add calls.Generate it from the source event ID, message batch ID, or transaction ID.

Agent memory enforces isolation between actors only through the filters that you pass, such as actor_id. Always pass actor_id in your calls to the aidb_memory functions, and use agent_id and session_id to narrow results further. Row-level security managed by Agent Governance is planned for a future release.

Adding memories

Use aidb_memory.add when you want your agent to learn from a conversation or event. The operation is asynchronous. It accepts the event first, and then the Agent Memory Server builds durable memories from the submitted turns in the background.

SELECT aidb_memory.add(
  turns           => $$[
    {
      "role": "user",
      "content": "Hi Sam, my annual subscription renewed, but my 20% discount was not applied. I was charged the full $120."
    },
    {
      "role": "assistant",
      "content": "I can help check the renewal and discount history for your account."
    }
  ]$$::jsonb,
  namespace       => 'helpdesk_namespace',
  actor_id        => 'alice',
  agent_id        => 'helpdesk-agent-64849',
  session_id      => 'conv-738949',
  idempotency_key => 'conv-738949-turn-001'
);

The function returns the ID of the aidb_memory.add operation.

  • turns is a JSONB array of message objects, one for each message in the conversation. In your application, build it from the messages exchanged between the user and your agent. Each object has a role, such as user or assistant, and the message content. Include enough context for the memory builder to extract useful facts.
  • actor_id identifies the user, tenant, device, or other subject whose memory is stored.
  • agent_id and session_id are optional filters. Using them consistently makes later aidb_memory.search, aidb_memory.list_memories, and aidb_memory.delete calls safer.
  • idempotency_key helps prevent duplicate ingestion when an application retries the same event.

Checking processing status

Use aidb_memory.status after add when your application must wait until a memory is searchable before it calls search.

SELECT *
FROM aidb_memory.status(
  id         => '7c6adca3-277c-48ad-b6f6-5bbeff362540',
  namespace  => 'helpdesk_namespace',
  actor_id   => 'alice',
  agent_id   => 'helpdesk-agent-64849',
  session_id => 'conv-738949'
);

The result shows the status of the aidb_memory.add operation. The id argument is optional. If you omit it, the query isn't limited to one event, so you can filter by actor, agent, or session instead, and page through the results with limit and offset.

An event moves through these states:

StateMeaning
ACCEPTEDThe event was accepted.
PROCESSINGThe event is being processed.
READYThe memories are ready to retrieve.
SKIPPEDThe event was skipped.
FAILEDMemory formation failed.

If an event is FAILED, the error_detail column of the status result describes the error.

Memories are searchable only after the event reaches READY. If your application needs a memory that it just added, such as in the next step of the same conversation, poll aidb_memory.status until the state is READY before you call search. If you don't need the memory immediately, you don't need to check.

To audit events and their states directly, query the aidb_memory.events view.

Searching memories

Use aidb_memory.search when your agent needs the most relevant memories for a natural-language query. Include the same actor_id, agent_id, and session_id filters that you used when you added the conversation.

SELECT *
FROM aidb_memory.search(
  query      => 'promo code failed to apply on auto-renewal',
  namespace  => 'helpdesk_namespace',
  actor_id   => 'alice',
  agent_id   => 'helpdesk-agent-64849',
  session_id => 'conv-738949',
  "limit"    => 5
)
ORDER BY score DESC;

The result lists the memories that match the query.

  • Use concise queries that describe the current task or the user's intent.
  • Set limit to the smallest number of memories that your prompt or application needs.
  • Review the returned score values and memory content before you inject memories into prompts or downstream actions.

Listing memories

Use aidb_memory.list_memories for inspection, debugging, administration, or user-facing memory review screens. Listing is an operator task. It filters by identifiers and isn't a semantic relevance search.

SELECT id, content, agent_id, session_id
FROM aidb_memory.list_memories(
  namespace  => 'helpdesk_namespace',
  actor_id   => 'alice',
  agent_id   => 'helpdesk-agent-64849',
  session_id => 'conv-738949',
  "limit"    => 100
);

The function returns a table of the memories that match the filters. Use the results to display what is stored, to confirm that asynchronous memory creation has finished, or to collect memory IDs for targeted deletion.

Deleting memories

Use aidb_memory.delete to remove memories. Deleting is an operator task. Delete by explicit memory IDs, which you can get from search or list_memories. Keep the actor and agent filters in the call so that you don't remove unrelated records.

SELECT aidb_memory.delete(
  selector   => '{
    "memory_ids": [
      "858ada52-10a3-42ca-b25c-fc4fbaeed2a5",
      "4ae513f0-7135-46cc-a445-bd2e77e948b5"
    ]
  }'::jsonb,
  reason     => 'Remove incorrectly stored facts',
  namespace  => 'helpdesk_namespace',
  actor_id   => 'alice',
  agent_id   => 'helpdesk-agent-64849',
  session_id => 'conv-738949'
) AS selected_memories_deleted;

The function returns the number of memories deleted. The reason is recorded for auditing.

To delete by scope instead of by ID, set the selector's scope to session, agent, or actor. For example, {"scope": "session"}.

Deletion is intended for administrative correction, data retention, privacy, and compliance workflows. Confirm the selected memory IDs before you run a deletion in production.

Production recommendations

  • Wrap application calls in transactions only when your application state requires it. Don't hold long-running transactions open while you poll status.
  • To trace memory events, query the aidb_memory.events view. It records the namespace, actor, agent, session, idempotency key, and state of each aidb_memory.add call.
  • Use least-privilege database roles for application callers, separate from the roles that manage storage schemas.
  • Validate JSONB payloads before you send them to the agent memory functions.
  • Use parameterized SQL from application code instead of string concatenation for JSON, identifiers, and filters.
  • Avoid storing secrets, payment data, or unnecessary personal data in memory turns.

Next steps