Skip to main content

Memories

Overview

Memories are named containers for storing and organizing knowledge items (entries) within a project. They provide a logical namespace for text content, enabling structured retrieval via the Knowledge module. Each memory can hold many memory entries — individual pieces of text that are automatically embedded for semantic search.

Key Concepts

Memory

FieldTypeDescription
idstringPublic ID (mem_ prefix)
project_idstringID of the owning project
namestringHuman-readable name
descriptionstring|nullOptional description
tagsstring[]|nullOptional labels for filtering by category
created_atstringISO 8601 creation timestamp
updated_atstringISO 8601 last-update timestamp

Memory Entry

Memory entries are the individual knowledge items stored inside a memory. When an entry is created or updated, its content is automatically embedded using the configured embedding model. The embedding is used for semantic similarity search in the Knowledge module.

FieldTypeDescription
idstringPublic ID (me_ prefix)
memory_idstringID of the parent memory
contentstringText content of the entry
sourcestringOrigin of the entry: manual, agent, or extraction
created_atstringISO 8601 creation timestamp
updated_atstringISO 8601 last-update timestamp

Sources

  • manual — Default. Entry created directly by a user or API caller.
  • agent — Entry written by an agent during execution.
  • extraction — Entry extracted from a document or external source.

Write Algorithm

Every write to a memory — via REST, agent tool, or extraction — goes through the same deduplication algorithm. You never need to check for duplicates yourself.

How It Works

When you call POST /api/v1/memories/:memoryId/entries, the server:

  1. Embeds the incoming content.
  2. Finds the most similar existing entry in that memory (cosine similarity via pgvector).
  3. Decides based on two configurable thresholds:
Similarity rangeDecisionWhat happens
duplicate_thresholdSkipThe fact is already known. Returns the existing entry unchanged.
update_thresholdMergeThe fact overlaps. The incoming content is appended to the existing entry.
< update_thresholdCreateThe fact is new. A new entry is created.

Request Fields

FieldTypeDefaultDescription
contentstringThe fact or observation to write
sourcestringmanualOrigin: manual, agent, extraction
duplicate_thresholdnumber0.95Similarity above which the write is skipped
update_thresholdnumber0.75Similarity above which entries are merged

Response

The response always includes an action field alongside the entry:

actionHTTP statusMeaning
created201New entry written
updated200Existing entry merged with new content
skipped200Duplicate detected — existing entry returned

Examples

First write — new fact:

POST /api/v1/memories/mem_abc/entries
{ "content": "Customer prefers email over phone calls" }

201 { "action": "created", "id": "me_001", "content": "Customer prefers email over phone calls", ... }

Duplicate write — same fact rephrased:

POST /api/v1/memories/mem_abc/entries
{ "content": "The customer likes email more than phone" }

200 { "action": "skipped", "id": "me_001", "content": "Customer prefers email over phone calls", ... }

Merge write — related fact with new detail:

POST /api/v1/memories/mem_abc/entries
{ "content": "Customer prefers email, especially for billing inquiries" }

200 { "action": "updated", "id": "me_001", "content": "Customer prefers email over phone calls\nCustomer prefers email, especially for billing inquiries", ... }

Unrelated write — genuinely new fact:

POST /api/v1/memories/mem_abc/entries
{ "content": "Customer fiscal year ends in March" }

201 { "action": "created", "id": "me_002", "content": "Customer fiscal year ends in March", ... }

Tag Filtering

Tags are free-form strings you attach to a memory at creation or update time. They let you organise and filter memories without knowing their IDs upfront.

Setting Tags

Pass tags when creating or updating a memory:

POST /api/v1/memories
{
"project_id": "prj_abc",
"name": "Customer Preferences",
"tags": ["customer", "crm", "user-prefs"]
}

Filtering GET /api/v1/memories

Use the tags query parameter to filter the list. The parameter supports glob patterns:

PatternMatches
crmOnly crm (exact)
customer*customer, customer-support, customer-prefs
user-?refsuser-prefs, user-xrefs, etc.

Multiple patterns are ORed — a memory is included if any of its tags match any pattern.

Example — exact match:

GET /api/v1/memories?project_id=prj_abc&tags=crm

Example — glob prefix:

GET /api/v1/memories?project_id=prj_abc&tags=customer*

Example — multiple patterns:

GET /api/v1/memories?project_id=prj_abc&tags=customer*&tags=crm

The same glob syntax applies to memory_tags in POST /api/v1/knowledge/search:

{
"project_id": "prj_abc",
"query": "preferred contact method",
"memory_tags": ["customer*"]
}

The server resolves all memories whose tags match the patterns, then searches entries within those memories. This lets agents and search callers target a category of memories without knowing specific IDs.

Agent Integration

Agents can read from and write to memories automatically during generation.

Automatic Knowledge Retrieval

Set knowledge_config on an agent to have the server search relevant memory entries before every generation and inject them as system messages:

{
"knowledge_config": {
"memory_ids": ["mem_abc"],
"memory_tags": ["customer*"],
"min_score": 0.6,
"limit": 5
}
}

Before each generation the server embeds the latest user message, runs searchKnowledge with the merged config, and prepends results like:

[Memory: Customer Preferences] Customer prefers email over phone calls, especially for billing inquiries
[Memory: Customer Preferences] Customer fiscal year ends in March

See the Agents module for the full knowledge_config reference and merge semantics.

write_memory Agent Tool

Agents can write new facts to a memory during generation by setting write_memory_id in the agent's knowledge_config. When this field is present, SOAT automatically injects a write_memory tool into every generation — no manual tool attachment needed.

The tool accepts a single input:

InputTypeDescription
contentstringThe atomic fact to write to the memory

The target memory is fixed by the write_memory_id value — the agent cannot choose a different memory. The write goes through the standard deduplication algorithm, so the agent never produces duplicate entries. Entries written by the tool are tagged with source: "agent".

To enable the tool, set write_memory_id in the agent's knowledge_config:

{
"knowledge_config": {
"memory_ids": ["mem_alice"],
"write_memory_id": "mem_alice"
}
}

You can set write_memory_id to the same memory used for retrieval (so the agent reads from and writes to the same pool) or to a separate memory.