Skip to main content
What this page is. The complete reference for Comis’s agent-memory capabilities and the exact config option for each. The memory features are ON by default (opt-out) — a fresh install runs them and you edit config to turn them off. The trust boundary (rag.scoring.trustAlpha, rag.includeTrustLevels) is frozen — not a tunable capability.
The LLM build/ask features (the session review job, the one learning-reflection cron, and the memory_ask grounded-Q&A tool) spend your own LLM/API budget. They are on by default, and the daemon prints a first-run notice listing what’s active. One line turns all of them off: memory.enabled: false.
The master kill-switch is memory.enabled, and the three recall model knobs nest under memory.recall.*. The whole per-agent learning layer is one agents.<id>.learning block (one learning.enabled flag + learning.reflect.* + learning.forget.*).
Where the config lives. Capabilities are configured per agent under agents.<agentId>. in ~/.comis/config.yaml. The shared memory engine (store + embeddings + reranker + the cost kill switch) is the top-level memory: block. The config below is the effective default — set any enabled: false to opt a feature out.
On by default is necessary but not always sufficient — several capabilities also need built derived state (a populated graph, scored usefulness) before they change recall. See Dependencies & gotchas below.

Default config (opt-out)

This is the effective default a fresh install runs. To opt out, set the relevant enabled: false (or flip the master memory.enabled: false to silence all LLM-cost features at once).

Capability → config map

The one learning-reflection engine

Comis’s learning layer is one outcome-gated reflection engine. A single __REFLECT__ cron maintains named Mental Model docs (kind: skill | profile | topic) via byte-stable delta-ops, gated on a real task outcome (the learningOutcome signal) rather than a text-overlap proxy. The whole layer is governed by one flagagents.<id>.learning.enabled — under the master memory.enabled switch.
  • Reflection (learning.reflect.*) — the __REFLECT__ cron clusters trusted-origin successful trajectories and distils them into Mental Model docs at trust=learned. A doc seeds only once its topic corroborates (learning.reflect.corroboration.mode, below). A learned doc is advisory (no executable column — the agent reads it and acts through its own already-permissioned tools); it can never exceed learned trust (a DB CHECK makes system structurally impossible). An admitted candidate promotes to active once its proof_count crosses promoteAtProofCount from attributed successful reuse; an active doc demotes (activestalearchived) on corroborated, sustained failing reuse. The per-user profile doc (kind:"profile") and higher-order topic observations (kind:"topic") are maintained in the same pass — a profile correction supersedes the prior doc with a bi-temporal history-append (the prior body is preserved in the doc’s history, never hard-deleted), and external-trust sources are excluded by the engine’s two-axis anti-poison SELECT. The same pass also distils advisory procedure docs from verifiably-successful orchestrate runs — a kind:"skill" doc that additionally records the deterministic tool footprint of the run (the audited tool names). It is outcome-gated and demote-on-failure like every learned doc, and it is advisory: the model reads the guidance and re-authors the script through its own already-permissioned tools — the doc is never a stored or replayed template, and there is no new execution path.
  • Procedure-doc surface budget (learning.reflect.maxProcedureDocsSurfaced, default 10) — a per-agent cap on how many procedure docs surface into one prompt’s <available_skills>. With no ranked top-K at surface time, a burst of procedure docs would otherwise bloat every prompt; the budget caps that subset only — when it is exceeded the most-corroborated procedure docs (highest proof count) keep their slot, surfaced in a stable listing order. User-intent skill docs and topic docs are unaffected — they keep a separate, uncapped path.
  • Forgetting (learning.forget.*) — couples a memory’s decay to its outcome-attributed failure_count, so wrong fades faster than merely old, and soft-evicts a sufficiently weak or stale memory: it is marked evicted_at (excluded from recall, still resolvable via asOf/inspect, reversible, never hard-deleted). A memory implicated in failureEvictionFloor (default 3) or more corroborated failures is soft-evicted regardless of its decayed strength, while a memory at/above highProofFloor (default 5) is exempt. A corroboration gate (≥2 independent failures, or one deterministic source, on every failure_count increment) plus exemptions for pinned / system / high-proof_count memories make induced eviction impractical: a poisoner cannot evict a well-corroborated, pinned, or system memory no matter how many failures it induces. The sweep runs on the keyless memoryLifecycle cron (__LIFECYCLE__).
Recall ranking itself is the fixed rag.scoring fusion (deterministic RRF + the cross-encoder reranker) — there is no learned recall weight.

Corroboration: single-owner (default) vs distinct-sessions (learning.reflect.corroboration)

Before a topic can seed a learned doc it must corroborate. The mode governs what counts as corroboration:
  • mode: single_owner (default) — repetition-as-corroboration, tuned for the primary Comis use case: a single-owner deployment (one trusted DM). One stable session means the distinct-sessions gate below is structurally unreachable (cardinality is always 1), so it would never learn anything. In single_owner mode the engine counts an explicitly-trusted owner’s repeated successes: when the owner succeeds at the same task minObservations times (default 2, never one-shot), the topic corroborates. The distinct-sessions gate still applies as a superset, so a box with two or more explicitly-trusted senders is handled the multi-user way automatically.
  • mode: distinct_sessions — the classic anti-domination gate: a topic needs ≥2 distinct (session, sender) successful observations. N near-identical successes from one sender in one session count once. Set this explicitly on a multi-user box that wants to require independent sessions even from its single trusted owner (the stricter posture).
single_owner is safe by construction as a default, even on a multi-user box. Repetition is counted only among senders the operator explicitly named in elevatedReply.senderTrustMap (resolving to a non-external tier) — a sender trusted merely by a promiscuous defaultTrustLevel, or an unknown sender, can ride past the success filter yet never self-corroborate by repetition. It also requires a single distinct owner, so a box with ≥2 explicitly-trusted senders falls back to the distinct-sessions gate. The only behavior change versus distinct_sessions is for a box with exactly one explicitly-trusted owner: it learns from that owner’s repetition (one session) instead of requiring two sessions. Choose distinct_sessions if you want to forbid even that.
The reflect:funnel telemetry carries a singleOwnerCorroborated count (how many topics corroborated via repetition this run), so comis explain and comis fleet show the mode is active — an admitted > 0 run with maxClusterCardinality: 1 reads as single-owner learning, not a contradiction. See learning in config-yaml for every key and default, the mental_models and memory_usefulness / evicted_at storage, and the counts-only trajectory telemetry (reflect:admitted / reflect:funnel for the reflection funnel; learning:memory_demoted / learning:memory_evicted for the forget sweep) surfaced through comis explain and comis fleet.

Strict config schema

The config schema is strict (z.strictObject): a config.yaml that carries an unrecognized key is rejected at boot with a parse error naming the exact key, so a typo or an unsupported block is pointed straight at the line to fix. A bare config (memory:/agents: with no learning keys) loads fully-defaulted.

Dependencies & gotchas

  1. Some capabilities need built derived state, not just the flag:
    • KG (rag.lanes.graphSpread) is a no-op until the knowledge graph is populated with entities/edges.
    • FORGET decay (rag.forget) shows up at recall; eviction is the memoryLifecycle sweep — live as soft, reversible eviction (evicted_at) when learning.enabled is on (it reads learning.forget.*), exempting pinned/system/high-proof memories. See the one learning-reflection engine.
    • Reflection needs a stream of trusted-origin successful outcomes to learn from — it gates on the learningOutcome signal, and abstains (a benign skip, never a failure) when a run finds no corroborated success.
  2. dialectic (memory_ask) spends tokens per ask — it is the only query-time LLM surface in the memory stack. Everything else in recall is LLM-free.
  3. Trust is frozen, not a tunable capability. rag.scoring.trustAlpha and rag.includeTrustLevels are the trust hard-boundary; leave them at the shipped values.
  4. On by default — watch your spend. The LLM build/ask features are opt-out so operators get the full memory stack from day one; they spend your own budget. Your controls are the first-run notice and the master switch memory.enabled: false (or per-feature enabled: false). Measure the effect in your own domain — Comis’s honest, reproducible methodology and the latest costed results are on the Memory benchmarks page.
See also: Memory · Search · Embeddings · RAG.