---
name: memorylayer
description: Reference guide for MemoryLayer MCP tools. 4 unified tools: remember (write), recall (read), code (codebase), consolidate (maintenance). Use when deciding which tool to call, understanding search modes, or troubleshooting why recall returned nothing.
---

## The 8 tools

| Tool | Purpose | Replaces |
|---|---|---|
| `remember` | Write anything | upsert · update · delete · chunked_store · batch_store |
| `recall` | Read anything | search · answer · weave · load · list · related · skill_load |
| `code` | All code intelligence | ingest · locate · impact · grep · load_symbol |
| `consolidate` | Maintenance + ACT-R compose | memory_consolidate · pruner_run |
| `audit` | Batch Z3 invariant checker | manual prove() loops |
| `domain` | Formal domain management | load_domain · export_domain · domain_status · set_domain_mode |
| `prove` | Z3 formal proof | direct prove() calls |
| `verify` | Hallucination gate — check text claims against stored knowledge | — |

## recall — intent routing

recall auto-routes based on query shape. You don't pick the sub-mode:

- `"what calls X?"` / `"imports"` / `"inherits"` → triple lookup (proven facts)
- `"explain how X works"` / `"how does"` → context bundle
- `"find ClassName"` / PascalCase name → symbol lookup
- `explore: true` → weave: result + tag/temporal/semantic edges expanded
- No query → list recent entries
- Bare id → direct load

**Tag matching:** `tags` default to **AND** — a result must carry *every* tag. For an OR/union
(e.g. load anything tagged rule, constraint, *or* guide) pass `match: "any"`:
`recall({ tags: ["rule","constraint","guide"], match: "any" })`. Priority-memory loads must use
`match: "any"` or they match almost nothing.

## Proven answers (default)

Closed relational questions are answered **proven-first**, automatically — no flag needed:

- `recall({ query: "does AuthService call validateToken?" })`
- `recall({ query: "is HNSW a kind of index?" })`

When the relation can be proven from the triple graph, recall returns
`{ verdict: "yes", confidence: "proven", proof: [...chain] }` at **zero LLM cost**. If it can't
be proven it falls back to normal semantic recall (best-effort). Trust the `confidence` field:

- `proven` — formal proof chain (authoritative)
- `retrieved` — found in the triple store / vector search (best-effort)
- `unsupported` + `abstained: true` — honestly not known

For a single high-stakes claim outside a closed relational question, call `prove({ claim })`
directly — it returns a full proof certificate (verdict, proof steps, axioms used) rather than
a best-effort recall result. Use it before acting on a claim you can't afford to be wrong about.

**Need certainty, not best-effort?** Pass `require_proof: true` — recall then abstains
(`{ proven: false, reason: "unsupported" }`) instead of guessing. Use it for high-stakes facts;
leave it off (default) for everyday recall. Open enumeration ("what calls X?") still lists all
matches from the triple store.

## code — actions

- `action: "ingest"` + path → bulk import code symbols
- `action: "locate"` + intent → pinpoint symbol, 20-line preview, callers
- `action: "impact"` + name → callers, callees, test files, regression risk
- `action: "grep"` + pattern → raw regex search

## Tool flow

**Before reading files:**
1. `recall({ query, namespace })` — hybrid semantic + keyword
2. `recall({ query, namespace, explore: true })` — + relational expansion
3. `code({ action: "locate", intent, namespace })` — if code-specific
4. `code({ action: "grep", pattern, namespace })` — last code resort
5. Read / Bash — only if all above return empty

**After significant work:**
- `recall({ query: "<topic>", namespace })` first — check whether this is already known
- No hit → `remember({ content, namespace, tags?, priority? })` — genuinely new finding
- Hit, but the fact changed → `remember({ id, content })` — update in place, don't duplicate
- Hit shows multiple stale/conflicting entries on the same topic → `consolidate({ action: "ripple", namespace })` first to clean up, then write
- `remember({ content: longDoc, namespace })` — auto-chunks if >4000 chars

Auto-dedup only catches near-identical wording, not "the same fact restated" — the
recall-first check above is what actually prevents stale duplicates from piling up.

## Scenario quick-pick

Match your question to the fastest tool path:

| Scenario | First call | Fallback chain |
|---|---|---|
| "What calls X?" / "imports" / "inherits" | `recall({ query })` — auto-routes to triple lookup | `code({ action: "impact" })` for blast radius |
| "Find X" / "where is X" / symbol lookup | `code({ action: "locate" })` | `code({ action: "grep" })` → `recall({ intent: "find_symbol" })` |
| "How does X work?" / broad investigation | `recall({ explore: true })` | `code({ action: "locate" })` → `code({ action: "impact" })` |
| "What do I know about X?" | `recall({ query })` | `recall({ explore: true })` |
| Writing / saving a finding | `recall({ query })` first, then `remember({ content, namespace })` if new | `remember({ action: "update", id, content })` if it already exists |
| High-stakes single claim before acting on it | `prove({ claim })` | `verify({ text })` if it's prose with multiple claims |
| Codebase cleanup / TTL prune | `consolidate()` | — |
| Session has stale/conflicting memories on one topic | `consolidate({ action: "ripple", namespace })` | — |
| Verify claims / hallucination check | `verify({ text, domain? })` | — |
| Architectural contracts / invariants for this project | `domain({ action: "load", source })` | — |
| CI-style check across a loaded domain | `audit({ domain })` | — |
| Teach a new procedure (formula or text checklist) | `consolidate({ action: "teach", name, trigger, expr? , steps? })` | — |
| Compile ACT-R procedure chunk from taught procedures | `consolidate({ action: "compose", name, trigger, steps })` | Teach each step first |

The hook injects a "Scenario detected" line when it recognises your intent — follow it when present.

## Core operating cycle

Use these ops every session — they're what makes MemoryLayer a thinking layer, not just storage:

| Op | Call | What it does |
|---|---|---|
| **THINK** | `recall({ query, explore: true })` | Surfaces related associations + open loops, not just the top vector match |
| **LEARN** | recall first (see "Before every remember" below), then `remember({ content, namespace })` | Extracts triples + salience → sets priority 1–10 automatically. Recall-first is what prevents stale duplicates. |
| **VERIFY** | `verify({ text, domain? })` | Splits prose into claims, checks each against stored knowledge → `grounded` / `refuted` / `unsupported` per claim |
| **PROVE** | `prove({ claim })` | Formal proof certificate for one high-stakes claim — stronger guarantee than a `verify` verdict |
| **SLEEP** | `consolidate({ action: "ripple" })` | Replays recent memories → derives transitive facts, surfaces contradictions, promotes stable patterns to formal axioms |

**When to run each:**
- **THINK**: any "how does X relate to Y?" or exploratory question — use `recall(explore:true)` instead of plain recall
- **LEARN**: after every significant finding — but recall first every time, not just on the first write
- **VERIFY**: before stating facts; after recall returns results you'll repeat to the user; after a subagent finishes
- **PROVE**: before acting on a single claim you can't afford to be wrong about, or when the user challenges a fact you stated
- **SLEEP**: at session end, before context compact, after heavy knowledge work, or whenever a recall-first lookup turns up stale/conflicting entries on the same topic

**`verify` result fields:**
- `grounded` — claim confirmed (taught or derived)
- `refuted` — actively disproved (Z3 formal contradiction when domain loaded)
- `unsupported` — not known yet; may still be true, just not taught
- `hallucinations[]` — the subset of claims that are `refuted`

## Namespaces

MemoryLayer supports both a global default and directory-scoped namespaces.
- **Directory-scoped** (preferred): `memorylayer namespace set <name>` or choose "current dir" during setup.
  Stored in `~/.memorylayer/namespaces.json` — most specific path match wins.
- **Global default**: `memorylayer setup --namespace <name>` (stored in `~/.memorylayer/namespace`).

Check active namespace for CWD: `memorylayer namespace get`
List all mappings: `memorylayer namespace list`

List all namespaces with memory counts, plus each one's group (in-tool, no CLI needed):
`recall({ view: "namespaces" })`.

**Searching several namespaces at once (namespace groups).** By default every `recall()` targets
exactly ONE namespace. When one body of work is split across namespaces (e.g. `mem-layer` for
design + `mem-layer-bugs` for defects), declare a group once and then search it in a single call:

```
remember({ namespace: "mem-layer",      group: "memorylayer" })   // declare membership
remember({ namespace: "mem-layer-bugs", group: "memorylayer" })
recall({ query: "...", group: "memorylayer" })                    // searches both, one query
```

- `remember({ namespace, group: null })` removes a namespace from its group.
- `recall({ namespaces: ["a","b"] })` is an ad-hoc scope without declaring anything (max 50).
- Multi-namespace responses echo `searched_namespaces` so you can see what actually answered.
- An **unknown group returns no results** rather than silently searching everything — so a typo
  shows up as an empty result, not a full-database scan.
- Groups are **declared, never inferred from names**. Don't assume `foo` and `foo-bar` are grouped.
- **Writes are always single-namespace.** `group` only widens reads; `remember()` still stores into
  the one `namespace` you pass. A project convention about *where bugs go* still governs writes.
- Not supported with `explore: true` (the weave edge-expansion contract takes one namespace) —
  you'll get a clear error telling you to drop `explore` or pass a single namespace.

**Scope policy (soft, flag-don't-reject):** a namespace can declare a scope so out-of-scope
writes get flagged instead of silently drifting. Set/clear: `remember({ namespace, policy:
"<description>", policyPattern?: "<regex>" })` (pass `policy: null` to clear). Read it back:
`recall({ namespace, view: "policy" })`. Without `policyPattern` the description is
documentation only — matching content isn't enforced. With a pattern, non-matching `remember()`
calls still store but get tagged `policy-flagged`/`out-of-scope` with `metadata.policy_violation`,
and the response includes a `policy_warning` field.

## Writing content that grounds cleanly (remember)

`remember()`'s triple extraction works best on **short, atomic, single-clause
subject-verb-object sentences** ("Raaj requires reproducing a bug before
fixing it.") — dense multi-clause narrative paragraphs usually fail to
extract a clean triple and later show as `unsupported`/`unparsed` on
`verify()`, even though the content is stored and searchable fine.

This is a known parser accuracy ceiling (some verb/noun homograph pairs —
e.g. "verifies"+"claims", "maps"+"callers" — can be mis-tagged by the
dependency parser regardless of phrasing), not a bug to work around per
call. **Product decision (2026-07-08): remember() does NOT accept or
enforce a structured `{subject, relation, object}` input format** — pushing
that decomposition onto the calling agent trades one accuracy problem
(parsing free text) for another (agents reliably self-decomposing facts),
for a feature that may not be worth the engineering cost. Not planned now;
may revisit later.

Practical guidance instead: when a fact matters for `verify()` grounding,
phrase it as one short SVO sentence per fact rather than a paragraph. If it
comes back `unsupported`/`unparsed` after that, it's likely a parser
limitation, not a content problem — don't burn time rewording it repeatedly.

## Priority (remember)

- `5` (default) — general context
- `8–10` — must-not-miss: hard constraints, security rules, landmines

## Dedup threshold

ONNX embeddings score ~10% lower than PyTorch for same content. Default threshold calibrated at ~0.85 (not 0.92).

## WCM engine states (prove / verify / audit / domain / consolidate)

Those five tools run on the WCM cognitive engine, a separate native process. If one returns an
error, the `error` field tells you what to do — don't retry blindly:

| `error` | Meaning | What to do |
|---|---|---|
| `wcm_booting` | Engine is starting. First launch after install/upgrade unpacks a large model payload — up to ~2 minutes. | **Retry shortly.** It will work. Meanwhile `remember`, `recall` and `code` are fully functional. |
| `wcm_timeout` | Engine is warm but this specific request overran its budget. | Retry with a **smaller input** — shorter text, fewer claims, narrower domain. Retrying the same thing won't help. |
| `wcm_unavailable` | Engine isn't running: the platform binary is missing or failed its integrity check. | Don't retry. Cognitive features are offline for this session; everything else works. `memorylayer info` shows status. |

All three carry a human-readable `message`, and a `retry` boolean so you don't have to
pattern-match the code. **A WCM error never means memory is broken** — storage, search and the
code tools do not depend on it.
