Skip to content

Memory Configuration

SynthOrg agents have persistent memory that spans conversations and tasks. The memory system stores experiences, knowledge, skills, and relationships, and retrieves relevant memories to inject into the agent's context. This guide covers how to configure memory backends, persistence levels, retrieval tuning, shared organisational memory, and consolidation.


Memory Architecture

The memory system has two concerns:

  • Agent memory: per-agent memories (what an agent has learned, experienced, and knows) stored in a pluggable memory backend
  • Operational data: structured records (tasks, cost records, messages, audit entries) stored in a persistence backend (SQLite)
graph TD
    Agent["Agent"]
    Retriever["Retrieval Pipeline"]
    Backend["Memory Backend<br/><small>sqlvector (pgvector / sqlite-vec)</small>"]
    OrgMem["Shared Org Memory<br/><small>Core policies + extended facts</small>"]
    Persistence["Persistence Backend<br/><small>SQLite / Postgres</small>"]

    Agent -->|"recall"| Retriever
    Agent -->|"store"| Backend
    Retriever --> Backend
    Retriever --> OrgMem
    Agent -.->|"tasks, costs"| Persistence

Memory Types

Agents store five types of memory:

Type Description Typical Lifetime
Working Current task context, active plans Task duration
Episodic Past events, conversations, outcomes Configurable retention
Semantic Learned facts, domain knowledge Long-term
Procedural Skills, patterns, how-to knowledge Long-term
Social Relationships, collaboration history Long-term

Memory Levels

The level field controls how long memories persist:

Level Value Behaviour
Persistent persistent Memories survive across all sessions and projects
Project project Memories persist for the duration of a project
Session session Memories persist for the current session only (default)
None none No memory storage

Agent Memory Configuration

Configure memory in the memory section of your company config:

memory:
  backend: "sqlvector"
  storage:
    data_dir: "/data/memory"
  options:
    retention_days: null          # null = keep forever
    max_memories_per_agent: 10000
    shared_knowledge_base: true
  retrieval:
    strategy: context
    relevance_weight: 0.7
    recency_weight: 0.3
    min_relevance: 0.3
    max_memories: 5               # tuned top-k after ranking; MMR on by default
    diversity_penalty_enabled: true
    include_shared: true
  consolidation:
    interval: daily
    max_memories_per_agent: 10000

The per-agent persistence level lives on the agent's MemoryConfig.type (default session), not in this company-wide section.

Top-Level Memory Fields

Field Type Default Description
backend string "sqlvector" Memory backend: "sqlvector" (durable, semantic), "composite" (per-namespace routing), or "inmemory" (ephemeral, discouraged)
storage MemoryStorageConfig (defaults) Storage backend settings
options MemoryOptionsConfig (defaults) Behaviour options
retrieval MemoryRetrievalConfig (defaults) Retrieval pipeline settings
consolidation ConsolidationConfig (defaults) Consolidation settings
procedural ProceduralMemoryConfig (defaults) Procedural skill auto-generation

Checking Memory Health

GET /health reports memory in one of three states, shown as a card in the dashboard's system-health popover:

State Meaning
durable Wired on a store that survives restarts and retrieves by meaning
degraded Wired, but not fully durable: the ephemeral keyword backend, a failed health probe, a missing dense index (keyword-only recall), or maintenance disabled
off No backend wired at all, whatever the configured type. Usually no embedding model resolved

degraded and off are surfaced rather than silently tolerated: memory that quietly degrades to substring matching looks healthy while recalling the wrong thing. Reaching durable takes more than embedder configuration: a durable backend must be wired on a store that survives restarts, an embedding model must resolve for semantic recall, and the readiness probe must pass. Setting the memory.embedder_* overrides alone lifts off only when a durable backend is already wired; a wired-but-degraded durable backend still fails the readiness probe, so the fault stays visible rather than masquerading as healthy.


Storage Configuration

Field Type Default Description
data_dir string "/data/memory" Directory for memory artefacts kept outside the database (Docker volume mount)

Vectors and their lexical index live in the operational database, so there is no separate vector-store or history-store to configure or back up.

Note

The data_dir path is validated to reject parent-directory traversal (..) to prevent path escape attacks.


Memory Options

Field Type Default Description
retention_days int or null null Days to retain memories (null = forever)
max_memories_per_agent int 10000 Upper bound on memories per agent
shared_knowledge_base bool true Whether shared knowledge is enabled

The consolidation cadence is consolidation.interval, not an option here: that is the field the scheduler reads and the memory.consolidation_interval setting mirrors.


Retrieval Pipeline

When an agent needs context, the retrieval pipeline queries the memory backend, ranks results, and injects the top matches into the agent's prompt.

Retrieval Fields

Field Type Default Description
strategy string "context" Injection strategy (only "context")
relevance_weight float 0.7 Weight for backend relevance score (0.0--1.0)
recency_weight float 0.3 Weight for recency decay score (0.0--1.0)
recency_decay_rate float 0.01 Exponential decay rate per hour
personal_boost float 0.1 Boost for personal memories over shared (0.0--1.0)
min_relevance float 0.3 Minimum combined score to include a memory
max_memories int 5 Tuned top-k injected after ranking (1--100)
include_shared bool true Whether to query shared org memory
default_relevance float 0.5 Score for entries missing a relevance score
injection_point string "system" Where to inject: "system" (system prompt) or "user"
memory_filter_strategy string "off" Post-ranking filter: "off" (no filter), "tag_based" (only non-inferable-tagged memories), or "passthrough" (inject all)
fusion_strategy string "linear" Ranking fusion: "linear" (relevance + recency) or "rrf" (Reciprocal Rank Fusion over multiple ranked lists)
rrf_k int 60 RRF smoothing constant (only with RRF strategy, 1--1000)
diversity_penalty_enabled bool true Apply MMR diversity re-ranking (context strategy only; off for other strategies)
diversity_lambda float 0.7 MMR trade-off: 1.0 pure relevance, 0.0 maximum diversity
candidate_pool_multiplier int 3 Dense/lexical over-fetch width before ranking narrows to max_memories

Weight Tuning

For the linear fusion strategy, relevance_weight + recency_weight must equal 1.0:

retrieval:
  relevance_weight: 0.7   # prioritize semantic relevance
  recency_weight: 0.3     # with some recency bias
  • Higher relevance_weight: better for knowledge-heavy tasks where the most relevant memory matters regardless of when it was stored
  • Higher recency_weight: better for conversational contexts where recent interactions are more important
  • personal_boost: adds a bonus to the agent's own memories over shared org memories (0.1 = 10% boost)

Shared Organisational Memory

Beyond per-agent memory, SynthOrg supports shared organisational memory: knowledge available to all agents.

org_memory:
  core_policies:
    - "All code must pass review before merging."
    - "Customer data is never logged or stored in plain text."
    - "Budget decisions require CFO approval above 50 units in the configured currency."
  extended_store:
    max_retrieved_per_query: 5

Org Memory Fields

Field Type Default Description
core_policies list [] Policy texts injected into every agent's system prompt
extended_store ExtendedStoreConfig (defaults) Extended facts store
write_access WriteAccessConfig (defaults) Write access control

How It Works

The hybrid prompt + retrieval backend uses two layers:

  1. Core policies: short, critical rules injected directly into every agent's system prompt. These are always available and never filtered.
  2. Extended store: a searchable database of organisational facts, procedures, and conventions. These are retrieved on demand via the retrieval pipeline (up to max_retrieved_per_query per query).

Consolidation & Archival

Over time, agent memories accumulate. Consolidation manages memory volume through retention rules and archival:

consolidation:
  interval: daily
  max_memories_per_agent: 10000
  retention:
    default_retention_days: null   # keep forever by default
    rules: []                      # per-category overrides
  archival:
    enabled: false
    age_threshold_days: 90
    dual_mode:
      enabled: false
      dense_threshold: 0.5
      summarization_model: "example-capable-001"
      max_summary_tokens: 200
      max_facts: 20
      anchor_length: 150

Consolidation Fields

Field Type Default Description
interval string "daily" Run frequency: hourly, daily, weekly, never
max_memories_per_agent int 10000 Upper bound on memories per agent

Retention

Per-category retention rules (uniform across all agents):

Field Type Default Description
default_retention_days int or null null Default retention (null = forever)
rules list [] Per-category retention rules

Archival

When archival is enabled, memories older than age_threshold_days are archived using one of two modes:

Mode When Used Description
Abstractive Sparse/conversational content LLM generates a summary of the memory
Extractive Dense/factual content Verbatim key facts + start/mid/end anchors preserved

The archival system classifies each memory by density score and routes to the appropriate mode:

Field Type Default Description
archival.enabled bool false Whether archival is active
archival.age_threshold_days int 90 Minimum age before archival
archival.dual_mode.enabled bool false Enable density-aware dual-mode
archival.dual_mode.dense_threshold float 0.5 Score threshold for DENSE classification
archival.dual_mode.summarization_model string null Model for abstractive summaries (required when enabled)
archival.dual_mode.max_summary_tokens int 200 Max tokens for summaries (50--1000)
archival.dual_mode.max_facts int 20 Max extracted key facts (1--100)
archival.dual_mode.anchor_length int 150 Character length per anchor snippet (50--500)

Note

When dual_mode.enabled is true, summarization_model must be set. This model is used for abstractive archival and should be a cost-effective model.


Procedural Memory

When an agent fails a task and recovers, the procedural pipeline asks a model what it would do differently, and stores the answer as a reusable skill. Later tasks recall that skill instead of rediscovering the same workaround.

procedural:
  enabled: true
  model: null                 # unset: the proposer makes no LLM call
  temperature: 0.3
  max_tokens: 1500
  min_confidence: 0.5
  skill_md_directory: null    # set to also write portable SKILL.md files
Field Setting key Applies Description
enabled memory.procedural_enabled Next task Master switch. When off, every capture short-circuits and no LLM call is made
min_confidence memory.procedural_min_confidence Next task Quality floor: proposals rated below it are discarded
temperature memory.procedural_temperature Next restart Sampling temperature for the proposer
max_tokens memory.procedural_max_tokens Next restart Response token budget for the proposer
skill_md_directory memory.procedural_skill_md_directory Next restart Directory for SKILL.md materialisation; unset keeps skills in the backend only
model (company config) Next restart Proposer model. Unset means the proposer skips rather than guessing a model

enabled and min_confidence are re-resolved on every capture, so pausing skill generation or tightening the quality floor takes effect on the next task. The rest are baked into the frozen proposer config at startup.


Practical Example

A complete memory configuration for a research lab that prioritises long-term knowledge retention:

memory:
  backend: "sqlvector"
  storage:
    data_dir: "/data/memory"
  options:
    retention_days: null
    max_memories_per_agent: 50000
    shared_knowledge_base: true
  retrieval:
    strategy: context
    relevance_weight: 0.8        # strong relevance bias for research
    recency_weight: 0.2
    personal_boost: 0.05
    min_relevance: 0.4           # higher threshold for quality
    max_memories: 30             # more context for complex tasks
    include_shared: true
  consolidation:
    interval: weekly
    max_memories_per_agent: 50000
    archival:
      enabled: true
      age_threshold_days: 180
      dual_mode:
        enabled: true
        dense_threshold: 0.6
        summarization_model: "example-basic-001"
        max_summary_tokens: 300
        max_facts: 30

org_memory:
  core_policies:
    - "All research findings must be reproducible."
    - "Cite sources for all claims."
  extended_store:
    max_retrieved_per_query: 10

Memory Admin API

Operators with the CEO or SYSTEM role can manage embedding fine-tuning at runtime through the /admin/memory/fine-tune* endpoints (MemoryFineTuneController in src/synthorg/api/controllers/memory/fine_tune.py, guarded by require_roles(HumanRole.CEO, HumanRole.SYSTEM)).

Start a fine-tune run

curl -X POST http://localhost:3001/api/v1/admin/memory/fine-tune \
  -H "Content-Type: application/json" \
  -H "Cookie: ${SESSION}" \
  -d '{"agent_id": "sarah_chen"}' | jq

Resume, cancel, or check status

# Resume a paused run
curl -X POST http://localhost:3001/api/v1/admin/memory/fine-tune/resume/${RUN_ID} \
  -H "Cookie: ${SESSION}"

# Read current status
curl http://localhost:3001/api/v1/admin/memory/fine-tune/status \
  -H "Cookie: ${SESSION}" | jq

# Cancel the active run
curl -X POST http://localhost:3001/api/v1/admin/memory/fine-tune/cancel \
  -H "Cookie: ${SESSION}"

Preflight check, checkpoints, deploy / rollback

# Validate configuration before running
curl -X POST http://localhost:3001/api/v1/admin/memory/fine-tune/preflight \
  -H "Content-Type: application/json" \
  -H "Cookie: ${SESSION}" \
  -d '{"agent_id": "sarah_chen"}' | jq

# List available checkpoints
curl http://localhost:3001/api/v1/admin/memory/fine-tune/checkpoints \
  -H "Cookie: ${SESSION}" | jq

# Deploy or roll back a specific checkpoint
curl -X POST http://localhost:3001/api/v1/admin/memory/fine-tune/checkpoints/${CHECKPOINT_ID}/deploy \
  -H "Cookie: ${SESSION}"
curl -X POST http://localhost:3001/api/v1/admin/memory/fine-tune/checkpoints/${CHECKPOINT_ID}/rollback \
  -H "Cookie: ${SESSION}"

# Delete a checkpoint
curl -X DELETE http://localhost:3001/api/v1/admin/memory/fine-tune/checkpoints/${CHECKPOINT_ID} \
  -H "Cookie: ${SESSION}"

Admin endpoints on the backlog

Consolidation, reindex, procedural-skill management, and organisation-memory promotion are described in the Memory design page but are not exposed as REST endpoints today. These operations happen on agent-lifecycle boundaries (consolidation cycles, startup reindex, procedural-memory auto-generation); a dedicated admin surface is tracked on the GitHub issue tracker under the memory label.


See Also