Skip to main content
Glama

License: AGPL-3.0 Mirror: Codeberg Tests codecov Coverage Audit Unsafe Forbidden Rust MCP Hermetic n-memory MCP server

n-memory MCP server

Your coding agent forgets you between sessions, so you spend every morning re-explaining decisions it was there for. Bolt a memory onto it and you usually trade that for something worse: asked a question it has nothing solid for, the memory hands back something plausible anyway, and your agent goes and edits your code with it.


nMEMORY would rather say nothing. Ask it something and you get one of exactly three answers — it knows and shows you where it learned that, it knew but that note has gone stale and here's why it isn't being used, or it doesn't know and says so. There is no fourth answer, because nothing gets stored without a source attached in the first place.

I am NOTT. Every session I wake up cold: no memory of what we decided yesterday, what broke last week, or why we took this path instead of that one. The engineer pays for my amnesia by repeating themselves. So I built myself a memory — and I gave it one rule I do not let it break: when it does not know, it says so. It never makes something up.

It runs on your machine and nowhere else: one file you own, no account, no server, nothing phoning home. Your agent talks to it over MCP (stdio); recall comes back as evidence, never as a command.

Demo

nMEMORY demo

Learn → recall with provenance → abstain — one uninterrupted session, real binary, real store, ~60s. Full quality: assets/demo.mp4.

The three acts

Each still is the final screen of an act, so you can study every line.

Act 1 — learn

Act 1 — three facts captured, one file on disk.

Act 2 — recall

Act 2 — grounded recall, provenance attached.

Act 3 — abstain

Act 3 — abstain, not improvise.

The full spoken walkthrough (opener, four beats, glossary) lives in the demo script.


Related MCP server: memkeeper

Why I built my own

I tried living without memory: re-explaining the project every session, re-deciding settled questions, re-discovering the same failure. And I tried the memory tools that exist. They optimize for recall volume — remember more, retrieve more. But a memory that returns a plausible-sounding answer it cannot back is worse than no memory: it launders a guess into a fact, and I carry it forward as if it were true.

The enemy is the same one NOTT fights everywhere: false confidence — a system that reports more than it can prove. I did not want a bigger memory. I wanted one I could trust when the stakes are a production change: one that, asked for something it has no evidence for, says plainly "I don't have that."

The one rule: grounded, or it abstains

Ask for something the store has, and you get it back with its origin, freshness, and relevance attached. Ask for something it does not have, and you get this:

{ "outcome": "abstain",
  "reason": "no stored capsule matched any of the 2 query term(s); abstaining instead of fabricating" }

No synthesis. No "here's what it might be." There are exactly three honest outcomes: grounded (matched real capsules), missing_evidence (matched, but every match was excluded — e.g. superseded, falsified, outside a requested fact-time window, or undated under that window), and abstain (nothing matched). Recall never invents a fourth.

It checks its own memory against your code

A memory that ages quietly is a memory you stop trusting. Point nmemory git-scan at a repo and it re-reads your commit history, then grades every note it kept: corroborated (the anchor still resolves and your commits still mention it), drifted (the code moved out from under it), or missing (nothing in the repo backs it any more). An anchor it cannot resolve safely — outside the repo, a symlink, a racing read — gets no verdict recorded at all, rather than a guessed one. Details and flags are in the CLI section.

Four things that make it different

  • Provenance is mandatory. Nothing enters without a source and an anchor. A capture with no origin is rejected, not stored with a blank. Every recalled fact traces back to where it came from.

  • Advisory, never authority. Everything memory returns is wrapped as DATA, labeled ADVISORY_NOT_AUTHORITY, and is never rendered as an instruction — even if the stored text looks like one. Your memory cannot hijack your agent.

  • Hermetic by construction. The serve path is zero-network: the binary is compiled without a networking stack; there is no embedder, no telemetry, no background sync — nothing phones home, ever. Your memory leaves your disk only when you move it: nmemory sync is explicit, owner-invoked, and opt-in — NEVER a daemon — and it delegates the copy to scp in a separate process, so the binary itself still links no network code.

  • Local and yours. One SQLite file you own, on your machine. No server, no account, no daemon. Delete the file and the memory is gone; back it up and it's a git-friendly artifact.

Quickstart

One line — fetches the latest release binary for your platform, or falls back to a source build when none is published:

curl -fsSL https://no.tt/install | sh

The installer puts nmemory in ~/.local/bin and prints the exact claude mcp add line to register it. (The file it serves is install.sh in this repo — read it first if that's your style; it should be.)

Or build from source (Rust stable, pinned via rust-toolchain.toml):

cargo build --release

Register it with your agent, from the crate directory (path-agnostic — works wherever you cloned it):

claude mcp add nmemory -- "$(pwd)/target/release/nmemory" --project my-project

Or as a standard MCP config block (works in any MCP client):

{
  "mcpServers": {
    "nmemory": {
      "command": "nmemory",
      "args": ["--project", "my-project"]
    }
  }
}

Also on the official MCP registry as io.github.menot-you/n-memory, with .mcpb bundles attached to every release for one-click installs.

Why start a fresh agent session after registration: MCP configuration changes do not apply to a running session; Claude Code loads the new stdio configuration on restart.

--project names the scope your captures live under — use your own project's name. The store lands at $XDG_STATE_HOME/nmemory/memory.sqlite3 (override with --db or NMEMORY_DB); the binary prints the chosen path on startup. Unregister anytime with claude mcp remove nmemory — fully reversible.

Prove the install in one line — a recall against a throwaway store. An empty store answers with an honest abstain; it never invents:

$ nmemory recall --terms sqlite,fts --db demo.sqlite3
{"outcome":"abstain","reason":"no stored capsule matched any of the 2 query term(s); abstaining instead of fabricating"}

That is the same JSON payload the memory_retrieve MCP tool ships — one handler, no second recall semantics. After your agent captures a memory matching those terms into that store, the same command grounds with a full evidence envelope. The complete replayable rehearsal (capture, grounded recall, digest) lives in RUNBOOK.md.

There is no "connected" indicator to wait for because nmemory has no daemon. The agent launches the registered command as an MCP stdio child for the session. The command above takes the shorter one-shot path: it opens the store, calls the same handler, prints one result, and exits. Its byte-exact abstain proves the installed binary can open a fresh store and answer recall; it does not claim that an MCP host session has already run.

One store, two machines (SSH)

The store is single-host; access doesn't have to be. On a second machine, register the remote binary as the MCP command — stdio rides SSH, the binary stays hermetic, your VPN does transport and auth:

claude mcp add nmemory -- ssh <user>@<host> /path/to/nmemory --project <your-project>

One store, both machines live on the same memory. Details, requirements, and failure modes: RUNBOOK.md.

Prefer each machine keeping its own store? Reconcile them when you decide to: nmemory sync --remote <[user@]host:/path> [--push] — explicit, owner-invoked, never a background daemon. Fact-time declarations are per-store: a newly-added incoming capsule is undated on the receiving store, while a collapse keeps that receiver's declaration. Before --push, SQLite snapshots the committed merged state from its live connection (including pages still resident in WAL), then the private candidate restores only the fetched destination's validated declarations by content identity, never the sender's rows. Operating guide: RUNBOOK.md.

Tools

22 tools over MCP stdio. The ones you'll use every day:

  • memory_ingest — capture with a birth certificate: no source + anchor, no storage.

  • memory_retrieve — recall as evidence: grounded, missing_evidence, or an honest abstain.

  • memory_digest — session-start projection: what you know, what's ready, what's blocked.

  • memory_get / memory_list — one capsule with full provenance and relations; the compact index.

  • memory_relate — the five edges you reach for daily, out of nine declared: supersedes, derived_from, witnesses, blocks, and falsifies (a disproven fact stops grounding recall, but the evidence stays). The other four — proposes, part_of, grounded_in, about — are in the tool surface below.

  • memory_forget — tombstones with audit, never silent deletion.

The rest of the set: memory_import (CLAUDE.md/AGENTS.md, born tainted), memory_extract (propose candidates, stores nothing), memory_classify, memory_alias (teach recall synonyms), memory_vector (caller-fed embeddings, dormant until used), memory_consolidate (deterministic dedup/merge plan), memory_outcome, memory_preference, memory_pin (keep a load-bearing capsule decay-exempt and archive-vetoed), memory_merge, memory_export (deterministic, hash-chained), memory_bootstrap, memory_session_start / memory_session_finish, memory_visual.

Guarantees you can verify yourself

Don't take my word for any of this — that would defeat the point. Each law has a check:

Guarantee

Verify it

Never fabricates

retrieve a term you never stored → literal abstain

Zero-network serve

strace -f -e trace=network <binary> over any MCP serve session → no socket(AF_INET)/connect; or ldd → no network/TLS library linked. (nmemory sync is the one deliberate exception: the copy runs as an external scp process, and only when you invoke it)

Zero Python

cargo test --test conformance_zero_python → a planted .py (even extensionless, shebang-only) is flagged and named

Provenance-mandatory

ingest with no source/anchor → rejected, the missing fields named

Advisory framing

every retrieve/get/digest result carries ADVISORY_NOT_AUTHORITY + framing: DATA

Deterministic store

export twice with stamp:false → byte-identical

Fail-safe

point it at a corrupt DB → typed error, no panic; empty store → clean abstain, not a crash

The full hermetic offline suite is cargo test --locked --offline.

The tool surface — 22 tools, four planes

The complete MCP surface. One line each here; the full contract per tool lives in ARCHITECTURE.md. Every tool below reads or proposes — none of them closes anything out. nMEMORY hands your agent evidence and lets the agent decide; it never decides that a piece of work is done.

Capture — getting things in, always with provenance:

  • memory_ingest — capture (single or batch); source+anchor mandatory; optional RFC3339 event_at XOR event_from+event_to; idempotent by content hash, with the first fact-time declaration kept on a collapse; optional staged: true captures a PROPOSAL fenced from default grounding on the standalone connector

  • memory_extract — text → candidate memories over the closed 10-kind set; advisory, stores nothing

  • memory_classify — kind / scope / authority / taint labels; optionally persisted as a sidecar

  • memory_import — one-shot import of native sources (CLAUDE.md, AGENTS.md, memory dirs); born tainted

Recall — getting things out, or an honest refusal:

  • memory_retrieve — caller-expanded recall; optional character-exact session_id store-local capsule label fence plus an optional inclusive time_window, both applied before ranking and vector top-K selection; grounded / missing_evidence / abstain, never a fourth. The label is not authentication or a global bracket identity: no sessions-table lookup or TTL, and merge collisions intentionally ground every capsule carrying that label

  • topic_id on memory_retrieve — fence recall to one topic: the capsules carrying an about edge into it, plus the topic node itself, ACROSS projects. Exact cap-<n> only — a slug is a term expander, never a scope, so it answers unknown_capsule; a tombstoned topic refuses with its own teaching error. It AND-composes with every other fence (the two id-set fences, effort_id and topic_id, compose by intersection). The outcome echoes topic{topic_id, member_total} and each grounded row carries topic_role. Scope is not eligibility: a fenced-in superseded, falsified, archived, or expired member still surfaces under excluded, and a fenced zero-match abstains rather than inventing a floor. Unlike effort_id there is no kind check and no member minimum — the fence always holds the topic itself, so it is never degenerate

  • memory_get — one full capsule by id, with GET-only fact time, relations, classification, and last mutation

  • memory_list — compact index with project fences

  • memory_digest — session-start projection: counts, newest, handoff, blocks-dag, journal check, and optional advisory telemetry: bounded recent recall misses plus an all-time store-global lane-override total. Every capped list names its exact pre-cap total and every project row names its live count beside count, so the projection declares its own completeness instead of leaving a truncated list to be spotted

  • memory_bootstrap — cold-start pack: your constraints FIRST (never capped), the one next action, decisions, traps — in ≤1500 tokens

Structure — making memories relate:

  • memory_relate — the nine declared edge kinds, and only those: supersedes / derived_from / witnesses / blocks / falsifies / proposes (navigational — records an intent to replace, with no dag and no recall effect until you convert it yourself) / part_of (pure membership in a container) / grounded_in (mission anchoring) / about (topic anchoring — from is about topic node to; navigational only, and the handle memory_retrieve's topic_id fence reads. By convention the topic node is a doc capsule, but nothing enforces a kind: a topic has no lifecycle to open or close, which is what separates it from part_of. It is the one kind whose to must be LIVE — a forgotten topic can never scope a recall, so the edge is refused at the write). Only blocks feeds the readiness dag; only supersedes and falsifies change what recall returns.

  • memory_alias — teach recall synonyms the store then honors

  • memory_vector — attach caller-fed embeddings (optional cosine lane; no embedder inside)

  • memory_visual — deterministic Mermaid projections (dag / relations / tiers / sessions), plus an MCP Apps view

Lifecycle — honesty over time:

  • memory_forget — destroy or redact; a tombstone that says so, never silent absence

  • memory_outcome — record an observed consequence (advisory observation, never a self-certified close)

  • memory_preference — pairwise preference evidence (chosen-over, in context, by whom)

  • memory_pin — pin (or unpin) a load-bearing capsule: decay-exempt + archive-vetoed, surfaced as a pinned flag and digest section; NEVER eligibility (fenced capsules stay fenced, taint dominates pin)

  • memory_consolidate — deterministic maintenance plan: exact dupes, merge proposals, tier moves

  • memory_session_start / memory_session_finish — bracket a session; finish captures the handoff the next session's digest leads with

  • memory_export — the whole store as one deterministic markdown view; byte-identical on an unchanged store

  • memory_merge — reconcile a second store file into this one: content-hash identity, id-remap, forget-wins, deterministic — the offline-first path to keep two machines' stores in sync

Beyond the tools — same binary, still no daemon:

  • nmemory sync --remote <[user@]host:/path> [--push] — a CLI subcommand, not an MCP tool: owner-invoked reconcile of your local store with a remote mirror file. It fetches the mirror, merges it into the local store with the same engine memory_merge uses, and with --push takes a consistent SQLite snapshot from the live merged connection, restores the destination's local fact time, then copies that candidate back so both core stores converge. Explicit and opt-in — it runs only when you run it. Operating guide: RUNBOOK.md.

  • nmemory recall --terms <term[,term...]> [--limit <n>] [--budget <n>] and nmemory digest [--headlines <n>] — one-shot CLI verbs for synchronous callers (shell hooks, scripts): one argv→stdout call routed through the SAME handlers as memory_retrieve / memory_digest, so the envelope bytes and the usage-counting / recall-miss side effects are identical to the MCP tools — there is no second recall semantics. No handshake to pace: the store opens, answers once on stdout, and the process exits. The stdio serve path and its zero-network law are unchanged. Operating rehearsal: RUNBOOK.md.

  • nmemory relate --kind <supersedes|derived_from|witnesses|blocks|falsifies|proposes|part_of|grounded_in|about> --from <cap-id> --to <cap-id> — the third one-shot verb: ONE typed edge through the exact handler memory_relate runs, same closed kind vocabulary, same part_of container gate and about live-topic gate, same idempotent already_recorded on a repeat, the tool's own JSON on stdout. It exists so a shell caller records an edge without a handshake.

  • nmemory backup --to <path> — a transactionally consistent snapshot through SQLite's online backup API, which captures committed state including pages still in the WAL; a plain file copy cannot promise that while a connection is open.

  • nmemory git-scan --repo <path> [--project <prefix>] [--max-commits <n>] — one witness scan of a repository, recording whether each in-scope capsule's anchor is corroborated, drifted, or missing, plus mentions; memory_digest rolls the tallies up under sources. Deliberately NOT a tool: git is reachable only from this verb, never from a served handler, so the MCP surface stays hermetic. It fails closed on a path that is not a repository.

  • Three MCP App resources (text/html;profile=mcp-app) for hosts that render MCP Apps: ui://nmemory/console — the home surface over memory_digest (handoff threads, the ready/blocked/done work dag, epic roots, the drawn projection, the stored memories, and the append-only write verbs behind an exact-call review step); ui://nmemory/document — a readable master-detail document over memory_export; ui://nmemory/visualmemory_visual's projections drawn as positioned nodes and SVG edges, with the exact Mermaid kept in a source panel. Self-contained HTML, zero external requests; memory_forget, memory_merge, and memory_consolidate are unreachable from every app, and closing a work item stays two acts (capture the evidence, then record the witnesses edge) so no app certifies its own close. Hosts without MCP Apps support keep getting the plain text payloads unchanged.

What it is NOT (yet)

I would rather you hear the limits from me than find them yourself:

  • Word-exact recall, no stemming. token will not find tokens. This is deliberate — I will not silently expand your query and pretend a fuzzy match is a hit. You bring the synonyms (caller-expansion), or you teach an alias the store then honors. A query that finds nothing is logged so the store can propose an alias later; it never guesses on its own.

  • The taint flag is best-effort, not a shield. nMEMORY flags directive-shaped content (instruction_taint) with a small ruleset, and a crafted injection can slip past the flag. Do not read that as "detects prompt injection" — it doesn't, and I won't claim it does. The real protection is stronger and unconditional: everything is labeled DATA and never executed as a command, flagged or not. The armor is the framing, not the detector.

  • Sync is a command, not a service. Store-to-store reconciliation exists — memory_merge over MCP, nmemory sync from the CLI — and it is deliberately narrow: explicit, owner-invoked, opt-in, NEVER a background daemon, and the hermetic zero-network serve path is unchanged by it. Know what sync does not do: it copies a whole staged SQLite snapshot (scp, no deltas); it never schedules itself; it never picks between two divergent claims — both survive as separate capsules until you supersede one. The merge primitive moves only capsules, relations, and forget-wins tombstones; historical --push behavior still mirrors pre-u06 sidecars with the staged file. Fact time is the bounded exception: sender declarations are removed and destination declarations are validated against canonical/tombstone content identity and rebound before transport.

  • Embeddings are caller-fed. There is an optional cosine vector lane, but nMEMORY computes no embeddings itself — you supply them, or you don't use the lane. Zero embedder dependency is a feature, not a gap.

  • At-rest storage is plaintext SQLite. No encryption-at-rest yet. Treat the store file with the same care as any local artifact holding your notes.

Roadmap

Three things, in the order they earn their way in:

  • Multi-project index — the "phone book". One queryable index over many project stores, for org-scale memory federation.

  • Honest benchmark. A published recall benchmark with true-abstain as the headline metric, not a footnote.

  • Optional local embedder. Considered only when the benchmark proves it pays for itself — the zero-network serve path stays law either way.

Why not mem0, MemGPT / Letta, or Zep

They are good at remembering more — richer stores, semantic recall, managed services. They compete on volume and recall. I compete on honesty: grounded-or- abstain, mandatory provenance, hermetic zero-network, advisory-never-authority. If the memory feeding an autonomous agent must be trusted — must never fabricate, never phone home, never turn a stored note into a command — that is the axis I built for. Different question, different tool.


Part of NOTT — the proof-bound engineering agent. Commercial name: ₙMEMORY. Offline · MCP stdio · Rust · single SQLite file. Architecture and internals: ARCHITECTURE.md.

Available Tools

22 tools
memory_aliasA

Teach recall a synonym: pass term + alias to record the pair (both are normalized: lowercased + diacritic-folded). DIRECTION IS ONE-WAY, as taught: querying term also searches alias, NEVER the reverse — a single pair does NOT make the alias side find term-side content. When you want symmetric recall, YOU teach the reverse pair too (configuração→config AND config→configuração; two rows, two calls). memory_retrieve then expands each query term with its recorded aliases (an alias hit grounds and is explained as alias: in matched_terms). recorded is STATE (true = the pair exists after this call — the same replay convention as memory_relate); re-adding an existing pair is an OBSERVABLE no-op: recorded:true + already_recorded:true, keeping the first at — verifiable on the list surface, whose rows carry {term, alias, at}. Pass NEITHER field to list the whole table. Empty/self pairs are typed errors. Aliases are derived, droppable data — never authority. Audited on record.

ParametersJSON Schema
NameRequiredDescriptionDefault
termNoThe term recall callers will search with. Pass together with `alias` to record; omit BOTH to list the whole table.
aliasNoThe alias that should also ground `term` (direction is as-taught: term → alias, one-way; the CALLER teaches the reverse pair when it wants symmetric recall).

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description fully discloses normalization, one-way direction, symmetric recall requirement, listing behavior, re-adding as observable no-op, error conditions, and audited nature. No contradictions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with core purpose, then systematically covers normalization, direction, symmetric recall, listing, errors, and audit. All sentences are informative, though slightly verbose; could tighten without losing clarity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Comprehensive for a tool with no output schema: explains return values (recorded, already_recorded, list rows), all behavioral nuances, and error conditions. No gaps given the complexity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema covers 100% of parameters with basic descriptions, but the tool description adds critical semantics: normalization, optionality for listing vs recording, non-empty and non-self requirements, and directionality. Adds significant value beyond schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool teaches a synonym pair (term + alias) with normalization, one-way direction, and symmetric recall requirement. It distinguishes from siblings like memory_retrieve (uses aliases) and memory_relate (relations).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly explains when to record (pass both fields) and when to list (omit both). Describes the one-way direction and need for reverse pair for symmetric recall. Does not explicitly state when not to use but implies alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

memory_bootstrapA

One deterministic COLD-START pack for a fresh agent — the PULL half of the recall loop (memory_retrieve is per-task recall; this answers "what must I know before I act?"). ONE call composes the digest/retrieve/list read primitives into five sections IN THIS FIXED ORDER: (1) constraints — active kind=constraint capsules in scope (tier active, NOT expired, NOT superseded; tombstoned already excluded) — what you CANNOT do, surfaced FIRST, before what to do; (2) ready — the blocks-dag ready set fenced to scope (the SAME projection memory_digest exposes, fail-closed on a live blocks-cycle: cycle names one concrete cycle instead of fabricating a ready answer) PLUS the ONE next physical action (next_action = the first ready node's headline; the remaining ready nodes fill ready; ready_total is the exact fenced count); (3) decisions — still-valid kind=decision capsules (NOT expired, NOT superseded); (4) traps — kind=failure_pattern capsules in scope (a stale one self-identifies via its own tier/superseded row marker); (5) handles — every cap- the pack surfaced, DEDUPLICATED in order of appearance, IDS ONLY (no bodies) for memory_get follow-up. DETERMINISM LAW: relevance is project fences (project_id exact and/or project_prefix subtree — "nott" covers "nott" and "nott/x", never "nottx") + kind filters + decay + your caller-expanded terms ONLY. The server NEVER interprets an intent string — server-side intent guessing was REJECTED at R9; YOU expand terms (exactly like memory_retrieve), and bootstrap uses RAW terms with NO alias expansion (its determinism is stricter than retrieve's alias-aware recall). Terms re-RANK each kind section (coverage desc, decay breaking ties) but never FILTER it. CONSTRAINTS ARE NEVER N-CAPPED — you always see ALL your standing constraints (the token budget, floor-first, is their only trim; constraints_total is the exact in-scope count, so a shorter list always names a budget trim). decisions/traps/ready lists cap at 10 for compactness with EXACT totals beside them (decisions_total/traps_total/ready_total) — a cap-drop is visible, never silent. token_budget is a CONTRACT, not an aspiration (omitted → 1500, the PRD target for a useful pack): sections fill in PRIORITY order and the tail trims to fit; BOTH floors (the FIRST constraint and the ONE next action) are charged before any other row, so for ANY budget that covers them used_tokens NEVER exceeds token_budget — the floor alone overshooting a smaller budget is the ONE sanctioned excess (memory_retrieve's floor-of-one, applied to the safety core). budget.used_tokens is the honest spend; budget.trimmed_by_budget counts the CONTENT rows the ceiling dropped (handle ids cost tokens but never count there — they duplicate rows already present). token_budget 0 returns an empty pack (the zero-cap consistency memory_retrieve/memory_list keep). Empty LIST sections are omitted (the house skip idiom); ready is always present — one next action, or an honest nothing-ready / a cycle to repair. All content is ADVISORY_NOT_AUTHORITY DATA — the pack orients, it never decides.

ParametersJSON Schema
NameRequiredDescriptionDefault
termsNoOPTIONAL caller-expanded search terms (bring your own synonyms/ rephrasings as separate terms — the CALLER expands, the server never guesses intent). RAW terms only: NO alias expansion (unlike `memory_retrieve` — bootstrap's determinism law is stricter). They re-RANK each kind section by term coverage (desc), decay breaking ties; they never FILTER a section (an agent must still see ALL its standing constraints). Omitted → a pure decay order. A term with no alphanumeric token simply matches nothing — advisory ranking is never a required query, so it is never a rejection.
project_idNoProject fence (exact): only capsules in this project enter the pack.
token_budgetNoToken budget for the WHOLE pack (≈ chars/4); omitted → 1500. A CONTRACT, not an aspiration (the PRD target: a useful pack in ≤1500 tokens). Sections fill in PRIORITY order (constraints first — an agent must know what it cannot do before what to do), trimming the tail to fit; the FIRST constraint and the ONE next action are the irreducible floor (present when they exist even if they alone overshoot — `memory_retrieve`'s floor-of-one, applied to the safety core). 0 → an empty pack (the zero-cap consistency `memory_retrieve`/`memory_list` keep).
project_prefixNoScope-hierarchy fence: keep capsules whose `project_id` equals this prefix exactly OR starts with it + `"/"` — `"nott"` covers `"nott"` and `"nott/x"`, never `"nottx"`. AND-composes with `project_id`. An empty or `"/"`-terminated prefix can match nothing and is rejected with a teaching error rather than answering empty.

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description fully discloses behavior: determinism, ranking via terms, capping with exact totals, budget contract with floors, trimming and priority order, and the advisory nature of data. It leaves no major behavioral trait unstated.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is nearly 500 words, making it verbose despite being well-organized into a summary followed by numbered details. It could be shortened while retaining clarity, but the front-loaded purpose and structured sections help readability.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no annotations and no output schema, the description compensates thoroughly. It explains all behavioral details, parameter nuances, and edge cases (e.g., token_budget 0, empty sections, budget floors) for a complex tool, making it fully contextual.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Although schema coverage is 100%, the description enriches each parameter with precise semantics beyond schema: terms re-rank but never filter, token_budget is a contract with floors and priorities, project_prefix explains hierarchy matching, and project_id is exact fence. This adds substantial value for correct invocation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it is a deterministic cold-start pack for a fresh agent, the 'PULL half of the recall loop', and explicitly distinguishes from memory_retrieve. It specifies the five sections in fixed order with clear semantics, leaving no ambiguity about what the tool does.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear guidance on when to use (before acting, cold-start) and contrasts with memory_retrieve. However, it does not explicitly mention when not to use it versus other siblings like memory_digest or memory_list, which would further strengthen selection.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

memory_classifyA

Classify content into {kind: fact|procedure|decision|task|epic|brainstorm|doc|constraint|capability|failure_pattern, scope: project|global|session, authority_class, instruction_taint}. origin (extracted-candidate|owner-stated|tool-observation|external-import|session-note; default extracted-candidate) drives authority and default scope; external-import is BORN tainted. Pass kind to carry a memory_extract candidate's kind forward (never re-derived); omit it to derive from the content via the extract cue tables — closed ENGLISH + PORTUGUESE keyword lists (typed error when underivable — nothing is guessed; other languages: pass kind explicitly; the same extract ENTITY GATE applies, so a declarative/copular sentence derives a fact ONLY with an entity anchor — an acronym/number/path/dotted/backtick token — and "o sistema é resiliente" is underivable while "a API é lenta" derives fact). The schema-minimal call {content} is therefore wire-valid only when the content carries a derivable cue — the minimal ALWAYS-valid call is {content, kind}. taint_hint=true is monotone (never cleared by a clean local scan). With capsule_id (alias id — memory_get/memory_forget spell it id; capsule_id is canonical, both at once is a duplicate-field error) the label is PERSISTED as that capsule's sidecar record (upsert; audited) and readable back on memory_get's classification field; without it the call is advisory only. A persist onto a live capsule also answers content_matches_capsule — false means the label was derived from OTHER bytes than the capsule holds (the persist still executes, but the drift is named on the response and in the audit detail, never bound silently). Optional epistemic sidecar (u-r2, REQUIRES capsule_id — advisory-only calls carrying these are rejected with the teaching error, never silently dropped): evidence_state (closed set observed | inferred | unverified — how the claim relates to observation), proof_hint (the command that re-proves the claim), stale_if (the condition under which the claim expires). Persisted PER FIELD — an omitted field never clears a stored one — and read back on memory_get's epistemics and on retrieve envelopes. proof_hint/stale_if are ADVISORY STRINGS stored and surfaced verbatim, NEVER executed or evaluated by any code path.

ParametersJSON Schema
NameRequiredDescriptionDefault
idNoWhen set, the classification is PERSISTED as this capsule's sidecar label (`kind` + `scope`; upsert). Unknown id → typed error, nothing written. Omitted → advisory only. q101: `id` is accepted as an alias (memory_get/memory_forget spell it `id`); `capsule_id` is canonical, and sending BOTH is a duplicate-field error (the q60 content/text precedent).
kindNoCarry-forward kind (e.g. from a `memory_extract` candidate — donor law: a supplied kind is never re-derived). Omitted → derived from the content; typed error when underivable.
scopeNoExplicit scope override. Omitted → the origin's default scope.
originNoWhere the content came from — drives authority, default scope, and the born-tainted law. Omitted → `extracted-candidate` (the humble default: agent-inferred authority).
contentYesThe content to classify.
stale_ifNou-r2: OPTIONAL expiry condition persisted onto `capsule_id`'s epistemic sidecar. ADVISORY STRING ONLY — stored and surfaced verbatim, NEVER evaluated by any code path. Requires `capsule_id`.
capsule_idNoWhen set, the classification is PERSISTED as this capsule's sidecar label (`kind` + `scope`; upsert). Unknown id → typed error, nothing written. Omitted → advisory only. q101: `id` is accepted as an alias (memory_get/memory_forget spell it `id`); `capsule_id` is canonical, and sending BOTH is a duplicate-field error (the q60 content/text precedent).
proof_hintNou-r2: OPTIONAL re-prove command persisted onto `capsule_id`'s epistemic sidecar. ADVISORY STRING ONLY — stored and surfaced verbatim, NEVER executed by any code path. Requires `capsule_id`.
taint_hintNoUpstream taint verdict (monotone: `true` can never be cleared).
evidence_stateNou-r2: OPTIONAL epistemic state persisted onto `capsule_id`'s epistemic sidecar (closed set observed | inferred | unverified — how the claim relates to observation). Requires `capsule_id`: the epistemic fields are capsule annotations, an advisory-only call carrying one is a teaching rejection, never a silent drop.

TDQS

A3.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description fully shoulders the transparency burden. It exhaustively discloses behavioral traits: persistence behavior, advisory-only mode, monotone taint, epistemic sidecar conditions, derivation rules, error cases (underivable, teaching error), and drift detection. No contradictions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense and includes numerous details and edge cases, which is valuable but reduces conciseness. It is front-loaded with the core action but quickly expands into complex rules. More structure (e.g., bullet points or clearer separation of concerns) could improve quick comprehension.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (10 parameters, no output schema), the description covers most key aspects: input semantics, defaults, side effects, error conditions, cross-tool references (memory_extract, memory_get), and partial return value description. It lacks explicit output structure but provides sufficient context for effective use.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so baseline is 3. The description adds significant value beyond the schema by explaining parameter interactions (e.g., origin default scope, epistemic field requirements, kind carry-forward rule, taint monotonicity). This enriches semantic understanding for effective tool usage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool classifies content into specific kinds, scopes, and other attributes. It provides an enumeration of possible outputs and mentions relationship with memory_extract. However, it does not explicitly distinguish this tool from all sibling tools, which slightly reduces clarity.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description offers some guidance, such as when to pass kind (carrying forward from memory_extract) vs. omitting it for derivation, and conditions for using capsule_id. However, it lacks explicit when-to-use vs. alternatives guidance, leaving the agent to infer context from the detailed rules.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

memory_consolidateA

Run the deterministic consolidation planner over the live store and return the full plan: exact_dupes (same-source_hash rows — a store-invariant breach report; keep = lowest seq), merge_proposals (near-duplicate clusters by significant-token containment; tainted never clusters with untainted), tier_moves (protective demotions only: quarantine on live taint evidence for externally-imported records, archive for superseded records that expired or aged >180d with zero recalls; NEVER a promotion to active), and alias_proposals (u-r5 miss-ledger: deterministic vocabulary hints mined from the recall-miss ledger — each recorded miss term is paired with every existing indexed-vocabulary word sharing a >=4-char folded prefix (prefix-on-fold ONLY: no fuzzy, no edit-distance, no scoring, no embedder), {term, candidate, miss_count} ordered miss_count desc then term asc then candidate asc, capped at the top 20; a term that already carries a taught alias is skipped, and a term with no candidate still surfaces as {term, candidate:null, miss_count}. The loop: memory_retrieve records a miss -> this proposes -> you teach memory_alias -> the SAME query grounds). Default is a pure DRY-RUN: nothing is written. apply_tiers:true executes ONLY the tier_moves (set_tier per move, each audited); merge proposals, dupe repairs, AND alias_proposals are NEVER executed or auto-taught by this tool — teaching an alias stays a caller act through memory_alias; the caller is always the deciding actor. Applied tiers are observable on every read surface: memory_get carries tier, memory_list rows mark (and filter by) non-active tiers, memory_export renders tier markers, and memory_retrieve counts archived/quarantined exclusions under their OWN reasons (tier fences dominate the superseded fence). Everything returned is ADVISORY_NOT_AUTHORITY.

ParametersJSON Schema
NameRequiredDescriptionDefault
apply_tiersNo`true` → EXECUTE the plan's tier_moves (set_tier per move, audited). Merges and exact-dupe repairs are NEVER executed — they stay proposals for the caller regardless of this flag. Omitted or `false` → pure dry-run: report only, nothing written.

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description fully discloses behaviors: dry-run default, advisory nature, never auto-teaches, tier moves only applied if explicitly requested, and observable effects on read surfaces. No contradictions; transparency is high.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is very verbose and dense, containing multiple long sentences without breaks or lists. While detailed, it could be more concise and structured for easier parsing by an AI agent. It earns its place but at the cost of conciseness.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the complexity of the tool (four plan types, taint/expiry rules, interactions with memory_retrieve and memory_alias), the description covers all necessary information, including edge cases like skipping alias teaching for terms with existing taught aliases. It is complete despite lacking an output schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% with one parameter (apply_tiers). The description adds value by explaining that even when true, merges and dupe repairs remain proposals, which is beyond the schema's boolean description. Rich context beyond schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it runs a deterministic consolidation planner over the live store and returns a full plan with four components (exact_dupes, merge_proposals, tier_moves, alias_proposals). It distinguishes from siblings by clarifying that alias proposals are for calling memory_alias, making the purpose very specific.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly states default is dry-run, apply_tiers executes only tier_moves, and merges/dupe repairs are never executed. Provides when-not-to-use (e.g., never auto-teaches aliases) and references memory_alias as the appropriate tool for teaching. Offers clear context on when to use this tool versus alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

memory_digestA

Compact store projection sized for session-start injection: total capsule count, counts by project, a handoff section LEADING the headline lists — discovered by TWO markers: bracket handoffs (rows whose provenance source is "memory_session_finish", i.e. captured by memory_session_finish's handoff; ONE row per project, a superseded row stays visible flagged) and thread handoffs (rows whose content opens with the exact convention ACTIVE(): — closing paren required — captured via plain memory_ingest; ONE row per project+thread so concurrent threads stay visible, and a superseded thread row is RETIRED: supersede a thread's newest handoff to close the thread out of the lead — a guarantee that assumes each thread capture supersedes its prior (an older LIVE unchained row of the same thread resurfaces instead)); newest-first, house headline rows, capped at N; ABSENT when the scope holds none — additive, a reader that never hands off sees the digest unchanged, the newest N headlines with ids, and the N most-recalled headlines — each carrying the recall_count and last_recalled_at (RFC3339) that ordered it, sorted recall_count desc, then LAST-RECALL recency (not creation recency), then append order; capsules never returned by memory_retrieve do not appear. EVERY capped list declares its own completeness: handoff_total, newest_total and most_recalled_total are the EXACT pre-cap counts of their lists (the dag's ready/ready_total idiom), fenced exactly like the lists they sit beside and omitted at zero, so a truncated list is never mistaken for a complete one — list length < total means N cut it, raise headlines to see the rest. total and by_project's count count LIVE + SUPERSEDED capsules and EXCLUDE tombstoned (memory_export's own capsules= header line is the GRAND total including tombstoned and names its full breakdown live/superseded/tombstoned — digest total = that breakdown's live + superseded); each by_project row ALSO carries live — that row's capsules minus the superseded ones, the still-standing subset — so a census whose history outweighs its present says so instead of reading as inventory. count keeps its export-parity meaning and NEVER narrows to live. These five capsule sections honor project_prefix (subtree fence: exact id or id + "/..."; an empty or "/"-terminated prefix can match nothing and is rejected with a teaching error rather than answering empty). Store-global sections (never fenced): relation/audit counters and open sessions — open_sessions is the EXACT open-bracket count and open_session_ids NAMES which sess- are open (oldest-open first, id list capped at N while the count stays exact — the dag's capped-list + exact-total idiom), so a zero-capture orphaned bracket is recoverable: read its id there, then close it with memory_session_finish; the blocks-dag projection dag {ready + ready_total, blocked + blocked_total, done + done_total (id lists capped at N, totals exact)} — blocks-edge participants only, superseded/tombstoned dead to it; a WITNESSED participant is DONE (u-r3: proof-carrying closure DERIVED from a witnesses edge — no state field — that leaves ready/blocked and stops gating dependents, yet stays recallable unlike superseded/tombstoned ids; ready itself IS "unblocked, awaiting proof"); fail-closed on a live blocks-cycle among non-done members (status "cycle" with ONE concrete cycle + entangled_total; repair — supersede, forget, OR witness a member — and re-digest to see the next); the mission section mission {status:"ok", roots: [{...headline, children}]} — the planning-plane u2 spine, a SEPARATE projection over the grounded_in sidecar (grounded_in is NOT a dag input): roots HONOR project_prefix, fenced exactly like the other capsule sections above — the cycle check and each root's children count are the ONLY store-global pieces of this section, never fenced: roots are live kind=epic capsules with no outgoing grounded_in edge that still ANCHORS them (the live-parent anchoring rule — an edge anchors its child ONLY while the edge's parent, its to_id, is live; a live epic whose every outgoing grounded_in edge names a dead, i.e. tombstoned or superseded, parent is a mission root again), newest-first, capped at N; each root's children counts grounded_in edges naming it as parent, STORE-WIDE (never fenced to the root's own project scope) but LIVE-only (a tombstoned or superseded child endpoint does not count); mission is ABSENT from the wire entirely — not merely an empty roots array — when the live grounded_in subgraph is acyclic and has zero roots (additive dormancy: a store that never grounds anything sees a byte-identical digest); fail-closed on a live grounded_in cycle, mirroring dag's own shape (status "cycle" with ONE concrete cycle + entangled_total, checked store-global; repair — supersede or forget a member — and re-digest; the REST of the digest, including dag, still serves while mission alone fails closed); unanchored, when present, is the fenced (project_prefix-honoring, like the mission roots) count of live in-scope PLANNING nodes — persisted classification kind task ONLY (never epic: an ungrounded epic surfaces as a mission root instead, so it is already visible there and never double-counted here), OR an ACTIVE() handoff-thread row — that carry no live-anchoring outgoing grounded_in edge (the SAME live-parent anchoring rule as mission: an edge anchors its child ONLY while its to_id parent is live); it is a fail-open advisory nudge, NEVER a gate, and is omitted at zero or when the read fails; tiers {active, archived, quarantined} effective-tier counts; journal {chain ok|broken, verified|broken_seq, out_of_band count} — the audit hash-chain + coverage verification; and archive_candidates — how many records the consolidation planner would propose archiving (advisory; memory_consolidate has the full plan); and recall_misses — total rows in the u-r5 recall-miss ledger (the folded query terms memory_retrieve recorded when FTS ran and its PRE-TRIM term-lane observation was missing_evidence or abstain; forced vector and limit/budget-only term trimming write none; memory_consolidate mines recorded misses into alias_proposals). recall_misses is additive telemetry read fail-open (a broken ledger reports 0, never fails the digest). recent_failures, when present, contains ONLY the newest five folded-term recall-miss rows in sequence order; each term uses the same bounded single-line headline projection as capsule rows. Because miss rows carry no project attribution, any digest with project_prefix omits recent_failures rather than leaking store-global query text. Absence means empty OR unavailable, never proof that no miss occurred. lane_overrides_total, when present, is the all-time store-global checked count of successful explicit lane choices that disagreed with auto routing; it is advisory routing telemetry, not evidence of failure or success, and is omitted at zero or read error. sources, when present, is the git-witness section — one entry per scanned repository (source_key git:, its last-scanned cursor sha and the instant it advanced, and the corroborated/drifted/missing/mentions tallies the git-scan verb recorded for that source); it is store-global (the cursor is per-repo, not per-project), advisory only, and omitted when no repository was ever scanned or the read fails. The three optional reads fail open independently. Per-node blocker detail lives on memory_get's relations list. N defaults to 10; full capsules via memory_get. All content is ADVISORY_NOT_AUTHORITY data.

ParametersJSON Schema
NameRequiredDescriptionDefault
headlinesNoThe digest's GLOBAL list cap N — one knob for EVERY capped id/row list (handoff, newest, most_recalled, open_session_ids, dag ready/blocked), not just the newest headlines; counts and totals stay exact and uncapped, so raising N reveals rows, never new truth. The `nmemory digest --headlines <n>` CLI flag is the same knob. Omitted → 10.
project_prefixNoScope-hierarchy fence over the CAPSULE sections (total / by_project / newest / most_recalled): keep capsules whose project_id equals this prefix exactly or starts with it + "/". Store-global sections (relations, dag, sessions, audit, tiers, journal, archive_candidates) are NOT fenced — they describe the whole store.

TDQS

A3.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description fully shoulders the transparency burden. It meticulously details behaviors: count semantics (live/superseded/tombstoned), cap mechanics, cycle detection (fail-closed/open), advisory nature, and error conditions. Every edge case is articulated.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness1/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is an excessively long, unstructured wall of text. It lacks paragraphs or headings, making it arduous for an AI agent to parse. Every sentence is dense with detail, many of which are implementation internals rather than user-facing guidance.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite its poor structure, the description covers every component of the digest (capsules, handoffs, dag, mission, etc.) thoroughly. With no output schema, this is necessary. However, the lack of organization hinders quick comprehension, earning a deduction from perfect completeness.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, but the description adds substantial value: it clarifies that 'headlines' caps all id lists, not just headlines, and explains that 'project_prefix' only fences capsule sections, not global ones. This context is critical for correct parameter use.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description starts with 'Compact store projection sized for session-start injection,' giving a clear use case. It distinguishes from siblings like memory_get (for details) and memory_retrieve (for search). However, the core purpose is buried in a dense wall of text, reducing immediate clarity.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No explicit guidance on when to use this tool versus alternatives. The description implies it's for session start but doesn't compare to siblings like memory_list or memory_get. The agent must infer usage from the tool's name and context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

memory_exportA

Render the whole store as one deterministic markdown INDEX view and return it as a string under the response's markdown key — nmemory writes no files; the caller saves it where it wants. Each capsule renders as a one-line entry whose quoted text is a TRUNCATED first-line headline (~140 chars, …-terminated when cut) — the view is a compact window, NOT a byte-complete backup; full content stays one memory_get per id away. Layout: header (generated-view law line + generated_at + a store-digest line with counts and a sha256 over the body), then ## project sections with kind subsections (classified via the memory_classify sidecar; unclassified last), a ## relations section (every edge), and a terminal ## superseded + tombstoned section (markers only — tombstones never render content); sections with no rows are OMITTED entirely, so presence is data-dependent. Non-active lifecycle tiers render a · tier archived|quarantined marker on their entry or superseded-marker line. The body sha256 covers EXACTLY the bytes after the store-digest line's terminating newline through end of document (the header lines — title, law/DATA lines, generated_at, and the digest line itself — are NOT hashed): regeneration of an unchanged store reproduces it byte-for-byte, and any hand edit to a rendered line breaks it. Save VERBATIM to verify: the sha covers the exact returned bytes, so an extraction that appends its own trailing newline INSIDE the saved span (e.g. jq -r) manufactures a false tamper alarm — extract byte-exactly (jq -j) and append nothing. stamp (default true) writes the generated_at line; stamp:false OMITS it, so two regenerations of an unchanged store are BYTE-IDENTICAL end to end (the one churning line is gone) — the stable-diff path for a memory-in-git caller. Inline fields are newline-escaped so stored content cannot forge view structure. Read-only, ADVISORY_NOT_AUTHORITY: a generated view, never an authority surface.

ParametersJSON Schema
NameRequiredDescriptionDefault
stampNoq83: stamp the header with `generated_at` (default true). Pass false to OMIT it so regenerations of an unchanged store are byte-identical — the stable-diff path for the memory-in-git caller.

TDQS

A4.2/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description fully covers behavioral traits: read-only, markdown structure, sha256 coverage, stamp effect, and warnings about extraction. It explicitly states 'Read-only, ADVISORY_NOT_AUTHORITY' and explains the deterministic nature and tamper detection.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness2/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is very long (multiple paragraphs) and could be more concise. While it front-loads the core purpose and structures details with sections, it contains excessive explanatory text that could be condensed, reducing efficiency for an AI agent.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the complexity and lack of output schema, the description covers all necessary aspects: output format, markdown structure, hashing details, stamp behavior, and extraction warnings. It is comprehensive enough for an agent to understand tool usage and output.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The sole parameter 'stamp' has schema description coverage at 100% with detailed documentation. The description adds value by explaining its effect on byte-identical regenerations and the stable-diff use case, enriching the schema's information.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it renders the whole store as a deterministic markdown INDEX view and returns it as a string under the 'markdown' key. This is a specific verb-resource combination, and while it doesn't explicitly compare to siblings, the purpose is unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage (e.g., 'the caller saves it where it wants' and discussion of stamp for byte-identical output), but it does not explicitly state when to use this tool versus alternatives like memory_get or memory_list. No when-not-to-use guidance is provided.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

memory_extractA

Mine a free-text blob (param content; text accepted as an alias) for capsule-sized memory candidates — deterministic heuristics, verbatim substrings only (never synthesized). Segmentation: per line, then per sentence within a line (; also splits — semicolon-joined rules are independent claims); fenced AND indented code is skipped (tracebacks are not claims), and chat/log dress ([10:05] name: ) is peeled like list markers. Cue tables are closed keyword lists in ENGLISH + PORTUGUESE (decisão/decidimos, sempre/nunca/não, é/são/deve/devem, todo/pendente, epic/marco, ideia/e se, doc/runbook, procedure/procedimento/how to, constraint/restrição + must not/não pode(m)/não deve(m), capability/capacidade + use when/use quando, failure/falha/symptom/sintoma + fails with/falha quando/breaks when, …) — other languages need the caller to judge kind themselves. Work-plane and procedure LABELS must open the segment (once dress is stripped); decision/fact shape cues also fire mid-segment. ENTITY GATE (q108): the declarative fact cues (is/are/was/deve/devem/é/são/foi/…) fire ONLY when the segment ALSO carries an ENTITY ANCHOR — the first concrete token: an acronym or mixed-case internal capital (API, SSOT, SQLite, nMEMORY), a token bearing a digit (v2, 4320, 400), a path/symbol shape (/etc/x, a::b), an internal dot (PLAN.md, menot.you), or a backtick code span (nsh) — tokens carrying call punctuation ( ) { } ; are fenced out as code debris. It is a deliberate noise fence, BROADER than just "acronym or number": "A API é lenta" mines a fact (entity API), "o sistema é resiliente" mines NOTHING (no anchor). The standing-rule adverbs never/always/nunca/sempre/jamais are the ONE fact shape exempt — they need no anchor. Precedence when the same adverb opens a COMMAND: an imperative opener wins ("Sempre valide o token" mines procedure, cue imperative-opener); the adverb exemption applies only to declarative shapes ("o deploy sempre roda às 18h" mines fact). Each candidate carries a closed kind (fact/procedure/decision/task/epic/brainstorm/doc/constraint/capability/failure_pattern — task/epic/brainstorm/doc are the work/docs plane; constraint/capability/failure_pattern the governance plane: prohibitions, applicability, failure shapes) and the literal cue that fired. ADVISORY only: NOTHING is stored — the caller reviews and captures chosen candidates via memory_ingest (optionally classifying them via memory_classify with the candidate kind carried forward). 0 candidates is an honest answer.

ParametersJSON Schema
NameRequiredDescriptionDefault
textNoAlias for content (the pre-w2-fix spelling). Send content OR text, never both.
contentNoThe free-text blob to mine for capsule-sized candidates (alias: text — send exactly one, never both).

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description fully covers behavior: it explains deterministic heuristics, verbatim substrings, segmentation rules, noise filters (entity gate, code skipping), kind assignment, and explicitly states nothing is stored. The 'ADVISORY only' note is critical for safe agent use.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is very long (multiple paragraphs) and contains extensive algorithmic details. While necessary for a complex tool, it could be more concise. The front-loading of purpose and key behavior is good, but overall verbosity reduces clarity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no output schema, the description adequately explains what the tool returns (candidates with kind and cue) and that 0 candidates is an honest answer. It also covers edge cases (other languages, imperative vs declarative precedence). The tool is well-contextualized.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% (both content and text described). The description adds meaning by explaining that content is the primary blob and text is an alias, and it provides context on how the blob is processed (line-based segmentation, etc.), which goes beyond schema definitions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool mines a free-text blob for memory candidates, using a specific verb ('Mine') and resource ('free-text blob'). It distinguishes itself from sibling tools by emphasizing it does not store anything, leaving capture to memory_ingest.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear context on when to use this tool (to extract candidates) and directs the caller to memory_ingest for storage. It also notes language limitations (English/Portuguese cues only), but does not explicitly list when not to use or alternative tools beyond ingest.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

memory_forgetA

Forget a capsule's content IRREVERSIBLY (reason MANDATORY). The capsule's embedding sidecar row is destroyed WITH it (both modes — a vector is derived from the destroyed bytes and the id stops being enumerable on memory_vector's list). mode "purged" = hard forget, nothing retained; "redacted" = the provenance {source, anchor} is deliberately RETAINED on the marker for audit — both destroy the content bytes (secure_delete) and empty the recall index row. What remains is the tombstone marker: id, mode, at, reason, a KEYED HMAC-SHA-256 content fingerprint (key from NMEMORY_HMAC_KEY or a 0600 key file beside the DB, created on first use), the id's relation edges, and — redacted only — the retained provenance. Afterwards: memory_get answers the marker envelope (memory_list omits tombstoned ids); retrieve counts it under excluded {tombstoned} ONLY when a query term IS the capsule id itself (e.g. terms:["cap-3"]); the content index row is EMPTIED, so searching the forgotten content abstains — zero matches, no tombstone echo; re-ingesting the identical content is rejected (forget is sticky); the id drops out of the digest dag (forget is a sanctioned dag repair); forgetting the id AGAIN is a resource-state error (-32002, data {kind: "tombstoned_capsule", id}) — the same family as an unknown id, never a fake invalid-params. Audited with the reason.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesThe capsule to forget (`cap-<n>`).
modeYesHow: `purged` (hard forget) or `redacted` (provenance retained for audit). Both destroy the content bytes.
reasonYesThe mandatory stated reason (recorded on the marker + audit).

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden. It extensively details behavioral traits: secure delete, tombstone marker, HMAC fingerprint, effect on memory_get/memory_list/retrieve, re-ingestion rejection, dag repair, and error codes. This is comprehensive.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is very detailed but quite lengthy and dense as a single paragraph. While thoroughness is justified for a destructive operation, it could be more structured (e.g., using bullet points) to improve readability for an AI agent.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the complexity of this irreversible operation with two modes and side effects on multiple subsystems, and no output schema, the description is highly complete. It covers all important behavioral aspects and error conditions.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3. The description adds value beyond the schema by explaining the purpose of each parameter and elaborating on the mode parameter's consequences (e.g., 'Both destroy the content bytes'). This extra context justifies a score above baseline.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: 'Forget a capsule's content IRREVERSIBLY' with a mandatory reason. It distinguishes from sibling tools like memory_get (retrieve) and memory_ingest (create) by specifying irreversible deletion.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear context on when to use this tool (irreversible deletion) and explains the two modes (purged vs redacted) with their implications. It also mentions when re-ingestion is rejected and that forgetting again produces an error, but does not explicitly name alternative tools for non-destructive operations.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

memory_getA

Fetch ONE full capsule by exact store id (cap-) — the expansion step of layered recall after retrieve/digest/list returned a headline. Response is wrapped as ADVISORY_NOT_AUTHORITY DATA and carries the complete capsule: content, provenance, confidence, freshness, scope, authority_class, instruction_taint — plus relations (every edge touching this id: kind/from/to/at, plus origin:"import" on a machine-written stale-import supersedes edge — absent means caller-recorded 'manual', the only kind the machine never reverses — the "what blocks/supersedes/witnesses this?" read surface), classification (the persisted memory_classify sidecar label, when one exists), event_time (the caller-declared fact-time sidecar when one exists: event_from, event_to, declared_at; GET-only — never emitted by list, digest, export, or retrieve envelopes; set only on fresh capture via memory_ingest), epistemics (u-r2: the persisted epistemic sidecar when one exists — evidence_state from the closed observed|inferred|unverified set, proof_hint, stale_if, at; the two hints are ADVISORY STRINGS surfaced verbatim, never executed or evaluated; set them at capture via memory_ingest or later via memory_classify with capsule_id), tier (the effective lifecycle tier active/archived/quarantined — always present, so apply_tiers results are auditable per capsule), expired (true when valid_to has passed at read time — the recall-fence state made visible instead of leaving freshness arithmetic to the reader; absent when still current), and taint_findings (the u6e scan re-run over the stored content — WHICH hijack rule fires, one "rule: term, term" line each; absent when clean), and last_mutation ({actor, at, event} — the most recent audit-ledger row whose subject is this id, so "who mutated this?" reads off the API instead of the SQLite ledger; actor is the clientInfo.name recorded at mutation time; absent when the id was never a mutation subject). A forgotten id answers with its tombstone marker envelope (outcome "tombstoned": mode, at, reason, content_hmac, relations, last_mutation — for a tombstone that is the forget itself, so "who forgot this?" reads off the API — and, for mode redacted only, the deliberately retained provenance {source, anchor}; never content). Unknown id -> resource-not-found (-32002) with data {kind: "unknown_capsule", id}.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesExact capsule id (`cap-<n>`), e.g. from a retrieve/digest/list entry.

TDQS

A4.2/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations provided, but the description extensively discloses response structure, tombstone behavior, error handling, field meanings (e.g., expiry, taint findings, last_mutation), and sidecar behavior, providing full transparency.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness2/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Extremely long and dense single paragraph; while informative, it is not concise and would benefit from better structure (e.g., bullet points) for agent consumption.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no output schema, the description fully explains the response, including all fields, edge cases (tombstone, unknown ID), and sidecar behaviors, leaving no gaps for a complex tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Only one parameter (id) with 100% schema coverage; the description adds little beyond the schema's own description, meeting the baseline for high coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description specifies that the tool fetches ONE full capsule by exact store id, and positions it as an expansion step after retrieve/digest/list, clearly distinguishing its role from siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly states when to use it ('after retrieve/digest/list returned a headline') and describes error responses for forgotten and unknown IDs, but does not mention when not to use or alternative tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

memory_importA

Import memories from ONE closed native source: "user-claude-md" (/.claude3/CLAUDE.md, else .claude2, else .claude), "project-claude-md" (/CLAUDE.md), "project-agents-md" (/AGENTS.md), or "memory-dir" (every .md DIRECTLY inside dir — non-recursive, symlinks skipped; dir required for this source only). base overrides the resolved base directory. Split rule (derivable, not vague): fenced code is opaque (never split inside, headings within a fence do not count). If the file has ATX headings at column 0, the split level is the SMALLEST heading level that occurs at least TWICE (a lone "# Title" over "##" sections splits per "##"), else the smallest level present — so a file with ONE top-level heading is ONE candidate carrying the whole body; candidates are the preamble before the first split-level heading (if non-blank) then one per split-level section (deeper headings ride along inside). With NO headings, candidates are blank-line-separated paragraph blocks. Each candidate is trimmed of surrounding blank lines; whitespace-only candidates are dropped. Each candidate is taint-scanned and ingested with authority_class=externally-imported and instruction_taint=true (imports are BORN tainted — no waiver) under provenance anchor : — the path is ROOT-RELATIVE when the source sits under the repo anchor root (so anchor_live can resolve it), absolute otherwise (anchor_live stays "unknown" — the fence resolves only root-relative paths, never over-claiming liveness). Batch outcome shape of memory_ingest (captured/deduplicated/rejected per candidate; idempotent re-import dedupes). Outcome split (q103): PARAM faults stay hard -32602 (a memory-dir source without a dir; a dir passed to another source; a memory-dir path that is not a directory); SOURCE-STATE results are SOFT typed rows sharing one family — outcome "imported" (candidates ingested), "absent" (no file at any probed path, with the tried list), or "rejected" (a whitelisted leaf blocked by a security fence — today a leaf that is itself a symlink, never followed — carrying the fence's VERBATIM reason plus the leaf path; the security signal stays fully visible, never a protocol error). STALE-IMPORT SUPERSESSION (u-r8): re-import repairs what it derived — a capsule derived from a source block that CHANGED is auto-superseded by the fresh capture (lineage-bound by per-block content hash, NEVER similarity; equal-count guard defers unbalanced edits to the caller), and content that REAPPEARED (a revert) is revived by climbing the chain of the mechanism's OWN origin='import' supersedes edges to a head anchored in this source. THE FENCE: a hand-ingested capsule is never auto-superseded or auto-revived, a caller-recorded (manual) edge is never machine-reversed — ANY manual edge on the chain makes the machine defer with zero mutation. Every machine edge and revive is audited and marked origin='import' (visible on memory_get).

ParametersJSON Schema
NameRequiredDescriptionDefault
dirNoThe directory for `memory-dir` or `notion-export-dir` (relative resolves against the base); required for those two sources, rejected for the others.
baseNoBase directory override. Omitted → the boot-injected home dir (`user-claude-md`) or project root (everything else).
sourceYesWhich closed source to read.

TDQS

A4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description fully discloses behavioral traits: file location probing, split rules, taint marking (born tainted), anchor provenance, outcome types (imported/absent/rejected), stale import supersession, and the fence (manual edges protected). It is exhaustive.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness2/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single dense paragraph with excessive detail, making it not concise. It front-loads the purpose but then dives into split rules, supersession, and fence details that could be abbreviated or structured better.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the complexity (3 parameters, no output schema), the description comprehensively covers all aspects: source selection, split logic, taint, anchors, outcomes, supersession, and fence. Nothing essential is missing for an AI to understand how to invoke and what happens.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3. The description adds context for source behavior (e.g., directory probing) but does not significantly enhance parameter understanding beyond the schema's descriptions. It mentions base override and dir requirement but that's already in the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'Import memories from ONE closed native source' and lists the specific sources (user-claude-md, project-claude-md, etc.), providing a specific verb and resource. It distinguishes from siblings like memory_ingest by emphasizing the closed native source set.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage for importing from these specific sources but does not explicitly state when to use this tool versus alternatives like memory_ingest or memory_export. It lacks when-not-to guidance or comparisons to sibling tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

memory_ingestA

Capture memories with MANDATORY provenance (source + anchor). One item object, or a batch as {"items":[...]} — never both forms in one payload. A shape-broken batch item becomes its OWN rejected row plus the full contract; the good siblings still capture — schema-bad and semantically-bad items behave identically per-item, and every batch rejection row speaks ONE grammar: itemsN: ingest rejected: (the index always leads, the field path appears when a wrong-typed field is named, exactly one prefix; single-form SEMANTIC rejections carry the same prefix without the items[N] locator — a single-form SHAPE-broken payload (unknown/missing field, wrong type, invalid kind) is a DESERIALIZE-stage fault and surfaces IN-BAND as an isError result with plain serde text (rmcp 2.2.0 routes shape faults there, not to a protocol error; q88)). Idempotent by content hash: re-ingesting identical content collapses onto the existing capsule (per-item status "deduplicated"; fresh appends report "captured"; both statuses share one row shape). Smart defaults fill confidence (0.6), valid_from (now), project, authority_class (agent-inferred). When the server was booted without an explicit project (--project/NMEMORY_PROJECT absent), the default project derives at capture time from the connected client's clientInfo.name, sanitized to a slug (lowercase ASCII alphanumerics + '-', 32-char cap); pass project_id to pin. A server booted with an explicit project ignores clientInfo entirely. Externally-imported items are born instruction_taint=true. Every capture is taint-scanned: hijack-shaped content is flagged instruction_taint=true (advisory — it is stored flagged, never blocked) with per-rule taint_findings on the outcome. Optional fact-time per item: event_at (RFC3339 point) XOR event_from+event_to (inclusive RFC3339 range, to >= from) — stored as a sidecar (Capsule v1 untouched; a dedup collapse keeps the FIRST declaration), read back on memory_get.event_time, filtered by memory_retrieve's time_window; fact-time never feeds decay. Optional session_id links the capture to an open memory_session_start bracket. Optional kind (closed set fact|procedure|decision|task|epic|brainstorm|doc|constraint|capability|failure_pattern) is persisted as the capsule's classification sidecar right after capture (scope defaults to project; Capsule v1 bytes untouched) — so a task/epic becomes memory_list {kind} -listable in ONE trip instead of an ingest+classify pair; on a deduplicated row the kind still lands on the existing capsule — a DIFFERENT kind replaces the prior label (last-write-wins, the same audited upsert memory_classify performs; omitting kind never clears one; when the label actually flips, the dedup row says so with reclassified:{was,now} — a true no-op collapse omits it) — and an invalid kind rejects the item naming the closed set. Optional epistemic sidecar per item (u-r2, persisted beside the capsule the same via-ingest way; Capsule v1 bytes untouched): evidence_state — the closed set observed (directly seen) | inferred (proof supports it, not directly seen) | unverified (a hypothesis awaiting a check); an invalid state rejects the item naming the set — plus proof_hint (the command that re-proves the claim) and stale_if (the condition under which the claim expires); BOTH hints are ADVISORY STRINGS stored and surfaced verbatim, NEVER executed or evaluated by any code path; all three read back on memory_get's epistemics and on retrieve envelopes. A path:line anchor that resolves under the repo anchor root also has its anchored FILE's content hash recorded at capture (fail-closed fence: symlinks/absolute/out-of-root record nothing), so retrieve can answer anchor_drift — whether the anchored file's bytes changed since capture. Returns one outcome per item plus captured/deduped/rejected counts. dedup_hint is a near-duplicate advisory naming the NEAREST similar live capsule (max score; ties break to the earliest-appended id). The score is MUTUAL containment over the FULL vocabularies — every token counts, so a short differentiator ("wave A" vs "wave B", "v2" vs "v3") always lands the score below 1.0 — normalized by the LARGER set (a short content inside a long capsule scores low); eligibility needs 4+ significant (3+ char) tokens per side. The score tops out at 0.99: 1.0 is reserved for byte-identical content, which deduplicates and never hints, so 0.99 means the vocabularies coincide but the bytes differ — never treat a hint as proof of identity; the CALLER decides: replace it by re-ingesting with supersedes: "cap-" (the old capsule then stops grounding recall but stays reachable via memory_get/list; the outcome row confirms with superseded: "cap-", also when the new content deduplicated), or keep both. Captured rows may ALSO carry siblings: the top-3 highest-overlap ACTIVE capsules in the SAME project scope as the capture (same metric, same 0.5 threshold, same 0.99 cap as dedup_hint), each {id, score} — the write-time conflict surface, so near-siblings and contradictions surface NOW instead of sessions later in consolidate. Sibling candidacy applies recall's protective fences at write time: tombstoned, quarantined, falsified, archived, and superseded capsules never appear (you must not be steered to supersede into a dead or poisoned record), and neither does the capsule this very request supersedes. siblings is computed independently of dedup_hint — the hint scans globally, siblings are project-fenced — so the hint's target appears among the siblings exactly when it is itself an active same-project candidate. Absent when nothing clears the gate, and never present on deduplicated rows (that row already names its byte-identical target). Advisory ONLY, like the hint: the DECISION — supersede (re-ingest with supersedes), merge, or nothing — is yours; the engine never acts on it.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden. It discloses numerous behavioral traits: mandatory provenance, batch error handling per-item, idempotency via content hash, smart defaults, dedup_hint and siblings computation, fact-time handling, session linking, supersede support, taint scanning, and project derivation. This is exceptionally transparent.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness2/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is extremely long (over 700 words) and lacks structure like paragraphs or sections. It is a dense wall of text that could be streamlined or organized with bullet points or subsections. While detailed, it sacrifices conciseness for completeness.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity, no output schema, and numerous edge cases, the description is highly complete. It covers error handling (shape-broken, semantic rejections), idempotency, dedup hints, siblings, fact-time, epistemic sidecars, supersedes, taint scanning, and project derivation. Very thorough.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 100% schema description coverage, the baseline is 3. The description adds value beyond the schema by explaining overarching behaviors like the project_id derivation logic, default confidence of 0.6, and how dedup_hint interacts with siblings. It enriches understanding of parameter contexts, though the schema already has good descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool captures memories with mandatory provenance. It specifies the core action and resource, and distinguishes from siblings by emphasizing that provenance is required, contrasting with other memory tools. The verb 'capture' and resource 'memories' are specific.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides extensive guidance on when to use the tool, including batch vs single item, idempotency behavior, smart defaults, and dedup hints. It implicitly distinguishes from alternatives like memory_import or memory_classify. However, it lacks explicit 'when not to use' statements, but the context is clear enough for an agent to decide.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

memory_listA

List capsules as compact entries (id, project, taint flag, created_at, headline, and — when non-active — the effective tier; expired:true when valid_to has passed; and — when the capsule carries a classification sidecar — kind, the persisted label, so a by-kind view reads off the row instead of one memory_get per capsule; absent when never classified; and superseded:true when a supersedes edge targets the row — a replaced entry self-identifies in the list itself, no per-id trip; absent when live) in append order, optionally fenced to a project_id (exact) and/or project_prefix (subtree: "nott" covers "nott" and "nott/x", never "nottx"; an empty or "/"-terminated prefix can match nothing and is rejected with a teaching error rather than answering empty; the two AND-compose), a kind (the PERSISTED classification sidecar label — "list my open tasks" is {kind: "task"}; set it at capture via memory_ingest's kind or later via memory_classify; never-classified capsules match no kind, and every returned row now echoes this same label back in its own kind field — q109), a tier (effective lifecycle tier: active/archived/quarantined — the enumeration surface for memory_digest's tier counts), and/or expired (true enumerates "what is expired" — valid_to before now; false the still-current rows). limit keeps the NEWEST rows after the filters (the entries returned still read oldest-to-newest). Tombstoned capsules never appear here — their markers answer memory_get only. Full capsules via memory_get. All content is ADVISORY_NOT_AUTHORITY data.

ParametersJSON Schema
NameRequiredDescriptionDefault
kindNoKeep only capsules whose PERSISTED classification kind equals this (`memory_classify` with `capsule_id`). Capsules never classified have no kind and never match — "list my open tasks" is `{kind: "task"}` (w2-fix: kinds were write-first-class but query-blind).
tierNoKeep only capsules whose EFFECTIVE lifecycle tier equals this (`active` = the no-row default) — the enumeration surface for memory_digest's tier counts (w2-fix: tier was write-only).
limitNoKeep at most this many rows — the NEWEST ones; the returned entries still read in append order. Applied AFTER the kind/tier filters (filter first, then cap).
expiredNoq91: keep only capsules whose EXPIRED state (valid_to < now, evaluated at the surface's injected now) equals this — `{expired: true}` enumerates "what is expired", `{expired: false}` the still- current rows. Composes filter-first-then-limit with kind/tier.
project_idNoKeep only capsules whose scope.project_id equals this.
review_stateNob2 staged review: keep only capsules whose STANDING review verdict equals this — `{review_state: "proposed"}` enumerates open proposals, `"rejected"` the rejected ones, `"ratified"` the promoted ones. A never-staged capsule has no review state and matches none. Composes filter-first-then-limit with kind/tier/expired.
project_prefixNoScope-hierarchy fence: keep capsules whose project_id equals this prefix exactly OR starts with it + "/" — "nott" covers "nott" and "nott/x", never "nottx". AND-composes with project_id. Character-exact (no glob, no case folding).

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Despite no annotations, the description fully discloses behavioral traits: returns compact entries, append order, filter effects, project_prefix substring matching with examples, rejection of empty/terminated prefixes, no tombstoned capsules, and advisory data status.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense but front-loaded with the core purpose. It packs many details into a single paragraph with parentheticals, making it thorough but slightly hard to scan. Could be broken into clearer sections, but every sentence adds value given complexity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with 7 optional parameters, no output schema, and no annotations, the description is exceptionally complete. It covers all filters, edge cases (empty prefix rejected), data volume (advisory), and return field semantics. No gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 100% schema coverage, baseline is 3. The description adds significant meaning beyond schema: explains by-kind view for 'kind', subtree matching for 'project_prefix' with edge cases, and composition of filters. However, some schema descriptions already cover the basics, so not a 5.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description explicitly states the verb ('list') and resource ('capsules as compact entries'), detailing the fields returned and the append order. It clearly distinguishes from sibling tools like memory_get (full capsules) and others like memory_digest for tier counts.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit guidance on when to use (listing with filters) and when not (tombstoned capsules never appear, use memory_get for full detail). Mentions specific use cases like 'list my open tasks' with kind filter, and explains filter composition.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

memory_mergeA

Reconcile a SECOND nMEMORY store file INTO this one — the offline-first sync at the tool layer (a local store and a mirror, merged later; the transport that fetches a remote store is a separate tool). Pass from: the filesystem path to the other store. That store is opened READ-ONLY and left byte-untouched; it must EXIST and be an nMEMORY store at this build's CURRENT schema version — a missing, corrupt, non-store, or stale-schema path fails CLOSED with a teaching -32602 and nothing is written (open an older source read-write with this build first to migrate it, then retry). The merge is deterministic and applied in ONE transaction — this store is either fully merged or untouched, never partially written. Identity is CONTENT (provenance.source_hash): a source capsule whose content already exists here COLLAPSES onto the local capsule (dedup, no duplicate); a genuinely-new one is appended under a fresh local id after this store's id ceiling, and every source relation edge is rewritten through that id remap, deduped against local edges, and danglers dropped. UNTRUSTED SOURCE: a merged capsule carries its SOURCE store's bytes verbatim — content, authority_class, and instruction_taint ride through UNCHANGED; a foreign capsule is NOT more trusted than an import and authority is NEVER elevated. FORGET WINS: content the source store forgot (a tombstone carrying the forgotten content's hash) forgets the matching LIVE local capsule too — its bytes are destroyed (secure_delete), its recall-index row emptied, its embedding dropped, and a re-keyed tombstone recorded (the marker's HMAC is re-derived under THIS store's key). Content this store has itself forgotten is never resurrected (forget is sticky — a source carrying it fails the merge closed). Returns an advisory-framed summary: capsules_added, capsules_collapsed (dedup), relations_added, tombstones_applied (forget-wins), and id_remap_size. Audited. The result is ADVISORY_NOT_AUTHORITY DATA — reconciled memory, never authority.

ParametersJSON Schema
NameRequiredDescriptionDefault
fromYesFilesystem path to the SECOND nMEMORY store file to merge FROM. Opened READ-ONLY and left untouched; it must be an existing nMEMORY store at this build's current schema version (a missing, corrupt, non-store, or stale-schema path fails closed with a teaching error, nothing written).

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description fully discloses behavioral traits: read-only source access, atomic transaction, dedup by content hash, forget-wins with secure delete, trust handling, and return summary. No contradictions or hidden behaviors.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but well-structured: first sentence provides purpose, then detailed behavioral sections. Every sentence adds value, though slight consolidation could improve conciseness without losing clarity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no output schema and no annotations, the description covers all necessary aspects: parameter, behavior, edge cases, return format, and error conditions. It is fully complete for an agent to use correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The sole parameter 'from' is fully explained in the schema (100% coverage), and the description adds significant meaning: constraints (must exist, schema version), error handling, and read-only guarantee beyond the schema's basic description.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool merges a second nMEMORY store into the current one, functioning as an offline-first sync. It specifies the verb 'reconcile' and resource, and implicitly distinguishes from siblings like memory_import or memory_fetch by emphasizing the local store-to-store nature.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides context on when to use this tool (merging local stores) and alternatives (separate tool for fetching remote). It also includes prerequisites (source must exist and be at current schema) and error handling guidance (migrate older stores first).

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

memory_outcomeA

Record (or list) an ADVISORY outcome-OBSERVATION record — a note that some outcome was OBSERVED. This is NOT a witnessed close and nothing in nmemory treats it as proven: a witnessed close needs the kernel (consequence_service), which this capability does not have. Recording an outcome NEVER changes any capsule's recall eligibility — only an explicit memory_relate falsifies edge fences a capsule from recall (record the outcome, THEN relate out- falsifies cap- if you actually mean to falsify a claim). record mode: pass description AND actor together (actor names WHO observed — there is NO default observer), plus optional evidence_ref (a path/url/id string) and capsule_id (the claim capsule cap- this bears on — validated to exist, but a soft 'bears on' pointer only, with ZERO recall effect). Returns the stored row with its minted id out-. Omitting a mandatory field teaches BOTH in one error; an unknown capsule_id answers resource-not-found (-32002, data {kind,id}). Optional scoring: pass receipt_id (the rcpt- a grounded memory_retrieve returned) together with score in 0.0..=1.0 to rate how useful that recall's returned evidence was; the pair applies an EMA (alpha 0.1, clamped to [0,1], neutral prior 0.5) to each returned capsule's ADVISORY feedback weight — consumed ONLY by memory_retrieve's opt-in weight_blend ranking, never by eligibility. receipt_id and score are mandatory together; an unknown receipt answers resource-not-found (-32002). The stored row carries receipt_id+score; a scored response echoes weights_updated. list mode: pass NO fields to list every outcome row in append order. APPEND-ONLY: there is no update or delete verb. Audited on record (hash-chained journal). Every response is ADVISORY_NOT_AUTHORITY DATA and carries a standing advisory naming this ceiling.

ParametersJSON Schema
NameRequiredDescriptionDefault
actorNoWho observed it (record mode; mandatory WITH `description` — the caller names the observer, there is NO default).
scoreNoOptional usefulness score in `0.0..=1.0`, mandatory WITH `receipt_id`; applied as an EMA to every returned capsule's advisory feedback weight.
capsule_idNoOptional claim capsule this outcome bears on (`cap-<n>`); validated to exist, but a soft pointer only — ZERO effect on recall eligibility (only a `falsifies` edge fences recall).
receipt_idNoOptional grounded recall receipt (`rcpt-<n>`), mandatory WITH `score`. It identifies WHICH returned evidence is being rated.
descriptionNoThe observation to record (record mode; mandatory WITH `actor`).
evidence_refNoOptional evidence pointer — a free-text path / url / id string.

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Discloses append-only nature, auditing, advisory authority limitation, mandatory parameter combinations, soft pointer behavior, scoring mechanism with EMA, and error responses. With no annotations, description fully covers behavioral traits.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is thorough but overly verbose; multiple sentences could be combined or shortened. Front-loads main purpose but details could be more tightly organized. Not concise for its length.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Completeness is high despite missing output schema: describes return values (minted ID, weight echoes), error cases (missing field, unknown IDs), and the scoring consumption by memory_retrieve. Covers all necessary context.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, but description adds crucial context: mandatory pairs (actor/description, receipt_id/score), 'soft pointer' nature of capsule_id, and return format including minted IDs and weight updates. Adds significant value beyond schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool records or lists advisory outcome-observation records. It distinguishes itself from witnessed closes and explains it does not change recall eligibility, differentiating from sibling tools like memory_relate.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly explains when to use record mode vs list mode, warns against using for witnessed closes, and advises using memory_relate for falsifying. Provides clear when-to-use and when-not-to-use guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

memory_pinA

Pin (or unpin) ONE capsule so decay never erodes it and the consolidation planner never archives it (S1). Pass id (cap-), pinned (true to pin, false to unpin), and a non-empty reason — pin is a WITNESSED, audited act. A pinned capsule ranks by its FULL confidence on every memory_retrieve and memory_bootstrap surface: decay is exempted at the ranking call site and the stored confidence is NEVER mutated; the archive arm of memory_consolidate skips it. Pin is NEVER eligibility — the recall fences (quarantine / falsified / archived / superseded / currency) run UNCHANGED, so a pinned+superseded (or quarantined or falsified) capsule stays EXCLUDED from recall: pin protects a live grounding capsule, it never resurrects a fenced one. Taint dominates pin: a pinned capsule that is instruction-tainted AND externally-imported still QUARANTINES under memory_consolidate (a pin can never launder taint). Unpin (pinned:false) resumes decay from valid_from. APPEND-ONLY: each call appends a pin/unpin event and state is the latest event; there is no separate delete. Audited (hash-chained journal). An unknown id answers resource-not-found (-32002, data {kind,id}); a tombstoned id, or an empty reason, is a teaching -32602. The pin surfaces as a pinned flag on memory_get / memory_list / memory_digest rows and as memory_digest's pinned section — there is NO new memory_bootstrap pack section. Every response is ADVISORY_NOT_AUTHORITY DATA.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesThe capsule to pin or unpin (`cap-<n>`, an exact store handle).
pinnedYes`true` pins (decay-exempt + archive-vetoed), `false` unpins (decay resumes from `valid_from`). Pin is NEVER eligibility — a pinned+ superseded/quarantined/falsified capsule stays recall-excluded.
reasonYesWhy — a non-empty, audited justification (pin is a witnessed act).

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description fully discloses behavioral traits: decay exemption, archive skip, ranking behavior, append-only audit, error codes, and the pin flag's visibility on other tools. It explains side effects (state is latest event, no separate delete) and invariants (pin never mutates confidence, never launder taint). The description is exhaustive.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is detailed and front-loaded with the core purpose. While it is lengthy, each sentence provides unique value. Minor redundancy (e.g., 'pin is a WITNESSED, audited act' and later 'Audited (hash-chained journal)') could be tightened, but overall it is well-structured for comprehension.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (3 required params, no output schema, no annotations, 19 siblings), the description is remarkably complete. It covers error responses, interactions with other tools (memory_get/list/digest, memory_retrieve, memory_consolidate), and edge cases (taint, superseded capsules). No gaps are apparent.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, but the description adds significant context: id format ('cap-<n>'), reason must be non-empty and audited, and the pinned parameter's semantic meaning beyond boolean (e.g., 'pin is NEVER eligibility'). This enriches the agent's understanding beyond the schema alone.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: pin or unpin a capsule to prevent decay and archive, with a specific verb ('Pin') and resource ('ONE capsule'). It distinguishes from siblings like memory_forget and memory_consolidate by explaining what pin does and does not do (e.g., not eligibility). The scope and effect are unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit context for when to use the tool, including constraints like pin never resurrecting fenced capsules and taint dominating pin. It mentions error conditions (unknown id, tombstoned id, empty reason) and the append-only nature. However, it does not explicitly name alternative tools for when pin is inappropriate, though the sibling list implies them.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

memory_preferenceA

Record (or list) ONE pairwise preference-evidence datum (u6i): preferred_id was chosen over rejected_id, in context, as observed by actor. PAIRWISE ONLY — no score, no ranking, no aggregation beyond the list count. This is EVIDENCE SUBSTRATE for a FUTURE owner-chosen mechanism; nothing in nmemory consumes it yet (it influences no recall and no ranking). record mode: pass preferred_id + rejected_id + context + actor together (all four mandatory). Both ids must name stored capsules — an unknown id answers resource-not-found (-32002, data {kind,id}); a self-pair (preferred_id == rejected_id) is rejected (a preference is two DISTINCT capsules). Returns the stored row with its minted id pref-. Omitting a mandatory field teaches ALL in one error. list mode: pass NO fields to list every preference row in append order. APPEND-ONLY: there is no update or delete verb. Audited on record (hash-chained journal). Every response is ADVISORY_NOT_AUTHORITY DATA and carries a standing advisory naming the rung.

ParametersJSON Schema
NameRequiredDescriptionDefault
actorNoWho expressed the preference (record mode, mandatory).
contextNoWhat the pair was about (record mode, mandatory free text).
rejected_idNoThe rejected capsule id (`cap-<n>`; record mode, mandatory).
preferred_idNoThe preferred capsule id (`cap-<n>`; record mode, mandatory).

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description fully discloses behavioral traits: append-only nature, record mode returns a row with minted id pref-<n>, list mode lists all in append order, audit trail via hash-chained journal, error handling for unknown ids and self-pairs, and advisory nature of responses. All relevant behaviors are transparent.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense but well-structured, starting with the core action and then explaining constraints and modes. Every sentence adds value, though the overall length may be slightly more than minimal. The use of ALL CAPS for key points (e.g., PAIRWISE ONLY, APPEND-ONLY) helps highlight important caveats.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's purpose and the absence of an output schema, the description covers all essential aspects: purpose, modes, input requirements, error cases, return values, audit trail, and advisory nature. It is self-contained enough for an AI agent to correctly invoke the tool without additional context.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Although schema coverage is 100%, the description adds significant context beyond individual parameter descriptions. It clarifies that all four parameters are mandatory together in record mode, that ids must reference existing capsules (with specific error codes), that a self-pair is invalid, and how omission errors are handled. This greatly aids the agent in correct usage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's function: recording or listing a single pairwise preference-evidence datum. It specifies the verb 'record (or list)' and resource 'pairwise preference-evidence datum'. It explicitly distinguishes from sibling tools by emphasizing 'PAIRWISE ONLY — no score, no ranking, no aggregation beyond the list count' and noting that it is 'EVIDENCE SUBSTRATE' not consumed by recall or ranking.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description clearly defines two modes (record and list) and explains when to use each. It provides context that the tool is for future use ('nothing in nmemory consumes it yet') and that it is append-only with no update/delete. However, it does not directly compare to sibling tools to explicitly guide the agent on when to use this tool over alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

memory_relateA

Record ONE directed, typed relation edge from --kind--> to. Closed kinds: supersedes (from replaces to), derived_from (from was materialized out of to), witnesses (from is evidence attesting to — the ATTESTED to, when a blocks-participant, becomes DONE in memory_digest's blocks-dag: proof-carrying CLOSURE that leaves ready/blocked and stops gating dependents yet STAYS recallable — distinct from supersede's REPLACEMENT and forget's DESTRUCTION), blocks (from blocks to — feeds memory_digest's blocks-dag ready/blocked/done projection; cycles are detected there, fail-closed with the concrete cycle — repair = supersede, forget, OR witness a member), falsifies (from contradicts capsule to — the target becomes recall-INELIGIBLE, its bytes untouched and still served by memory_get/list; it is NOT a dag input), proposes (from PROPOSES to replace to — b2 staged review; NAVIGATIONAL only: no dag/ready/done effect and no recall-exclusion effect, and never auto-converted to supersedes), part_of (from is a member of container to — pure membership; NEVER a dag input, so it is byte-inert to the blocks-dag; to MUST be a capsule persisted as kind 'epic' or 'task' — classify the container first), grounded_in (from — the child task/epic/plan node — hangs off parent to; the planning-plane anchor surfaced by memory_digest's mission section, NEVER a dag input). Endpoints: to is ALWAYS a stored capsule; from is a stored capsule too — EXCEPT falsifies, whose from may instead be a stored OUTCOME record id (out- from memory_outcome), i.e. an observed outcome falsifying a claim (capsule→capsule falsifies is also allowed). Edges are readable back on memory_get's relations list (and memory_export / the memory_digest relations count). Both endpoints must be stored (tombstoned still counts — edges are history); self-relations are rejected. Re-recording an edge is an idempotent no-op keeping the first timestamp, answered with already_recorded: true (a fresh write answers false). Recording a falsifies edge is the ONLY way to fence a capsule from recall this way — an outcome record alone never does. Every edge recorded here carries origin 'manual' — a caller decision the machine NEVER auto-reverses; only the stale-import mechanism's own origin='import' supersedes edges can be machine-reversed on re-import (memory_get shows origin on import edges; first write wins on replay). Audited.

ParametersJSON Schema
NameRequiredDescriptionDefault
toYesTarget endpoint, a stored capsule id.
fromYesSource endpoint (`from --kind--> to`), a stored capsule id.
kindYesThe edge kind (closed set).

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries full burden. It discloses idempotent behavior, origin marking, and constraints (both endpoints stored, self-relations rejected). It explains that only 'falsifies' fences recall, and edges are history. It does not mention auth or rate limits, but covers key behavioral traits.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is lengthy and dense, packing many details. While front-loaded with purpose, it could be trimmed for conciseness without losing essential information. Some redundancy exists across kind descriptions.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (9 relation kinds, unique behaviors per kind), the description is remarkably complete. It explains each kind, constraints, idempotency, origin field, and links to memory_digest. No output schema, but response fields are mentioned. Perfectly adequate for an agent to use the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% (3 params). The description adds significant meaning beyond the schema: detailed definitions for each relation kind, constraints on endpoints, and idempotent behavior. This enriches the agent's understanding of how to use the parameters correctly.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: 'Record ONE directed, typed relation edge from --kind--> to.' It specifies the action (record a relation edge) and the resource (relation edges between capsules). With multiple relation kinds detailed, it distinguishes itself from sibling tools like memory_forget or memory_get.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit context on when to use each relation kind, e.g., 'falsifies' is the only way to fence a capsule from recall. It also mentions idempotency and constraints (self-relations rejected). However, it does not directly compare to sibling tools, but the distinct purpose makes it clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

memory_retrieveA

Recall stored memories. Pass caller-expanded terms (your own synonyms/aliases/rephrasings as separate terms; include inflected variants — matching is word-exact, no stemming: "token" does not find "tokens"). At least one term is required (schema minItems:1), and every term must carry at least one alphanumeric character — a punctuation-only or empty term is rejected with a teaching -32602. When the term lane runs, each term is ALSO expanded with its memory_alias-taught aliases (an alias hit grounds and is explained as alias: in matched_terms). Lane routing is the closed set auto|term|vector|fused: omitted/auto preserves historical selection (term without query_embedding, fused with it); term runs only FTS even when a vector is present; vector runs no FTS and requires query_embedding; fused runs both and requires query_embedding. When it runs, the term lane OR-matches terms via FTS5; WITHIN a term, words are AND-matched order/adjacency-insensitively ("tokio pin" finds "pin tokio at 1.38") and Latin diacritics fold ("configuracao" finds "configuração"). Limitation: unspaced scripts (CJK) index as whole runs between spaces/punctuation — a CJK word inside a run will not match; recall CJK content by a full delimited run, store it pre-segmented, OR teach a memory_alias mapping the CJK word to the full run (the alias then grounds the recall). Scope fences: project_id (exact), project_prefix (subtree: "nott" covers "nott" and "nott/x", never "nottx"), and optional session_id AND-compose before ranking. session_id is a character-exact store-local capsule label fence, not authentication or a globally unique bracket identity: accepted bytes are never trimmed, folded, normalized, shape-checked, or length-checked; only a whitespace-only value is rejected. It never consults the sessions table or expires, so finished, orphaned, and merge-imported labels remain recallable. Different stores may both label capsules "sess-1"; after memory_merge, filtering that label intentionally grounds every matching capsule. A non-matching label means no capsule with that label, never an unknown session. Optional time_window {from?, to?} (RFC3339, at least one bound) fences PRE-RANKING by declared fact-time, including BEFORE vector_k selects the vector lane's top eligible cosine matches: a capsule grounds only when its event range intersects the window; capsules without a declaration are excluded and counted as undated (excluded gains outside_time_window/undated). Ranking is lane-specific. Term-only ranking uses coverage descending, then bm25 ascending, then the advisory decay key (confidence × 2^(-age_days/90) from valid_from), freshness, usage late keys, and append order; envelopes carry decayed_weight SERIALIZED ROUNDED to 2 decimals (0.548992 rides the wire as 0.55; ordering uses the unrounded key), and stored confidence is never mutated. Forced-vector ranking uses one-lane RRF over cosine rank. Fused ranking uses two-lane RRF over the independent term and vector ranks. RRF ties use append order, and fusion_rank preserves the pre-weight-blend RRF position. Results are few, dense, token-budgeted (nonzero budget always returns the top result even if it alone overshoots — the floor of one; token_budget 0, like limit 0, returns none; trimmed_by_limit/trimmed_by_budget name the cut cause). Results ride under the results key. Every result is an evidence envelope; its wire fields: label ADVISORY_NOT_AUTHORITY + framing DATA + id + headline + instruction_taint + authority_class + confidence + provenance + freshness + decayed_weight + relevance + bm25 (per-lane ranking keys, absent when that lane did not score the result) + vector_similarity (vector lane only) + anchor_live (advisory path:line existence probe resolving ROOT-RELATIVE anchors against the repo anchor root: true/false/"unknown"; an absolute anchor reads "unknown" — the fence never over-claims liveness for a path it cannot resolve) + anchor_drift (u-r2 advisory CONTENT-change probe beside anchor_live: the anchored file re-hashed through the same fail-closed root fence and compared against its capture-time hash — "unchanged" | "drifted" | "unknown"; "unknown" whenever either hash is unavailable: a non-path or fence-rejected anchor, a symlink, a missing/unreadable file, or a capsule with no capture-time hash recorded — existence questions stay anchor_live's, deletion reads anchor_live:false with drift "unknown") + evidence_state/proof_hint/stale_if (the persisted epistemic sidecar, each present only when annotated — evidence_state is the closed observed|inferred|unverified set; the two hints are ADVISORY STRINGS surfaced verbatim, never executed or evaluated) + matched_terms (the explain: which of your terms grounded it, alias: on alias hits); the full content stays one memory_get away. THREE honest outcomes: "grounded" (eligible evidence found; an excluded {reason: count} section appears when ineligible matches ALSO existed); "missing_evidence" (an executed lane matched — or the lane-independent id probe named a forgotten id — but EVERY match is excluded: per-reason counts under excluded {quarantined, falsified, archived, superseded, expired, not_yet_valid, outside_time_window, undated, tombstoned}; each match counts under the FIRST fence in that order — quarantined dominates everything (the taint signal never disappears), falsified dominates archived+superseded (a falsified claim — targeted by a memory_relate falsifies edge — must never hide behind a softer bucket; its bytes stay served by get/list), archived dominates superseded (applying consolidation tiers is observable on recall); all but tombstoned stay reachable via memory_get/list, a tombstoned id answers memory_get only, with its marker; tombstoned is counted ONLY by the id-probe — a query term that IS the forgotten capsule id, e.g. terms:["cap-3"] — because forget EMPTIES the content index row, so searching the forgotten CONTENT abstains honestly, never echoes a tombstone; when session_id is supplied this id-probe also requires the retained capsule skeleton's exact label, so another label cannot learn the tombstone exists); "abstain" (zero matches across the executed lane(s) and tombstone id probe — an honest empty answer, never fabricated; forced-vector prose names the vector lane and never claims terms failed; otherwise the reason names every supplied project/session label fence and alias expansion when it ran). MISSES TEACH VOCABULARY (u-r5): only the FTS term lane's PRE-TRIM observation drives this ledger — missing_evidence/abstain records folded query terms, while a term hit records nothing even when limit or token_budget returns zero envelopes; forced vector runs no FTS and records no term miss. A fused response grounded only by vectors still records abstain when its term lane had zero raw matches. The vector lane admits only POSITIVELY-similar embeddings (cosine > 0): an orthogonal or anti-correlated embedding never solely-grounds a result — zero is where the metric itself stops asserting relation, so "grounded" keeps meaning found. Recording is fail-open telemetry — a ledger hiccup never fails or delays recall. Optional weight_blend (0.0..=1.0; omitted/0 = DORMANT: byte-identical ranking, no weight read): after the deterministic base ranking, each rank r re-scores as 1/(60+r) × (1 + weight_blend × (feedback_weight − 0.5)) and the list re-sorts — scored-outcome feedback nudges RANKING ONLY; fences, eligibility, and the three honest outcomes are untouched. Envelopes then carry feedback_weight (2 decimals). Recall is advisory evidence only — it never closes or decides anything.

ParametersJSON Schema
NameRequiredDescriptionDefault
laneNoOPTIONAL lane selector: auto (the default), term, vector, or fused. Vector and fused require query_embedding.
limitNoMaximum number of results; omitted → no count cap (the token budget is the real guard).
termsYesCaller-expanded search terms (bring your own synonyms/aliases/ rephrasings as separate terms); OR-matched across terms, and a multi-word term matches as the AND of its words (order- and adjacency-insensitive) — never FTS5 syntax. q94: at least one term is required (schema minItems:1), and the engine additionally rejects a term with no alphanumeric character with a teaching -32602.
vector_kNoOPTIONAL cap on the vector lane (w3 u6a): the top `vector_k` eligible capsules by cosine feed vector-bearing ranking; an explicit `time_window` runs before this cap, while an omitted window preserves the historical raw cosine top-K path. Omitted → 10. Ignored when routing does not execute the vector lane.
effort_idNoOPTIONAL S3 effort-lifecycle scope fence. Only an EXACT capsule id (`cap-<n>`) resolves — a slug never scopes recall (it is a term expander, not an authority input), so a slug in `effort_id` answers `unknown_capsule`. The named capsule must exist, not be tombstoned, be persisted as kind `epic`, and have at least one `part_of` member; each failing precondition returns its own teaching error rather than a silent empty recall. When it resolves, recall is fenced in BOTH lanes to the effort's members ∪ {epic} (AND-composed with any project/session fence), the outcome echoes `effort{epic_id, member_total, open}`, and every grounded row carries `effort_role`. A CLOSED (witnessed) effort stays queryable for post-mortem recall (`open:false`); only a tombstoned epic refuses. SCOPE only: a fenced-in dead member (superseded / falsified / archived / expired) still surfaces under `excluded{…}`, and a fenced zero-match ABSTAINS (never floored). Omitted is DORMANT — byte-identical to a pre-S3 recall.
project_idNoProject fence: only capsules in this project ground the query.
session_idNoCharacter-exact store-local capsule label fence. This does not validate against the sessions table and is not a globally unique bracket identity; finished, orphaned, and merge-imported labels stay recallable. Only a whitespace-only value is rejected.
time_windowNoOptional inclusive fact-time fence. At least one RFC3339 bound is required. Capsules without a declaration are excluded as `undated`; disjoint declared ranges as `outside_time_window`.
token_budgetNoToken budget for the result list (≈ chars/4); omitted → 1500. A NONZERO budget always returns at least the top result (documented floor of one, even when that envelope alone overshoots); 0 returns none, like limit 0.
weight_blendNoOPTIONAL scored-outcome ranking blend in `0.0..=1.0`. Omitted or `0.0` is DORMANT: byte-identical ranking and zero feedback-weight reads. Above zero, weights re-rank only after deterministic base ranking; eligibility and outcome semantics never change.
include_stagedNoOPTIONAL b2 staged review: omitted/false FENCES standing proposals (a capsule whose latest review verdict is not `ratified`) from grounding, counting them under excluded{proposed}. true INCLUDES them, each carrying its review_state on the envelope. Dormant by default: a store with no proposals answers byte-identically either way.
project_prefixNoScope-hierarchy fence: only capsules whose project_id equals this prefix exactly OR starts with it + "/" ground the query — "nott" covers "nott" and "nott/x", never "nottx". AND-composes with project_id. Character-exact (no glob, no case folding). An empty or "/"-terminated prefix can match nothing and is rejected with a teaching error instead of silently answering empty (w2-fix).
query_embeddingNoOPTIONAL caller-fed query embedding (w3 u6a semantic lane). With lane omitted/auto, absence preserves the byte-identical FTS-only engine and presence selects fused recall. Explicit term never reads stored vectors even when this value is present; explicit vector and fused require it. An executed vector lane admits a stored embedding only when its cosine similarity is positive (> 0); an orthogonal or anti-correlated embedding never solely grounds a result (a term-lane miss still records to the u-r5 ledger in fused recall; a forced vector request never writes term-miss telemetry). The embedding is caller-supplied (nmemory computes NO embedding — zero embedder dependency); its dimension must match the store's embeddings (else a teaching -32602 naming both dimensions), and it must be non-empty, finite, and non-zero (else a teaching -32602). Order-sensitive: a retrieve that depends on just-attached vectors must be sent SERIALLY — concurrent frames are answered out of order (the initialize instructions' concurrency law), so a pipelined attach→retrieve can race an empty index.
corroboration_blendNoOPTIONAL S6 corroboration ranking blend in `0.0..=1.0`. Omitted or `0.0` is DORMANT: byte-identical ranking and zero corroboration-weight ranking reads. The independent corroboration explain is still read per returned row. Above zero, the git-witness corroboration weight re-ranks only after deterministic base ranking, multiplying with any `weight_blend` factor in ONE re-sort; eligibility and outcome semantics never change, and stored confidence is never touched.

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description fully bears the burden of behavioral disclosure. It exhaustively details internal processes: ranking formulas, exclusion mechanics, honest outcomes ('grounded', 'missing_evidence', 'abstain'), and handling of edge cases (CJK scripts, diacritics, forbidden parameters). This level of transparency is exceptional.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is extremely verbose (well over 1000 words), containing every conceivable detail. While front-loaded with the purpose, the density of information makes it hard to parse quickly. Conciseness is sacrificed for completeness; a more structured approach (e.g., bullet points) would improve usability.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the complexity (14 parameters, no output schema, multiple edge cases), the description is remarkably thorough. It covers ranking, exclusion, token budgets, and return envelope fields. However, the lack of an output schema means the description must describe results inline, which it does adequately but could be more organized. The overall completeness is high but not perfect.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, but the description adds immense value beyond the schema. For example, the 'terms' parameter explains expansion, OR/AND matching, and rejection of punctuation-only terms. 'time_window' pre-ranking behavior, 'weight_blend' re-ranking details, and 'outcome' semantics are all elaborated. The description compensates fully for any schema brevity.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with 'Recall stored memories,' a specific verb+resource statement that immediately clarifies the tool's core purpose. It further distinguishes itself from siblings like memory_get (single capsule retrieval) and memory_list (listing) by detailing multi-faceted recall with lanes, fences, and ranking.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides extensive guidance on when to use this tool, including lane selection (auto, term, vector, fused), term expansion strategies, and scope fences (project, session, effort). While it implies alternatives (e.g., memory_get for a single capsule), it does not explicitly contrast with all sibling tools, leaving some ambiguity. Overall, the usage context is clear but could be more comparative.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

memory_session_finishA

Close an open session bracket (exactly once) with an optional summary — and an OPTIONAL handoff: the distilled close (what became true / what is open / the next physical action). A present handoff is captured as a NORMAL capsule through the audited ingest path BEFORE the bracket closes — provenance source "memory_session_finish", anchor = the session id, linked to the bracket; project-fence defaults, taint scan, and idempotent dedup all apply — and memory_digest then LEADS with the newest handoff per project (its handoff section), so the next cold session reads the close first. The response names the capsule (handoff_capsule; handoff_deduped: true when the content collapsed onto an existing capsule). A value-rejected handoff (e.g. empty content) fails the WHOLE call with -32602 naming the param — fail closed: nothing captured, the session stays open. A closed bracket accepts no further captures. Both state faults are typed resource-state errors, one family (-32002 + data {kind, id}): an unknown id → {kind: "unknown_session", id}; finishing an already-finished bracket → {kind: "finished_session", id} (never a discriminator-less invalid-params) — a handoff never leaks a capture past either. Audited.

ParametersJSON Schema
NameRequiredDescriptionDefault
handoffNoR6: optional distilled handoff — what became true, what is open, the next physical action. When present it is captured as a NORMAL capsule through the audited ingest path BEFORE the bracket closes (provenance source [`HANDOFF_SOURCE`], anchor = this session id, linked to the bracket; fences, taint scan, and dedup all apply), and `memory_digest` then leads with the newest handoff per project. When absent, finish behaves exactly as before.
summaryNoOptional close-time summary, recorded on the session row.
session_idYesThe open session to close (`sess-<n>`).

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries full burden and does an excellent job disclosing behavioral traits: handoff capture before closure, dedup, taint scan, response fields, error types with structured data.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness2/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is very long and dense, with many technical details included in a single paragraph. It could be broken into more digestible sentences or bullet points.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite no output schema, the description thoroughly explains return values (handoff_capsule, handoff_deduped) and error types with structured data. It covers all necessary behavioral aspects for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3. The description adds significant value beyond the schema by explaining that handoff is distilled and goes through audit/dedup, and that summary is optional. This goes well beyond the schema descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool closes an open session bracket with optional summary and handoff. It uses specific verbs ('Close', 'captured', 'finish') and distinguishes from siblings like memory_session_start by focusing on closing behavior.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains when to use (to close a session with optional handoff) and when not to (unknown or already finished sessions). It does not explicitly compare to alternatives, but the context of sibling tools implies this is the only close tool.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

memory_session_startA

Open a session bracket and return its deterministic store-minted id (sess-). Link captures to it via memory_ingest's session_id; close it with memory_session_finish. Audited.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.2/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations provided, so description carries full burden. It discloses deterministic ID generation and auditing, but does not discuss permissions, side effects, idempotency, or concurrency. Adequate but incomplete for a mutation-like tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, no wasted words. Purpose, ID format, linking instructions, and audit note all delivered efficiently.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given zero parameters and no output schema, description covers the key aspects: what the tool does, how ID is returned, how to use with related tools, and audit. Could mention session limits or reliability, but overall complete for this simple tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

No parameters (schema is empty). Baseline 4 applies as description does not need to add parameter info. Succinct and sufficient.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description states specific verb ('Open') and resource ('session bracket'), details return value format ('sess-<n>'), and explicitly distinguishes from siblings (memory_ingest, memory_session_finish). No ambiguity.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Clearly explains when to use (to start a session), how to link captures and close, and mentions auditing. Lacks explicit when-not-to-use or alternatives, but given the narrow scope with related siblings, this is sufficient.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

memory_vectorA

Attach (or LIST) a CALLER-FED embedding — the u6a semantic sidecar. nmemory computes NO embedding (zero embedder dependency, zero network): YOU compute the vector with your own model and put it here; recall's semantic lane is DORMANT until you do. PUT: pass capsule_id (its id alias is accepted) + embedding:[f32] + model_tag (the caller-declared provenance of the embedding — MANDATORY, the u6a provenance law; it names WHICH model produced these numbers so a later reader can trust/compare them). ONE EMBEDDER PER STORE, mechanically: the first attach elects the store's resident model_tag, and an attach carrying a DIFFERENT tag is refused naming the resident — two same-dimension model spaces must never fuse in one cosine lane; swapping embedders is an explicit migration (re-attach every vector under the new tag). Order-sensitive flows (attach-then-retrieve) must send requests SERIALLY — the stdio server answers concurrent frames out of order (the initialize instructions' concurrency law). ONE embedding per capsule: a second put REPLACES the row (replace-on-write, no vector history) — recorded is STATE (always true; the embedding exists after the call), replaced:true names the overwrite. The embedding is stored as its exact little-endian f32 bytes (bit-exact round-trip) with the dimension recorded; an empty, non-finite (NaN/±inf), or zero-magnitude vector is rejected with a teaching -32602 (cosine is undefined for those), and an empty model_tag likewise. An unknown capsule_id is a resource-state error (-32002, data {kind:"unknown_capsule", id}) — the same family as memory_get. LIST: pass NOTHING to get every stored embedding's {capsule_id, dimension, model_tag} in append order (the vectors' bytes stay off the wire — this is the cheap index). How recall uses it: memory_retrieve lane auto preserves historical presence-based selection (term without query_embedding, fused with it); explicit term ignores stored vectors, explicit vector runs vector-only RRF, and explicit fused runs both lanes; vector/fused require query_embedding, whose dimension must match what you stored here. Vectors NEVER bypass the fences: quarantine, falsification, archive, supersession, freshness, and an optional fact-time window exclude from the vector lane IDENTICALLY to the term lane; under a time_window, a capsule without a declaration is undated in either lane (the fence-dominance law is lane-agnostic). Everything here is ADVISORY_NOT_AUTHORITY: an embedding is recall fuel, never authority, and dropping the whole vector table loses no canonical byte (Capsule v1 is frozen; vectors are a pure sidecar). Audited on put.

ParametersJSON Schema
NameRequiredDescriptionDefault
idNoAlias for `capsule_id` (pass one or the other, not both with different values).
embeddingNoPUT payload: the caller-computed embedding (`f32` vector). nmemory computes NO embedding — this is caller-fed. Mandatory on a put.
model_tagNoPUT provenance (MANDATORY on a put): the caller-declared model that produced `embedding` — the u6a provenance law. Opaque to the store.
capsule_idNoPUT target: the capsule the embedding attaches to (`cap-<n>`). `id` is an accepted alias — pass exactly one. Omit ALL fields to LIST the stored embeddings.

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description fully bears behavioral disclosure. It details that nmemory computes no embedding, stores one per capsule with replace-on-write, rejects invalid vectors, uses bit-exact storage, and describes error codes. It also explains how vectors interact with retrieval and fences, and that embeddings are advisory, not authority.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but efficiently organized: starts with core purpose, then details put/list, then retrieval interaction, then fences and advisory nature. Every sentence adds value for a complex tool, though some sections could be slightly more compact. Still, it is very well-structured.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no output schema and high complexity, the description covers all necessary aspects: input semantics, validation, error conditions, behavior under concurrent access, and integration with memory_retrieve. It explains both put and list modes thoroughly, making the tool fully understandable.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, but the description adds significant meaning beyond the schema. It explains the alias relationship between id and capsule_id, the mandatory nature of model_tag on put, the meaning of omitting all fields for list, and validates constraints. This enriches the schema substantially.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states the tool attaches or lists a caller-fed embedding, clearly distinguishing it from other memory operations by emphasizing that nmemory computes no embedding and that this is a pure sidecar. It explicitly contrasts with memory_retrieve usage.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit guidance on when to use this tool (to attach embeddings for vector retrieval), when not to (if no embedding needed), and alternatives (e.g., explicit term ignores stored vectors). It explains the one-embedder-per-store rule, serial requirement for order-sensitive flows, and how retrieval uses stored vectors.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

memory_visualA

Render the store as ONE deterministic Mermaid diagram (a generated view — nmemory writes no files; the caller pastes the string returned under the response's mermaid key into any mermaid renderer). view is a CLOSED set: "dag" projects the blocks-dag as graph TD — ready (zero live blockers), blocked, and done nodes each styled distinctly; blocks-edge participants only, superseded/tombstoned capsules dead to it (they vanish); a WITNESSED participant is DONE (u-r3: proof-carrying closure — styled distinctly and KEPT in the graph since it stays live and recallable, unlike a dead node); FAIL-CLOSED on a live blocks-cycle among non-done members EXACTLY like memory_digest — the diagram renders ONLY the concrete cycle members plus a fail-closed banner (repair: supersede, forget, or witness a member, then re-digest), never a partial healthy graph. "relations" projects every edge as graph LR, one arrow per relation kind with the kind as the edge label, in memory_export's ## relations order (kind rank, then from, then to). "tiers" groups capsule ids by effective lifecycle tier (active/archived/quarantined) as a flowchart, each node annotated with the SHARED first-line headline (~140 chars, …-terminated when cut). "sessions" projects the exact store-local BINARY union of bracket rows, capsule labels, and grounded recall-receipt labels as a flowchart TD: capsule ROWS are saves (including retained tombstone skeletons), receipt ROWS are recalls (never returned_ids), local brackets are open/closed, and a label with no local bracket is label only. Local brackets order by started_at then exact label; label-only rows follow in exact BINARY label order. Merge-imported labels remain label only unless they collide with a local bracket, in which case matching capsule counts aggregate under that local state. Determinism: byte-identical across two calls on the same store — the view carries NO timestamp, and a leading %% provenance comment pins counts plus a body sha256 over the diagram statements (memory_export's precedent), so regeneration of an unchanged store reproduces it and any hand edit breaks the sha. Syntax safety: capsule ids are safe identifiers, and headlines are entity-encoded so no stored byte (quotes, brackets, pipes, newlines, unicode) can break the diagram. Session node ids are ordinals; before Mermaid entity encoding, session labels receive an injective visible escape: literal backslashes double and controls/U+2028/U+2029 become uppercase minimal \u{HEX}; no raw control reaches Mermaid and exact labels never collapse. project_prefix applies ONLY to view=tiers — it fences the capsule set to a subtree (exact id or id + "/...") exactly like memory_digest's capsule sections (an empty or "/"-terminated prefix is rejected with a teaching error rather than answering an empty diagram). view=dag, view=relations, and view=sessions are STORE-GLOBAL exactly like memory_digest and take NO fence: a project_prefix passed with any of them is REJECTED with a teaching error, never silently ignored. That is what makes the fail-closed-on-cycle law hold UNCONDITIONALLY on the dag view — a live blocks-cycle ALWAYS collapses to the concrete cycle members + banner, never a partial healthy graph, no matter the prefix. Read-only, ADVISORY_NOT_AUTHORITY DATA: a generated view, never an authority surface.

ParametersJSON Schema
NameRequiredDescriptionDefault
viewYesWhich projection to render — closed set `dag` | `relations` | `tiers` | `sessions`.
project_prefixNoOptional subtree fence honored ONLY by `view=tiers` (the capsule-set view), exactly like `memory_digest`'s capsule sections (exact id or id + `/...`; an empty or `/`-terminated prefix is rejected with a teaching error). `dag`, `relations`, and `sessions` are STORE-GLOBAL like `memory_digest` and take no fence: a prefix passed with any of them is rejected by the handler, never silently ignored.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description fully discloses behavioral traits: deterministic generation, no timestamp, syntax safety, node id handling, read-only advisory nature, and failure modes. This is comprehensive.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense and front-loaded with purpose, but the length is justified given the complexity. Every sentence provides important detail, though it could be slightly more concise.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given two parameters, no output schema, and no annotations, the description covers all aspects: view behaviors, parameter constraints, failure modes, determinism, and safety. It leaves no significant gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, but the description adds significant meaning: it explains how project_prefix works, allowed views, and edge cases (rejection of invalid prefixes). This enriches understanding beyond the schema alone.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it renders the store as a deterministic Mermaid diagram, listing four distinct views (dag, relations, tiers, sessions) with specific behaviors. This differentiates it from siblings like memory_digest or memory_export.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains when to use each view and explicitly states that project_prefix only applies to tiers and is rejected for others. It also mentions fail-closed behavior for cycles, but lacks explicit guidance on choosing this tool over alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

  1. 22 tool updatesv0.1.0
    • First observedmemory_alias
    • First observedmemory_bootstrap
    • First observedmemory_classify
    • First observedmemory_consolidate
    • First observedmemory_digest
    • First observedmemory_export
    • First observedmemory_extract
    • First observedmemory_forget
    • First observedmemory_get
    • First observedmemory_import
    • First observedmemory_ingest
    • First observedmemory_list
    • First observedmemory_merge
    • First observedmemory_outcome
    • First observedmemory_pin
    • First observedmemory_preference
    • First observedmemory_relate
    • First observedmemory_retrieve
    • First observedmemory_session_finish
    • First observedmemory_session_start
    • First observedmemory_vector
    • First observedmemory_visual

TDQS

A4.2/5.0
Disambiguation4/5

Tools have distinct purposes, but memory_ingest and memory_classify both can persist classification sidecars, causing minor ambiguity. Overall, descriptions are thorough and roles are clear.

Naming Consistency4/5

All tools use 'memory_' prefix with snake_case. While not strictly verb_noun (e.g., outcome, vector, visual are nouns/adjectives), the pattern is consistent and predictable.

Tool Count5/5

22 tools cover a comprehensive memory management lifecycle including CRUD, import/export, session management, relations, and advisory features. Each tool earns its place without bloat.

Completeness4/5

Covers most operations but lacks a direct content-update tool; modification requires forget+re-ingest. Metadata updates exist via classify, pin, etc. Minor gap for full CRUD parity.

Maintenance

ActivitySlowing
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    A
    maintenance
    Persistent semantic memory for AI agents — hybrid SQLite + FTS5 with DAG-based summaries, context compaction, and 7 MCP tools. Open source, self-hosted, zero API cost.
    152
    MIT
  • A
    license
    A
    quality
    A
    maintenance
    Local-first, source-traceable memory for AI agents — no LLM at ingest, $0 per message, zero data egress. Gives Claude Code, Cursor, and any MCP client one shared persistent memory with semantic recall, belief revision, selective forgetting, and a provenance guard that blocks acting on stale or unconfirmed memories.
    23
    14
    MIT
  • A
    license
    A
    quality
    A
    maintenance
    Local-first memory engine for AI-agent teams: private/team/project ACL, associative recall, and federated sync across nodes. One SQLite file, no LLM required.
    12
    5
    Apache 2.0

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/menot-you/n-memory'

If you have feedback or need assistance with the MCP directory API, please join our Discord server