Agent memory

An AI agent forgets everything between model calls unless something remembers for it. Agent memory keeps two kinds of memory for your agents, in one of your…

An AI agent forgets everything between model calls unless something remembers for it. Agent memory keeps two kinds of memory for your agents, in one of your KiviDB databases:

  • Working memory, per conversation (a session): the recent messages and a running summary of the older ones, so a long conversation fits in a prompt.
  • Long-term memory, per user (an actor): lasting facts, preferences and events, pulled out of conversations in the background and found again by meaning when they are relevant.

Everything a store remembers is kept in the database it lives in, under keys starting kividb:mem:. Nothing is stored anywhere else.

How it works

  1. After each turn, your agent adds the new messages to the session.
  2. Before the next model call, it asks for recall: the session's summary, its recent messages and the long-term memories most relevant to the user's latest message, as ready-to-use text.
  3. In the background, once a session has been quiet for the extraction delay (five minutes by default), the store's language model reads the messages it has not read yet and keeps what is worth remembering. A memory the same actor already has (by similarity) is not kept twice.
  4. Once a session holds more messages than summarize after, the oldest are folded into its summary and only the most recent are kept as they are.

Memories have a type. Every store has semantic (a fact or preference: "The user deploys to eu-west-1") and episodic (something that happened: "The user migrated their cache on 12 October"). You can add up to three types of your own, each with a sentence describing what to extract, such as order_issue: "a problem the user had with an order, with the order number".

Models and keys

A store uses two models, each with your own API key, stored encrypted and never shown again:

Used forProviders
Language modelextracting memories and writing summariesOpenAI, Anthropic, or any HTTPS endpoint with OpenAI's /chat/completions shape
Embeddingsfinding memories by meaningOpenAI, or any HTTPS endpoint with OpenAI's /embeddings shape; or none, and you send vectors

You pay your provider for what these calls use; KiviDB adds no charge for agent memory beyond the database it lives in. With no language model, a store still keeps sessions and the memories you add yourself, but extracts and summarizes nothing. A custom endpoint must be HTTPS on a public address.

Personal data. By default, emails, phone numbers, payment card numbers, US social security numbers and IP addresses are replaced with markers such as [email] before a memory is kept. This is pattern matching: names and street addresses are not caught. Working memory keeps messages as you sent them.

In the console

The Agent memory section lists every store in your organization with the database it lives in; each database also has an Agent memory tab with its own stores. A store shows its sessions with their summaries and messages, its memories (browse, search, forget), when extraction last ran and why it failed if it did, and a place to try it. Agent memory is not available on sharded databases yet.

API

Authenticate with an API key, as for the rest of the API. {id} is the database, {store} the store's name, and {session} your own conversation id (letters, digits, ., _, :, @ and -).

Request
GET /agent-memoryevery store in the organization, with its database
GET /instances/{id}/agent-memorythis database's stores
PUT /instances/{id}/agent-memory/{store}create or change a store
GET /instances/{id}/agent-memory/{store}settings, and counts of sessions, memories and sessions waiting for extraction
DELETE /instances/{id}/agent-memory/{store}delete the store and everything it keeps
POST /instances/{id}/agent-memory/{store}/sessions/{session}/eventsadd messages: {"actor_id": "user-7", "events": [{"role": "user", "content": "..."}]}
GET /instances/{id}/agent-memory/{store}/sessionsa page of sessions, most recent first (?offset=)
GET /instances/{id}/agent-memory/{store}/sessions/{session}the summary and recent messages (?recent=50)
DELETE /instances/{id}/agent-memory/{store}/sessions/{session}forget a session's working memory
POST /instances/{id}/agent-memory/{store}/sessions/{session}/extractextract now instead of after the delay
POST /instances/{id}/agent-memory/{store}/recall{"session_id", "query"?, "actor_id"?, "limit"?}: summary, recent messages, relevant memories and a context string
POST /instances/{id}/agent-memory/{store}/memoriesadd a memory yourself: {"text", "type"?, "actor_id"?, "topics"?}
GET /instances/{id}/agent-memory/{store}/memoriesa page of memories, newest first
POST /instances/{id}/agent-memory/{store}/memories/search{"query", "mode": "semantic" | "keyword" | "hybrid", "actor_id"?, "types"?, "limit"?}
DELETE /instances/{id}/agent-memory/{store}/memories/{memory}forget one memory

Creating a store:

curl -X PUT https://api.kividb.io/instances/$DB/agent-memory/support-agent \
  -H "Authorization: Bearer $KIVIDB_API_KEY" -H "Content-Type: application/json" \
  -d '{
    "llm_provider": "openai", "llm_model": "gpt-4o-mini", "llm_api_key": "'"$OPENAI_API_KEY"'",
    "embed_provider": "openai", "embed_model": "text-embedding-3-small", "embed_api_key": "'"$OPENAI_API_KEY"'",
    "dimensions": 1536
  }'

A turn of a conversation, in Python:

import requests

API = f"https://api.kividb.io/instances/{DB}/agent-memory/support-agent"
H = {"Authorization": f"Bearer {KIVIDB_API_KEY}"}

def answer(session_id, user_id, user_message):
    memory = requests.post(f"{API}/recall", headers=H, json={
        "session_id": session_id, "actor_id": user_id, "query": user_message,
    }).json()
    reply = call_your_model(system=memory["context"], user=user_message)
    requests.post(f"{API}/sessions/{session_id}/events", headers=H, json={
        "actor_id": user_id,
        "events": [{"role": "user", "content": user_message}, {"role": "assistant", "content": reply}],
    })
    return reply

Settings

SettingDefault
extraction_delay_seconds300how long after a session's newest unread message extraction runs (30 to 3600)
summarize_after40summarize once a session holds more messages than this
keep_recent12messages kept as they are when summarizing
session_ttl_seconds3600a session is forgotten this long after its last message
memory_ttl_seconds31536000a long-term memory is kept this long (one year)
dedupe_threshold0.92a new memory at least this similar to one the actor has is a duplicate
custom_typesnoneup to three {"name", "description"}
redact_piitruereplace common personal identifiers before keeping a memory

From an AI assistant

The KiviDB MCP server has list_memory_stores, memory_add_messages, memory_recall, memory_search, memory_add and memory_forget, so an assistant can use a store you have made in the console.