rag.scoring.trustAlpha, rag.includeTrustLevels) is frozen — not a tunable capability.
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.*).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 relevantenabled: 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 flag — agents.<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 attrust=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 exceedlearnedtrust (a DBCHECKmakessystemstructurally impossible). An admittedcandidatepromotes toactiveonce itsproof_countcrossespromoteAtProofCountfrom attributed successful reuse; an active doc demotes (active→stale→archived) 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’shistory, 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-successfulorchestrateruns — akind:"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, default10) — 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-attributedfailure_count, so wrong fades faster than merely old, and soft-evicts a sufficiently weak or stale memory: it is markedevicted_at(excluded from recall, still resolvable viaasOf/inspect, reversible, never hard-deleted). A memory implicated infailureEvictionFloor(default 3) or more corroborated failures is soft-evicted regardless of its decayed strength, while a memory at/abovehighProofFloor(default 5) is exempt. A corroboration gate (≥2 independent failures, or one deterministic source, on everyfailure_countincrement) plus exemptions for pinned /system/ high-proof_countmemories 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 keylessmemoryLifecyclecron (__LIFECYCLE__).
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. Insingle_ownermode the engine counts an explicitly-trusted owner’s repeated successes: when the owner succeeds at the same task ≥minObservationstimes (default2, 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.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
- 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 thememoryLifecyclesweep — live as soft, reversible eviction (evicted_at) whenlearning.enabledis on (it readslearning.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
learningOutcomesignal, and abstains (a benign skip, never a failure) when a run finds no corroborated success.
- KG (
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.- Trust is frozen, not a tunable capability.
rag.scoring.trustAlphaandrag.includeTrustLevelsare the trust hard-boundary; leave them at the shipped values. - 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-featureenabled: false). Measure the effect in your own domain — Comis’s honest, reproducible methodology and the latest costed results are on the Memory benchmarks page.
