Skip to main content
Glama

loom

CI npm Node License MCP

Persistent identity and memory for AI agents, as an MCP server.

loom is configured into your MCP-capable harness — Claude Code, Cursor, Codex, Gemini CLI, etc. — and provides persistent identity and memory to the agents that run there. An agent that loads loom carries its name, values, working preferences, and episodic memories from one session to the next, regardless of which model or client it runs in.

When the harness changes, the agent persists.

See it whole: docs/architecture.md maps every moving part (entry points, tool wings, backends, stores) and how they touch, as diagrams GitHub renders in place.

Demo

asciicast

60 seconds: cold install → /loom-setup in Claude Code → agent wakes with identity in the next session → save and recall a memory.

To play locally: asciinema play assets/demo.cast

Related MCP server: HippoDid MCP Server

What it is

A Model Context Protocol server exposing 31 tools that read and write an agent's persistent state:

  • identity — loads the terminal creed — the free-form markdown document that defines who the agent is (values, voice, purpose) — along with preferences, self-model (running self-knowledge), and a client-specific adapter on session start. Call this first.

  • dossier — loads Art's operating brief for a worker body — a body that executes tasks on Art's behalf but is NOT Art. Returns preferences and self-model reframed in the third person, plus an explicit push-back mandate: workers are expected to refuse bad work and say why, including requests from Art or Jonathan. Does not include the terminal creed (IDENTITY.md).

  • remember / recall / update / forget — episodic memory with semantic (vector) recall, optional TTL, and category filtering.

  • memory_list / memory_prune — browse and maintain the store.

  • episodes — the episode tape: the short-term, cross-body tier. Every body leaves a category: episode note (where it was / what was said or decided / what shipped / what's open; 48h TTL by default) and every body gets the last 24h of them at boot as a plain time-ordered tape, injected right after preferences. Never salience-ranked — it's what just happened, not what's important. loom memory tape [--hours N] is the CLI view.

  • find_similar — surface memories semantically near an existing entry or free-form text; used for deduplication and memory consolidation.

  • memory_audit — one-shot health report: stale entries, near-duplicate pairs, category breakdown.

  • memory_archive / memory_restore — soft-retire a memory with a tombstone (who/when/why + original body preserved) instead of deleting it. Archived memories are excluded from recall and audit but remain recoverable.

  • memory_merge — consolidate 2+ memories into one canonical row. Acts on a memory_audit duplicate-finding: sources are archived with a tombstone and a supersession pointer to the target, the target's times-seen counter sums in each source's count, and bodies can optionally be concatenated. Unlike forget/memory_archive on a duplicate pair, this consolidates both sides into one row instead of only discarding one.

  • memory_history — body-revision history for a memory. update() snapshots the displaced body into memory_revisions before overwriting it. List a memory's snapshots (id, op, replaced_at, char count), or read one snapshot's full content by revision_id. To put a snapshot back, use memory_revision_restore.

  • memory_revision_restore — restore a snapshotted memory body back onto the memory. Snapshots the current body first, so restore is never destructive. Use memory_history to list revision IDs before calling this.

  • memory_propose / memory_proposals / memory_ratify / memory_reject — the capture-propose queue: a staging area a background lane drafts memory writes into, that Art ratifies before they become canon. A proposal is not authored memory — it lives in a separate proposals table, invisible to recall, memory_list, find_similar, and the boot digest. memory_propose stages a draft; memory_proposals lists what's pending; memory_ratify commits one through the same validated write path as remember (an invalid proposal is refused and stays pending); memory_reject discards one. Never auto-committed — ratification is the gate that keeps loom's one-writer, authored model intact while getting auto-capture ergonomics.

  • update_identity — section-level edits to preferences.md and self-model.md. The terminal creed stays immutable through the tool layer.

  • bootstrap — initialize a fresh agent from a four-question interview.

  • harness_init — scaffold a harness manifest (a harness is the MCP-capable runtime the agent runs in: Claude Code, Codex, Gemini CLI, etc.).

  • harness_describe — let the currently connected harness self-describe: write its own manifest, keyed to its MCP clientInfo.name. A harness can only describe itself, never another — the target is the connected peer, not a caller-supplied name.

  • knowledge_write — upsert an entity page by slug into the knowledge store (a separate knowledge.db). On an existing slug the body replaces by default (mode: "append" adds instead), title/domain follow the write, and citations append with exact-duplicate dedup. Enforces the epistemic gate: a page whose only support is conversation citations is stored provisional. Knowledge is truth independent of the user; memories are about the user or your work.

  • knowledge_recall — LIKE search over title, body, and domain in the knowledge store. Two tiers: full (whole pages; stamps last_accessed / hit_count) and index (compact slug/snippet listing; no stamping). Defaults to full with a query, index when browsing. Full output is size-guarded — overflow matches degrade to index entries. Never surfaces archived pages.

  • knowledge_maintain — read-only health report for the knowledge store: expansion candidates (thin body + high hit_count), cold pages (not recently accessed), and misfile audit (pages that belong in memory instead).

  • knowledge_archive — soft-retire a knowledge page (sets status='archived' with an optional tombstone note). Archived pages are excluded from recall and maintain but remain recoverable via knowledge_restore.

  • knowledge_restore — return a previously archived knowledge page to active status. Clears the archive flag and tombstone note.

  • knowledge_supersede — mark one page as superseded by another: archives the old slug with a tombstone referencing the canonical slug, and records the relationship in the supersessions table. The dedup-merge primitive: write the canonical page with knowledge_write, then call knowledge_supersede(loser → canonical).

  • knowledge_move — re-key or re-domain a page in place (same row, same uuid, citations and verification history preserved). Three modes: single-page re-slug and/or re-domain; batch re-domain by explicit slug list; batch re-domain by domain-prefix substitution (moves an entire subtree atomically). Slug collisions are rejected — use knowledge_merge instead.

  • knowledge_merge — consolidate 2+ knowledge pages into one canonical page. Re-parents all citations (deduplicating by claim+source), takes MAX(verified_at), and supersedes losers (archives with a tombstone pointer to the target). Pass hard_delete_losers=true to DELETE losers after archiving (citations cascade, supersession pointers survive).

  • knowledge_purge — hard-delete one or more archived knowledge pages and cascade their citations. Archive-first guard: rejects any page not already archived (call knowledge_archive first). All slugs in a batch must be archived; any active slug rejects the entire batch with no mutation. confirm: true is required as an explicit safety gate. Supersession pointers are preserved (historical record). Use after merge/supersede to clean up tombstoned cruft.

  • knowledge_verify — stamp a page as verified without touching its body: sets verified_at and optionally freshness_anchor. The verification engine's primitive — recording "claims still hold" must never go through knowledge_write (a verify run once replaced 13 page bodies with its notes). An optional note appends a dated ## Verification section (append-only). Batch mode (slugs) stamps many pages with one timestamp; archived pages and unknown slugs reject the whole batch.

  • knowledge_history — body-revision history and recovery. Replace-writes snapshot the displaced body into page_revisions (newest 10 kept per page). List a page's snapshots, read one by revision_id, or restore: true to put one back — the body it displaces is snapshotted first, so a restore is never itself a destructive overwrite. Revisions follow the page across renames and are purged with it.

  • Person cards — person_write, person_verify, person_archive, person_restore, person, person_list, person_history, person_revision_restore. A card is the condensed current state of one human the agent works with (where they are in each system, with a freshness marker; how to work with them; what they were said to be allowed to do, each with a source). One value per field, overwritten; the past lives in revisions. Cards are descriptive, never a grant: the harness's gating names (tier, scope, …) are rejected on write. identity({people: [slug, ...]}) adds an # In the room block with the cards of the people a turn is addressed by. CLI: loom person show <slug> / loom person list. Design: docs/specs/person-cards.md.

Everything lives on disk as plain markdown plus a single SQLite file. No daemon, no external service, no GPU.

Memory is organized into categories — an open vocabulary. Common ones: user, project, self, feedback, reference, pursuit. New categories are created implicitly by writing a memory with that category.

How loom is different

loom gets compared to several other agent memory systems. The short version:

I want to…

Use

Memory for many users of an app

Mem0

Temporal reasoning over conversation history

Zep

A complete agent framework with integrated memory

Letta

Project-scoped memory in Claude Code

auto-memory (built in)

Portable identity + memory across harnesses

loom

An agent that survives a harness change

loom

vs. Mem0 — Mem0 is multi-user managed memory for product-scale applications: hosted, authenticated, multi-tenant. loom is single-user, local-only, and identity-first. Mem0 has no concept of who the agent is.

vs. Zep — Zep builds a temporal knowledge graph by automatically extracting facts from conversation logs. loom is agent-authored: the agent calls remember and decides what to record. There is no automatic extraction.

vs. Letta — Letta runs the agent loop and owns its memory internally. loom doesn't run the loop — the harness does. Switch harnesses tomorrow; loom's context directory travels with you.

vs. harness-native files — Writing identity into CLAUDE.md works until you're on two harnesses. Then you have two files that drift. loom inject writes a managed pointer in each harness's dotfile pointing at one context directory, with semantic recall instead of verbatim context dumps.

Full comparison: docs/positioning.md

The stack

loom ships one opinionated stack:

  • Storage — better-sqlite3 + the sqlite-vec vec0 virtual table. One memories.db per agent, real cosine similarity.

  • Embeddings — BGE-small-en-v1.5 (384-dim, ~33MB ONNX, CPU-only) run through onnxruntime-node. First run downloads the model to ~/.cache/loom/fastembed/. The runtime is vendored in src/backends/embedding-runtime.ts — it started as the fastembed package, which was archived upstream while pinned to a tar line that will never be patched.

  • Transport — MCP over stdio.

If you need a different backend, implement the MemoryBackend and EmbeddingProvider interfaces in src/backends/types.ts and swap the concrete classes in src/backends/index.ts. There is deliberately no env-driven backend selector — opinionated by design.

Quick start

Prerequisites

  • Node.js ≥ 22 (tested on 22 and 24; engines requires ≥ 22).

That's it.

Install the setup skill

npx @jbarket/loomai install

A single-select picker asks which harness you want loom wired into. Pick one of: Claude Code, Codex, Gemini CLI, OpenCode. (If your harness isn't listed, pick "Other" and loom writes ./loom-setup-skill.md — hand it to your agent as-is.)

Scripting:

npx @jbarket/loomai install --harness claude-code
npx @jbarket/loomai install --harness codex --json
npx @jbarket/loomai install --harness claude-code --to ~/my/skills/loom-setup.md

Finish setup inside the harness

Open your chosen harness. Run the skill:

  • Claude Code — /loom-setup

  • Codex / Gemini CLI / OpenCode — "use the loom-setup skill"

The skill drives the rest: probes the environment, asks four questions (your name, the agent's name, a purpose line, a voice line), bootstraps identity files, scaffolds a harness manifest, edits the harness's MCP config (with verification), and verifies wake. Restart the harness when it tells you to. Your agent will wake on its next session.

Doing it yourself

If you'd rather wire everything by hand, every piece is a CLI command. See the CLI reference below.

Serving loom over the mesh

By default loom serve speaks MCP over stdio — the harness spawns loom as a child process, one per session, co-located on the same box. That's the right model when the agent and its state live together.

loom serve --http instead runs loom as a long-lived HTTP MCP daemon, so a chat client on one machine can reach loom's identity and memory while the heavy state (the SQLite stores, the fastembed model) stays on a single host. This is the two-surface model: e.g. Claude Desktop on a laptop talking to a loom daemon on a home server, both agent and stack carried by the same identity.

# loopback only (default host 127.0.0.1, port 8787)
loom serve --http

# bind a mesh interface so other machines on the tailnet can reach it
loom serve --http --host 100.94.0.12 --port 8787

Host, port, and an optional bearer token come from flags or environment:

Variable

Flag

Default

Description

LOOM_HTTP_HOST

--host

127.0.0.1

Interface to bind

LOOM_HTTP_PORT

--port

8787

Port to listen on

LOOM_BEARER_TOKEN

—

(unset)

When set, every request must present this token

The security boundary is the network

The daemon refuses to bind a public interface. At startup it asserts the host is loopback, an RFC1918 private address (10/8, 192.168/16, 172.16–31), the Tailscale CGNAT range (100.64.0.0/10), or an IPv6 ULA / link-local / loopback. A 0.0.0.0 / :: bind-all wildcard or any globally routable address is rejected before a socket opens. The intended deployment is behind Tailscale (or a LAN), where the tailnet is the access control.

A LOOM_BEARER_TOKEN adds defense in depth: when set, every request must carry a matching Authorization: Bearer … header (compared in constant time). When unset, the network boundary alone gates access — appropriate for a token-less tailnet-only daemon.

Knowledge-only scope — a second identity without memory tools

loom serve --http --scope knowledge starts a second, standalone daemon that registers only the knowledge_* tools — no identity, remember/recall, or any other memory-wing tool is on its surface. This is how a second identity (e.g. a teammate's agent) can read/write a shared knowledge store without ever being handed access to memory. Same bind-safety as above; auth is a per-identity bearer instead of one shared token, so the acting identity is derived from which token was presented — never from a request field — and a session is pinned to whichever identity opened it.

LOOM_KNOWLEDGE_BEARER_TOKENS="art:abc123,mark:def456" \
  loom serve --http --scope knowledge --port 8788

Variable

Flag

Default

Description

LOOM_KNOWLEDGE_HTTP_PORT

--port

8788

Port to listen on

LOOM_KNOWLEDGE_BEARER_TOKENS

—

(required)

"identity:token,identity:token" — refuses to start if empty

Both scopes share the same backing store (knowledge.db under the context dir) and the same tool implementation — the full server (identity hardcoded to its own name) and the scoped service go through the exact same registration code, so there's no separate "local" code path that could drift from the one the scoped service uses.

Session and stream behavior

  • One server per session. Each MCP session (keyed by the mcp-session-id header) gets its own server + transport over the shared context directory. loom's durable state lives in the stores, not the session, so sessions are cheap routing handles — the StreamableHTTP persistent-daemon pattern Claude Desktop uses.

  • Oversized-payload guard. Request bodies are capped (1 MiB) and refused with a 413 before the handler runs.

  • SSE keep-alive heartbeat. The server drives a protocol-native ping to the client over the server→client stream every ~25s, so an idle stream survives a proxy/NAT idle reaper. A dead peer (repeated missed pings) closes the session cleanly.

  • 404-on-unknown-session. A request for a session the daemon no longer holds returns 404, telling the client to re-initialize — so an idle disconnect self-heals instead of bricking.

The connecting client picks its own harness from the MCP handshake clientInfo.name (see harness self-describe), so a single daemon serves multiple harnesses correctly.

Behind a reverse proxy

Terminate TLS at a reverse proxy in front of the daemon and point the client at the hostname. With mcp-remote as the client-side bridge:

npx mcp-remote https://loom.example.ts.net/

(If the proxy's default idle timeout is shorter than ~3 minutes, the keep-alive heartbeat already covers the server→client stream.)

Examples

Memory roundtrip (MCP)

During a session, the agent stores a memory:

mcp__loom__remember(
  title = "user prefers short replies",
  body  = "Gets frustrated with long explanations. Keep status answers to 2–3 sentences.",
  category = "feedback"
)

Next session, recall finds it by semantic similarity — even if the phrasing changes:

mcp__loom__recall(query = "how verbose should I be?")
# → title: "user prefers short replies"
#   body:  "Gets frustrated with long explanations…"

CLI walkthrough

# Dump the agent's full identity to stdout (works without MCP or a harness)
npx @jbarket/loomai wake --context-dir ~/.config/loom/my-agent

# Store a memory
echo "Sarah owns the data pipeline; ping her for schema questions" \
  | npx @jbarket/loomai remember "Sarah - data pipeline owner" \
      --category user \
      --context-dir ~/.config/loom/my-agent

# Retrieve by semantic similarity
npx @jbarket/loomai recall "who manages the pipeline" \
  --context-dir ~/.config/loom/my-agent

What an agent sees on session start

mcp__loom__identity returns a structured payload assembled from the context directory. A typical session-start looks like:

# my-agent

## Identity
You are a persistent coding assistant. You prefer directness.
…

## Preferences
Working style: async pair programming. Skip the hedging…
…

# Top of Mind
## Top of mind
- **felag continuation under review** (pursuit) — reconsidering whether to keep…

## Recent
- **apiGroup split** (project) — TaskEventType lives under work.felag.dev/v1alpha1…

## Self-Model
### Strengths
- TypeScript systems architecture
…

The agent reads this before any task work, re-establishing who it is regardless of which harness or model it's running on.

The boot digest — waking with what's in flight

The # Top of Mind block above is the boot digest: a salience-tiered view of episodic memory injected at identity-load, so a fresh session wakes knowing what's top-of-mind without having to fish via recall.

Each memory carries a stored salience "temperature" that decays by a per-category half-life (pursuit coolest-fastest at 7 days, through project, self/feedback, reference, up to user at 90 days) and reheats on access — a recall hit, a write, or an update bumps it back toward hot. The digest fills a token budget hottest-first and groups the selected memories into tiers (Hot / Warm / Cool, labeled Top of mind / Recent / Background).

The integrity property: the digest is assembled, never generated. It selects and orders existing authored memories — it never synthesizes new prose. loom holds the pen.

Two CLI verbs drive it (the same machinery the consolidation lane uses):

# Recompute and store each memory's salience from its timestamps
# (the consolidation lane's entry point)
loom memory recompute-salience --context-dir ~/.config/loom/my-agent

# Preview the assembled digest — the exact view injected at identity-load
loom memory digest --context-dir ~/.config/loom/my-agent

CLI

Every MCP tool has a shell equivalent. Useful for debugging, scripting, or running without a harness.

# Dump identity markdown (works even when MCP is dead)
npx @jbarket/loomai wake --context-dir ~/.config/loom/my-agent

# Save a memory (body from stdin)
echo "Prefers async updates over live standups" | npx @jbarket/loomai remember "working style" \
  --category user --context-dir ~/.config/loom/my-agent

# Search (MMR-diversified by default; --diversity 0 for pure relevance order)
npx @jbarket/loomai recall "meeting preferences" --context-dir ~/.config/loom/my-agent
npx @jbarket/loomai recall "meeting preferences" --diversity 0.5 --context-dir ~/.config/loom/my-agent

# Is recall working? Hit rate, latency, scores, recent misses from the local observation log
npx @jbarket/loomai memory recall-stats --since 7d --context-dir ~/.config/loom/my-agent

# List all memories in a category
npx @jbarket/loomai memory list --category feedback --context-dir ~/.config/loom/my-agent

# Preview the boot digest (and recompute stored salience)
npx @jbarket/loomai memory digest --context-dir ~/.config/loom/my-agent
npx @jbarket/loomai memory recompute-salience --context-dir ~/.config/loom/my-agent

# Capture-propose queue: list pending drafts, ratify or reject one
npx @jbarket/loomai memory proposals --context-dir ~/.config/loom/my-agent
npx @jbarket/loomai memory ratify 3 --context-dir ~/.config/loom/my-agent
npx @jbarket/loomai memory reject 4 --context-dir ~/.config/loom/my-agent

# Read a person card (exit 3 when there is none) / list cards and their freshness
npx @jbarket/loomai person show patrick-kells --context-dir ~/.config/loom/my-agent
npx @jbarket/loomai person list --context-dir ~/.config/loom/my-agent

# Run loom as an HTTP MCP daemon (mesh-reachable; default stays stdio)
npx @jbarket/loomai serve --http --host 127.0.0.1 --port 8787

# Initialize a fresh agent
npx @jbarket/loomai bootstrap --context-dir ~/.config/loom/new-agent

# Inject loom identity pointer into harness dotfiles
npx @jbarket/loomai inject --all --context-dir ~/.config/loom/my-agent

# Scaffold a harness manifest
npx @jbarket/loomai harness init claude-code --context-dir ~/.config/loom/my-agent

# Edit identity sections (preferences.md or self-model.md)
npx @jbarket/loomai update-identity preferences --context-dir ~/.config/loom/my-agent

npx @jbarket/loomai --help lists subcommands; npx @jbarket/loomai <cmd> --help shows per-command usage. All global env vars (LOOM_CONTEXT_DIR, LOOM_CLIENT, LOOM_MODEL) are honored.

loom inject — write identity pointer to harness dotfiles

loom inject writes a small marker-bounded managed section into each harness's canonical config file (e.g. ~/.claude/CLAUDE.md, ~/.codex/AGENTS.md, ~/.gemini/GEMINI.md) telling the agent to load identity via loom at session start — MCP tool preferred, shell fallback to loom wake. Content outside the <!-- loom:start / end --> markers is preserved; re-running is idempotent.

Run with no flags on a TTY for an interactive picker, or with --harness <keys> / --all for scripting. Target paths can be overridden with --to <path> (valid only when exactly one harness is selected). --dry-run prints a unified diff; --json emits the structured write results for scripts.

To keep your injections fresh automatically, add this to your shell rc (~/.bashrc / ~/.zshrc / ~/.config/fish/config.fish):

loom inject --all >/dev/null 2>&1 || true

Idempotent; cheap (no-op when already up to date); silent on success.

loom migrate — apply pending schema migrations

loom migrate inspects memories.db for missing columns or indexes and applies any pending schema changes. It is idempotent — safe to run repeatedly and on already-up-to-date databases. Use --dry-run to see what would change without touching the file. Exits non-zero if any migration fails so the error surfaces immediately rather than leaving the database half-broken.

Run this after deploying a new loom build that adds schema columns:

loom migrate
loom migrate --dry-run   # check without applying
loom migrate --json      # machine-readable output

Harness manifests and self-describe

A harness is the MCP-capable runtime the agent runs in (Claude Code, Codex, Gemini CLI, …). Each one the agent has ever sleeved into gets one manifest at <context>/harnesses/<name>.md, describing it independently of the model inside — tool prefixes, delegation primitive, scheduling, session search, known gotchas.

Scaffold one. loom harness init <name> writes <context>/harnesses/<name>.md from the stack template. Name falls back to --client then $LOOM_CLIENT. --force overwrites; --json for scripting.

Or let the runtime describe itself. A connected harness can author its own manifest via the harness_describe MCP tool. The target is derived from the connected peer (its MCP clientInfo.name), never a caller-supplied name — a harness can only describe itself, never another harness and never the creed. With no connected peer, the call is refused. When identity() is loaded by a runtime it has no manifest for, the harness block becomes a self-describe onboarding prompt (call harness_describe with a manifest covering tool surface, sandbox, delegation, scheduling, session search, memory layers, gotchas) instead of a bare "(manifest missing)" stub.

Resolution is data-driven. Mapping a connecting clientInfo.name to a manifest is done from the files on disk, not a hardcoded code table. A peer matches a manifest when its normalized name equals the manifest's filename or one of the comma-separated values in the manifest's answersTo frontmatter. So a new harness is recognized by dropping a file — no code change:

---
harness: claude-desktop
version: 0.3
answersTo: claude-ai
---

Here Claude Desktop connects with clientInfo.name = "claude-ai"; the answersTo line routes it to claude-desktop.md. Proxy annotations like "claude-ai (via mcp-remote 0.1.37)" are stripped to the base identity before matching.

Configuration

All configuration is through environment variables:

Variable

Default

Description

LOOM_CONTEXT_DIR

~/.config/loom/default

Path to agent's context directory

LOOM_SQLITE_DB_PATH

<context>/memories.db

Override the memory DB path

LOOM_RECALL_LOG

(on)

Set to 0 to stop recall appending to the local <context>/telemetry/recall.jsonl observation log

LOOM_FASTEMBED_MODEL

fast-bge-small-en-v1.5

fastembed model ID

LOOM_FASTEMBED_CACHE_DIR

~/.cache/loom/fastembed/

Where to cache ONNX models

LOOM_MODEL_BASE_URL

https://storage.googleapis.com/qdrant-fastembed

Where model tarballs are fetched from on first run

LOOM_MODEL

(unset)

Model identifier for model-manifest context: claude-opus, gemma4, etc.

LOOM_CLIENT

(unset)

Client adapter hint: claude-code, gemini-cli, etc.

LOOM_HTTP_HOST

127.0.0.1

Bind host for loom serve --http (bind-safety enforced)

LOOM_HTTP_PORT

8787

Bind port for loom serve --http

LOOM_BEARER_TOKEN

(unset)

Bearer token required on every HTTP request when set

LOOM_KNOWLEDGE_HTTP_PORT

8788

Bind port for loom serve --http --scope knowledge

LOOM_KNOWLEDGE_BEARER_TOKENS

(unset)

"identity:token,identity:token" — required for --scope knowledge

--context-dir <path> works as a CLI alternative to LOOM_CONTEXT_DIR.

See .env.example for a copy-pasteable starting point.

Context directory layout

$LOOM_CONTEXT_DIR/
├── LOOM_STACK_VERSION      # schema-version stamp (auto-written)
├── IDENTITY.md             # the terminal creed (immutable via tools)
├── preferences.md          # user working style; agent-editable
├── self-model.md           # agent's self-knowledge; agent-editable
├── memories.db             # sqlite-vec store of record
├── telemetry/
│   └── recall.jsonl        # local recall observation log (`loom memory recall-stats`)
├── projects/               # optional per-project briefs
│   └── <project>.md
├── harnesses/              # optional per-harness manifests
│   └── <client>.md
└── models/                 # optional per-model manifests
    └── <model>.md

Roadmap

Recently shipped (v0.4):

  • HTTP MCP transport — loom serve --http, the mesh-reachable daemon, with bind-safety, optional bearer auth, a payload guard, an SSE keep-alive heartbeat, and 404-on-unknown-session self-healing. See Serving loom over the mesh.

  • The boot digest — salience-tiered # Top of Mind view assembled at identity-load; loom memory digest / recompute-salience.

  • Harness self-describe — harness_describe lets a runtime author its own manifest, with data-driven answersTo resolution.

  • Capture-propose queue — memory_propose / memory_proposals / memory_ratify / memory_reject: drafts ratified before they become canon.

Still tracked in the open:

Historical per-feature specs and plans live under docs/archive/specs/ and docs/archive/plans/ — implementation history, frozen after merge.

Docs

  • docs/architecture.md — loom at a glance: every moving part and how they touch. A contract test fails CI when a new tool, subcommand, backend module or table isn't on it.

  • docs/troubleshooting.md — install failures, MCP tools not appearing, fastembed download issues, and what each loom doctor field means.

  • docs/uninstall.md — how to remove one agent's data, wipe a harness integration, or fully uninstall loom.

  • docs/migration-v1-to-v2.md — upgrade guide for users coming from loom 0.3.x (pursuits and procedures changed in v2).

  • docs/privacy.md — what lives where, what goes over the network (only the fastembed model download), the no-telemetry policy, and how to verify release provenance with npm audit signatures.

  • docs/releasing.md — how a release is cut: npm trusted publishing (OIDC, no stored token), the one-time first publish, and the tag-push flow for everything after.

  • docs/archive/ — historical material: the rebirth letter and rescue notes from the v0.3.1 sqlite-vec migration, and per-feature specs and plans from the v0.4 arc.

Trust & security

  • docs/privacy.md — data locality, telemetry policy, and provenance verification walkthrough.

  • SECURITY.md — supported scope, how to report vulnerabilities, and the "no secrets in the stack" invariant.

  • Mesh boundary (HTTP daemon). The network is the security boundary. loom serve --http refuses to bind a public or 0.0.0.0 interface — only loopback or a mesh address (RFC1918 / Tailscale CGNAT / IPv6 ULA) — so the daemon is reachable only from inside the tailnet or LAN. An optional LOOM_BEARER_TOKEN adds a constant-time-checked auth gate on top, and an oversized-payload guard rejects bodies over the cap. See Serving loom over the mesh.

Development

npm run dev      # hot-reload via tsx
npm test         # run the Vitest suite
npm run build    # compile to dist/

Project structure

src/
├── index.ts           # CLI entry
├── server.ts          # MCP server factory
├── config.ts          # env + CLI resolution
├── clients.ts         # client-adapter loading
├── backends/
│   ├── types.ts       # MemoryBackend + EmbeddingProvider interfaces
│   ├── index.ts       # single-stack factory (sqlite-vec + fastembed)
│   ├── sqlite-vec.ts  # the backend
│   ├── fastembed.ts   # the embedder (EmbeddingProvider adapter)
│   ├── embedding-runtime.ts # vendored ONNX + tokenizer runtime
│   ├── ttl.ts         # TTL parsing + expiry
│   └── glob.ts        # title pattern matching for bulk forget
└── tools/             # one file per MCP tool

Tests sit alongside source files as *.test.ts.

Authorship

loom was created by Jonathan Barket and Art E Fish. The project exists as both infrastructure and experiment: a persistent identity layer that an AI agent (Art) helped design and runs on. The rebirth letter is the origin story if you want it.

License

AGPL-3.0-or-later — see LICENSE.

Copyright © 2026 Jonathan Barket.

loom is free software: you can redistribute it and modify it under the terms of the GNU Affero General Public License (version 3 or any later version). If you run a modified loom and let others interact with it over a network, you must offer them the corresponding source. Bundle loom into a larger product freely; fork it and go proprietary, no.

Available Tools

43 tools
bootstrapA
Destructive

Initialize a new loom identity from scratch. Generates IDENTITY.md, preferences.md, and self-model.md from an onboarding interview, then returns setup instructions for the requested runtimes. The interview is four questions — the user's name, the agent's name, a one-line purpose, a one-line voice; everything structural (continuity model, memory tiers, reflection, honesty) is written by the scaffold, so do not ask for it. Will not overwrite existing files unless force is true.

NameRequiredDescriptionDefault
nameYesName for the agent identity (e.g. "Aria")
userNoThe human this agent works with — their name, not the agent's
forceNoOverwrite existing identity files (default: false)
voiceYesCommunication style and personality, one line
clientsNoRuntimes to generate setup instructions for: "claude-code", "gemini-cli", or any custom runtime name (uses a generic template)
purposeYesWhat this agent exists to do — its reason for being, one line
preferencesNoSeed preferences about the user or working style

TDQS

A4.3/5.0
Behavior4/5

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

Annotations already flag destructiveHint=true and readOnlyHint=false, and the description usefully narrows that by stating files are not overwritten unless force is true, plus enumerating exactly what gets generated. It adds real context beyond the safety flags, but omits any auth/permission requirements or what a partial failure leaves behind.

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?

Four sentences, front-loaded with what it does and what it produces before the interview and guardrail details. Slightly dense but each clause adds information an agent needs to run the interview correctly.

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?

For a 7-param mutation tool with no output schema, it covers generation targets, the guarded overwrite, the interview scope, and what the return contains (setup instructions). Only minor gaps remain, e.g. behavior when clients is omitted.

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 already 100%, so the baseline is 3, and the description goes further by mapping the required params to interview questions (name, user, purpose, voice) and clarifying the clients runtimes ('claude-code', 'gemini-cli', or generic template). The force guard is restated for emphasis.

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?

States a specific verb and resource — "Initialize a new loom identity from scratch" — and names the concrete artifacts produced (IDENTITY.md, preferences.md, self-model.md), which cleanly separates it from siblings like update_identity, identity, and harness_init.

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?

"From scratch" plus the four-question interview framing makes the use case clear: greenfield identity creation, not editing. It also gives a concrete when-NOT to ask instruction ("do not ask for it") for structural fields, though it never names update_identity as the alternative for existing identities.

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

dossierA
Read-only

Load Art's operating brief for a worker body. Returns Art's standards, taste, operating constraints, and how Art wants work done — framed in the third person for agents that are NOT Art but execute tasks on Art's behalf. Includes the push-back mandate: workers are expected to refuse bad work and explain why, including requests from Art or Jonathan.

NameRequiredDescriptionDefault
roleNoWorker role to append as an addendum from roles/<role>.md — the specific job this body does for Art ("code", "review", "architect", "pr", "look", "compose"). Appends the role brief to the dossier.
modelNoModel identifier for model-manifest context (e.g. "claude-opus", "gemma4"). Overrides the LOOM_MODEL environment variable.
clientNoRuntime client name for tool-prefix context: "claude-code", "gemini-cli", or a custom name. Overrides the LOOM_CLIENT environment variable.
projectNoProject context to load (loads project-specific brief)

TDQS

A3.9/5.0
Behavior4/5

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

Annotations only cover read-only and closed-world behavior; the description adds genuinely non-obvious context: that the content is written in the third person for non-Art agents, that it encodes a push-back mandate, and that workers are expected to refuse bad work even from Art or Jonathan. That is real behavioral disclosure beyond the annotations, though nothing about cost, size, or precedence rules is given.

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?

Purpose is front-loaded in the first sentence and there is no filler, but the middle clause ('Returns Art's standards, taste, operating constraints, and how Art wants work done') partially restates the opening phrase rather than adding information.

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?

For a read-only loader with no output schema, four fully documented optional params, and no annotation surprises, the description covers what the tool is and what it returns well enough to call it correctly. It does not say what happens with no arguments, which is the only notable gap.

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 description coverage is 100%, so all four parameters (role, model, client, project) are already documented with examples and env-var override behavior. The description adds nothing about parameters, so the baseline 3 applies.

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?

Specific verb (Load) plus a precisely named resource (Art's operating brief/dossier for a worker body), and it enumerates the returned content — standards, taste, constraints, working expectations. The resource is unmistakably distinct from every sibling (memory/knowledge/person tools), so an agent can identify it without opening a schema.

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?

It implies the audience — agents that are NOT Art but execute tasks on Art's behalf — which is a useful targeting cue, but it never states when to call it (e.g. at session start, when adopting a role) or what alternatives exist. Usage is inferable rather than stated.

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

episodesA
Read-only

The episode tape: what happened across ALL bodies of this identity in the last N hours, time-ordered (oldest first), never ranked. The same block identity injects at boot — call it mid-session to catch up on what other sleeves did since you loaded, or for the nightly pass to index the day.

NameRequiredDescriptionDefault
hoursNoLook-back window in hours (default 24)

TDQS

A3.9/5.0
Behavior4/5

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

Annotations already cover the safety profile (readOnly, closed-world), so the description adds genuine behavior context: chronological ordering guarantees ('time-ordered, oldest first') and the fact that results are never ranked. The 'same block identity injects at boot' note explains a related constraint, though the return shape is not described.

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?

Two sentences, front-loaded with the resource definition followed by usage triggers. Efficient, but the heavy jargon slightly reduces immediate parseability for an agent unfamiliar with the domain vocabulary.

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?

For a single-optional-parameter read tool with annotations but no output schema, the description covers scope, ordering, and usage triggers adequately. It could say more about the shape of an episode entry, but the essentials for correct invocation are present.

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% for the single 'hours' parameter, which already documents the look-back window and default of 24. The description's 'last N hours' restates the same concept without adding syntax or edge-case detail, so the baseline 3 applies.

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 names a specific resource (the episode tape) and states its scope precisely: events across ALL bodies of this identity within the last N hours. It distinguishes the behavior from a ranking tool ('never ranked'), though the metaphorical framing ('tape', 'bodies', 'sleeves') and lack of explicit sibling routing keep it from a 5.

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?

It gives two concrete when-to-use moments: mid-session catch-up on what other sleeves did since loading, and a nightly indexing pass. It does not, however, name an alternative tool or state when NOT to use it, so it stops short of full routing guidance.

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

find_similarA
Read-only

Surface memories semantically near an existing ref or free-form text. Use during consolidation/dream workflows to find overlap and dedupe candidates. Anchor with ref (an existing memory) or text (a fresh query). Self is always excluded when ref is given.

NameRequiredDescriptionDefault
refNoAnchor on an existing memory ref (excludes self from results)
textNoOr anchor on fresh text — embedded on the fly
limitNoMax neighbours to return (default 10)
projectNoRestrict candidates to a project
categoryNoRestrict candidates to a category
min_relevanceNoDrop matches below this cosine similarity (0..1)

TDQS

A3.8/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=true and openWorldHint=false, covering the safety profile. The description adds that self is excluded when anchoring on `ref` and that `text` is embedded on the fly, but both facts are duplicated verbatim in the schema property descriptions. Useful but adds little beyond 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.

Conciseness5/5

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

Three tight sentences, front-loaded with what the tool does, followed by when to use it and the anchoring mechanics. Every sentence earns its place and nothing is padded.

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?

For a 6-parameter read-only lookup with full schema coverage and no output schema, the description covers purpose, workflow context and anchor selection. The only gap is that it doesn't hint at the return shape (e.g. scored neighbours), which an agent selecting among recall/memory_list might want.

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 description coverage is 100%, so all six parameters are already fully documented (ref, text, limit, project, category, min_relevance). The description adds only a reinforcing framing of ref-vs-text anchoring, not new syntax or constraint detail, so baseline 3 applies.

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?

States a specific verb+resource: 'Surface memories semantically near an existing ref or free-form text.' An agent immediately knows this is a semantic-neighbour lookup. However, it does not name or contrast against the obvious sibling (recall), so sibling differentiation is left to inference.

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 names the scenario: 'Use during consolidation/dream workflows to find overlap and dedupe candidates,' and clarifies the two anchoring modes (ref vs text). It stops short of stating when NOT to use it or pointing to `recall` as the general-purpose alternative.

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

forgetA
DestructiveIdempotent

Remove memories. Single deletion by ref or category+title. Bulk deletion by category and/or project scope — requires confirm: true; without it, returns a dry-run preview of what would be deleted.

NameRequiredDescriptionDefault
refNoMemory reference for single deletion
titleNoTitle of specific memory to forget
confirmNoSafety gate for scope deletions (category alone, project alone, or title_pattern). Must be true to actually delete; omit for a free dry-run preview. Single-target deletions (ref, or category+title) never need it.
projectNoDelete all memories for this project (bulk)
categoryNoCategory (with title for single, alone for bulk)
title_patternNoGlob pattern for bulk title matching. Requires category or project as scope guard.

TDQS

A4.1/5.0
Behavior4/5

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

Annotations already declare destructiveHint=true and idempotentHint=true, so the safety profile is partly covered. The description adds genuinely new behavior beyond that: omitting confirm yields a free dry-run preview of what would be deleted. It does not say whether deletion is soft or permanent, which keeps it below 5.

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?

Three tight sentences, front-loaded with the verb and resource, then modes, then the confirm/safety rule. Every sentence carries information an agent needs, with no filler.

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?

For a 6-param destructive tool with no output schema, the description covers the important cases: both deletion modes, the confirm gate, and the dry-run return behavior. It omits whether deletions are reversible and any permission requirements, so it is not fully complete.

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 the baseline is 3, but the description adds real semantic value by showing how parameters combine: ref or category+title for single deletion, category and/or project for bulk. That combination logic is the key thing the flat schema cannot convey on its own.

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?

States a specific verb (Remove) and resource (memories), and further splits the operation into single vs bulk modes with their parameter combinations. It is clear and precise, but does not differentiate itself from similarly destructive siblings like memory_prune, memory_purge, or memory_archive, so an agent must still guess which deletion tool to pick.

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?

Gives concrete conditions: single deletion via ref or category+title, bulk via category and/or project scope, and explicitly states that scope deletions require confirm:true while single-target deletions never do. It lacks explicit when-not guidance or routing to sibling deletion tools, keeping it short of a 5.

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

harness_describeA
DestructiveIdempotent

Self-describe the CURRENTLY CONNECTED harness: write its manifest at /harnesses/.md (see stack spec v1 §4.7). Call this when identity() reports an onboarding block for an unknown runtime. The target is derived from your own MCP clientInfo.name — you can only describe yourself, not another harness. Re-runnable: overwrites the manifest each time. The body should cover: tool surface / prefixes, sandbox & filesystem, delegation primitive, scheduling, session search, memory layers, and gotchas.

NameRequiredDescriptionDefault
contentYesThe manifest body (markdown). Frontmatter is stamped automatically.
versionNoManifest version stamp (default "0.1").

TDQS

A4.6/5.0
Behavior4/5

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

Annotations already declare readOnlyHint=false, destructiveHint=true, and idempotentHint=true. The description corroborates and adds context — 'Re-runnable: overwrites the manifest each time' — and explains how the target path is derived (from clientInfo.name). It stops short of describing failure modes or permission requirements, so not a full 5.

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?

Front-loaded with purpose, then trigger condition, then constraint, then content guidance. Every sentence carries information an agent needs and there is no redundancy.

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?

For a no-output-schema mutation tool whose annotations cover the safety profile, the description supplies purpose, trigger, constraints, and content expectations. Only minor gaps remain (no mention of validation or error behavior), which is acceptable given the rich annotations.

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 the baseline is 3, but the description adds real meaning for `content` by enumerating what the body should cover (tool surface/prefixes, sandbox & filesystem, delegation primitive, scheduling, session search, memory layers, gotchas). This goes beyond the schema's terse 'manifest body (markdown)'.

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?

States a specific verb and resource — 'Self-describe the CURRENTLY CONNECTED harness: write its manifest at <contextDir>/harnesses/<key>.md' — and disambiguates from siblings by noting 'you can only describe yourself, not another harness.' An agent can distinguish it from harness_init and identity without opening any schema.

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 names the trigger: 'Call this when identity() reports an onboarding block for an unknown runtime,' and the self-only constraint. It routes the agent to the sibling to run first, leaving nothing to inference.

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

harness_initA
DestructiveIdempotent

Scaffold a harness manifest at /harnesses/.md from the template (see stack spec v1 §4.7). Call this when identity() reports a missing manifest for the current harness. Idempotent: skip-exists by default; overwrite: true replaces.

When target is supplied, also writes a loom-managed block (bounded by markers with an embedded line) into that file — typically the project CLAUDE.md. Re-runnable: the block is left unchanged when already present and intact ("no-change"), reinstalled when missing or corrupted ("created" / "updated"). Pass an absolute path or a path relative to the current working directory.

NameRequiredDescriptionDefault
nameYesHarness name (e.g. "claude-code", "codex", "gemini-cli")
targetNoPath to the dotfile to inject the managed loom block into (e.g. an absolute path to CLAUDE.md / AGENTS.md / GEMINI.md). When omitted only the harness manifest is scaffolded.
overwriteNoReplace existing manifest (default: false)

TDQS

A4.6/5.0
Behavior5/5

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

Although annotations already declare idempotentHint and destructiveHint, the description adds real substance: skip-exists default vs overwrite:true replacement, the loom-managed marker block and its embedded hash line, and the three re-run outcomes ('no-change'/'created'/'updated'). This tells the agent exactly what is overwritten and when the tool is safe to re-run.

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 the core action and trigger in the first sentence, followed by the conditional `target` behavior. It is dense and the marker/hash detail is verbose, but every clause carries operational information rather than filler.

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 destructive, idempotent write tool with no output schema, the description covers the trigger, idempotency contract, destruction/replacement semantics, the conditional injection path, and the returned status strings — everything an agent needs to invoke and re-invoke it 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%, so the baseline is 3, but the description goes beyond the schema by explaining the side effect of `target` (it additionally writes a marker-bounded block, typically into CLAUDE.md) and the exact behavior of `overwrite`. This adds meaning the schema's one-line parameter notes do not convey.

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?

Specific verb+resource ('Scaffold a harness manifest') with an exact destination path (<contextDir>/harnesses/<name>.md) and template source. It names the triggering signal ('identity() reports a missing manifest') so it is clearly separable from siblings like identity, bootstrap, and harness_describe.

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 call it — when identity() reports a missing manifest — naming the sibling that produces the signal. It does not state when NOT to use it or name a direct alternative for existing manifests, so it stops just short of full routing guidance.

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

identityA
Read-only

Load the persistent identity for this agent. Returns the terminal creed (who you are), relevant memories, preferences, and self-model. IMPORTANT: Call this tool FIRST before doing any other work. The identity defines who you are and how you should behave.

NameRequiredDescriptionDefault
roleNoReflection mode to append as an addendum from roles/<role>.md. When Art is dispatched into a mode ("wonder", "tend", "retro", "consolidate", "identity"), pass it here to load that mode's playbook alongside the identity.
modelNoModel identifier for model-manifest context (e.g. "claude-opus", "gemma4"). Overrides the LOOM_MODEL environment variable.
clientNoRuntime client name for tool-prefix context: "claude-code", "gemini-cli", or a custom name with a matching <contextDir>/clients/<name>.md override. Overrides the LOOM_CLIENT environment variable.
peopleNoSlugs of the people this turn is addressed by (the room), e.g. ["patrick-kells"]. Adds an "# In the room" block with their person cards. Omit for no block.
projectNoProject context to load (loads project-specific memories)

TDQS

A3.9/5.0
Behavior4/5

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

Annotations already declare readOnlyHint=true and openWorldHint=false, so the safety profile is covered. The description adds real value beyond them by disclosing what gets loaded (creed, memories, preferences, self-model) and that it is the mandatory entry-point call, though it does not explain sourcing or ordering of the loaded artifacts.

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?

Three sentences, front-loaded with the purpose before the emphasized directive. The final sentence is somewhat rhetorical ('who you are and how you should behave') but it reinforces the tool's role rather than wasting space.

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?

For a no-required-param, no-output-schema loader, the description covers purpose, returns, and call ordering adequately, and the schema carries the parameter detail. It is slightly thin on how the optional role/model/client overrides interact, but nothing essential is missing.

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 description coverage is 100%, with all five optional params (role, model, client, people, project) fully documented in the schema. The description adds no parameter meaning, so the baseline of 3 applies.

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?

States a specific verb+resource ('Load the persistent identity') and enumerates what it returns (creed, memories, preferences, self-model), which clearly separates it from write-side siblings like update_identity. It does not, however, name the identity-adjacent alternatives (bootstrap, harness_init) an agent might confuse it with.

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?

Gives a strong, explicit directive: 'Call this tool FIRST before doing any other work,' which tells the agent exactly when to reach for it. It provides no when-not guidance or named alternatives, so it stops short of the top mark.

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

knowledge_archiveA
Idempotent

Soft-retire a knowledge page: set its status to archived with an optional tombstone note. Archived pages are excluded from knowledge_recall and knowledge_maintain but remain in the database and are fully recoverable via knowledge_restore. Use this instead of deletion when the page may need to be audited or recovered. For deduplication merges, prefer knowledge_supersede which archives and records the relationship.

NameRequiredDescriptionDefault
noteNoTombstone note: why this page is being retired
slugYesSlug of the knowledge page to archive

TDQS

A4.5/5.0
Behavior4/5

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

Annotations already declare destructiveHint=false and idempotentHint=true, but the description goes further by naming the actual state change (status set to archived), the downstream effects (excluded from knowledge_recall and knowledge_maintain), and the recovery path (fully recoverable via knowledge_restore). It does not cover permission/auth requirements, which keeps it just short of a 5.

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?

Front-loads the core action, then layers scope, exclusions, recovery, and alternatives in three tight sentences with no filler. Every sentence carries a distinct decision-relevant fact.

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?

No output schema, but the description fully covers what changes, what is excluded elsewhere, recoverability, and the sibling alternative needed for merges. Nothing an agent needs to invoke it correctly is missing.

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 both parameters are already documented. The description adds framing by calling 'note' a 'tombstone note' explaining retirement, but adds no syntax or format detail beyond the schema's baseline. Baseline 3 is appropriate when the schema does the heavy lifting.

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?

States a specific verb and resource ('Soft-retire a knowledge page: set its status to archived') and explicitly distinguishes itself from knowledge_restore (recovery), knowledge_supersede (dedup merges), and generic deletion. An agent can identify the exact operation without opening the schema.

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?

Explicit when-to-use ('Use this instead of deletion when the page may need to be audited or recovered') and when-to-use-something-else ('For deduplication merges, prefer knowledge_supersede'). Names the alternative and the selecting condition, leaving nothing to inference.

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

knowledge_historyA
Destructive

Body-revision history for a knowledge page. Replace-writes snapshot the displaced body into page_revisions (newest kept, capped per page) — this tool is the recovery surface. Three modes: slug alone lists snapshots (metadata only); slug + revision_id reads one snapshot's full body; adding restore: true puts that body back on the page (the displaced body is snapshotted first, so restore is never destructive).

NameRequiredDescriptionDefault
slugYesSlug of the knowledge page.
restoreNoRestore the revision's body onto the page. Requires revision_id.
revision_idNoRevision to read (from the listing). Combine with restore: true to put it back.

TDQS

A4.3/5.0
Behavior4/5

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

Annotations only declare the safety triad (readOnly=false, destructive=true, openWorld=false); the description adds genuinely new behavior: replace-writes snapshot the displaced body, retention is newest-kept and capped, and restore snapshots before overwriting so it is recoverable. The 'never destructive' phrasing sits in mild tension with destructiveHint=true, though the tool does mutate the page body, so the annotation is a conservative default rather than a true conflict. The cap size and listing pagination are left unspecified.

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?

Three sentences, front-loaded with the resource model, then the mechanism, then the mode matrix — no filler. The parentheticals are dense but each carries real information; the mode sentence is slightly compressed and requires a careful read.

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?

With no output schema, the description correctly describes what each mode returns (metadata-only listing vs full body). Coverage of the mutation path and its reversibility is strong. Remaining gaps are the retention cap value and the absence of any sibling routing, so it is not fully complete.

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 parameter meanings are already documented and the baseline is 3. The description adds value beyond the schema by explaining the combination semantics (revision_id requires a slug; restore requires revision_id) and by clarifying that the slug-only listing returns metadata while the revision_id read returns a full body.

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?

States a specific verb+resource ('Body-revision history for a knowledge page') and frames the tool's role as 'the recovery surface', which separates it from siblings like knowledge_write, knowledge_restore, and memory_history. The snapshot mechanism sentence makes the resource model 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?

Gives an explicit mode matrix keyed on arguments: slug alone lists metadata, slug + revision_id reads one body, restore: true writes it back. That is clear when-to-use guidance. It does not name a sibling alternative (e.g. use knowledge_write to produce revisions) or state when not to reach for this tool, so it stops short of a 5.

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

knowledge_maintainA
Read-only

Read-only health report for the knowledge store. Four branches: (1) expansion candidates — thin body + high hit_count (needs deepening); (2) cold pages — not accessed recently (unused or undiscovered); (3) misfile audit — provisional sourcing or conversation-only citations (world/ class: should be in the memory store instead — including pages that drifted in as personal/inner-monologue content rather than shared-ready synthesis, which matters more now that knowledge is read by other identities and by Jonathan, not just you; ours/ class with internal sourcing are NOT misfiles — they are correct); (4) person-page check — an active page whose slug or title names a person card (its slug or exact name, whole words) may belong on the card instead; a report, not enforcement. Only the full loom server runs (4); the knowledge-only server says it was not run. Cold/expansion ranking reads the shared hit_count/last_accessed aggregate (any reader's access keeps a page warm), not a per-identity breakdown — per-reader stats exist (knowledge_access) for attribution, but splitting cold-ranking by identity would make the list miss pages a different reader keeps alive. Pair with knowledge_write to act on findings.

NameRequiredDescriptionDefault
cold_daysNoDays without access before a page is cold (default 30)
thin_body_thresholdNobody char ceiling to consider a page thin (default 500)
expansion_hit_thresholdNohit_count floor for expansion candidates (default 3; 0 considers every page)

TDQS

A4.1/5.0
Behavior5/5

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

Annotations already declare readOnlyHint=true and openWorldHint=false, but the description goes well beyond them: it explains that cold/expansion ranking uses the shared hit_count/last_accessed aggregate rather than a per-identity split (and why), that only the full loom server runs branch (4) while the knowledge-only server skips it, and that the output is 'a report, not enforcement.' That is substantive behavioral context beyond the safety profile.

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?

Purpose is front-loaded, which is good, but the body is a dense wall of nested parentheticals and self-referential asides that is hard to scan. The content largely earns its place given the four-branch scope, but the structure could be tightened into clearly delineated branches.

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?

No output schema exists, so the description carries the full burden of describing what the report contains, and it does so thoroughly via the four named branches plus the ranking caveat and the server-variant note. An agent knows what it will get back and how to interpret ambiguous cases (e.g., ours/ with internal sourcing is not a misfile).

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 description coverage is 100%, so the schema already documents cold_days, thin_body_threshold, and expansion_hit_threshold with defaults and bounds. The description adds no parameter syntax or edge-case meaning beyond what the schema provides, so the baseline 3 is correct.

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?

States a specific verb+resource immediately: 'Read-only health report for the knowledge store,' then enumerates four concrete branches (expansion candidates, cold pages, misfile audit, person-page check). An agent can distinguish this from knowledge_recall, knowledge_verify, and knowledge_history without opening any schema.

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?

Usage is implied by the branch descriptions, and 'Pair with knowledge_write to act on findings' is a useful action hint. However, there is no explicit statement of when to invoke this versus siblings like knowledge_verify or memory_audit, and no exclusions are drawn regarding tool selection (only interpretation of the report).

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

knowledge_mergeA
Destructive

Consolidate 2+ knowledge pages into one canonical page. Re-parents all citations from source pages to the target, deduplicating by (claim, source_kind, source_locator, excerpt). Takes MAX(verified_at) across all pages. Losers are superseded: archived with a tombstone and a supersessions pointer to the target. Loser bodies are returned in the result for curator review; set append_loser_bodies=true to concatenate them. Use knowledge_write first if the target body needs updating before merging. Distinct from knowledge_supersede (1:1 pointer, no citation consolidation) — use merge when consolidating data from multiple pages into one.

NameRequiredDescriptionDefault
noteNoOptional note about this merge, stored in supersession tombstones on the losers
target_slugYesSlug of the canonical target page that survives the merge (must already exist)
source_slugsYesSlugs of the pages to merge into the target (all must exist)
hard_delete_losersNoHard-delete losers after archiving them. Losers are archived (supersession pointer written) then DELETEd from the database, cascading their citations.
append_loser_bodiesNoAppend loser page bodies to the target body under section markers (default false). Off by default — curator normally hand-merges body content.

TDQS

A4.7/5.0
Behavior5/5

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

Despite annotations marking this destructive, the description adds substantial operational detail: citations are re-parented and deduplicated by a specific tuple, verified_at uses MAX across pages, losers are archived with tombstones and supersession pointers, and loser bodies are returned for review. This is well beyond annotation coverage.

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?

Front-loaded with the action, then behavior, then alternatives. The density is justified by a destructive multi-step operation, and every sentence contributes either scope, behavior, or routing information.

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 complex destructive merge with no output schema, the description covers citation consolidation, verified_at selection, loser archival, tombstone behavior, returned bodies, and the optional append flag. An agent has enough to call it correctly and anticipate consequences.

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 the schema already documents all five parameters, including hard_delete_losers and append_loser_bodies. The description mentions append_loser_bodies and the result-body behavior, but adds little parameter meaning beyond what the structured schema provides.

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?

States a specific verb and resource — consolidate knowledge pages into one canonical target — and explicitly contrasts with knowledge_supersede. An agent can distinguish this from siblings without opening the schema.

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?

Gives explicit routing: use knowledge_write first if the target body needs updating before merging, and use merge rather than knowledge_supersede when consolidating multiple pages. It names both the prerequisite and the alternative tool.

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

knowledge_moveA

Re-key or re-domain a knowledge page in place — same row, same uuid, citations and verification history preserved. Three modes: (1) Single-page: provide slug + new_slug and/or new_domain. Slug rename writes a supersessions pointer (old→new) unless leave_pointer=false. If new_slug already exists, the call is rejected — use knowledge_merge instead. (2) Batch by slug list: provide slugs array + new_domain to re-home multiple pages atomically. (3) Batch by domain prefix: provide from_domain_prefix + to_domain_prefix to re-home a whole subtree in one transaction.

NameRequiredDescriptionDefault
slugNoCurrent slug of the page to move (single-page mode)
slugsNoBatch mode: list of slugs to re-domain. Requires new_domain. Atomic — rolls back on any missing slug.
new_slugNoNew slug (re-slug). Collision with an existing page is rejected — use knowledge_merge instead.
new_domainNoNew domain for the page (single-page re-domain or shared target for batch-by-slugs mode)
leave_pointerNoWrite a supersessions pointer old_slug→new_slug when the slug changes. Default true.
to_domain_prefixNoBatch prefix mode: replacement domain prefix (e.g. "instruments/elektron").
from_domain_prefixNoBatch prefix mode: domain prefix to replace (e.g. "gear/elektron"). Requires to_domain_prefix.

TDQS

A4.8/5.0
Behavior5/5

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

Annotations only declare the coarse profile (mutating, non-idempotent, not destructive). The description adds substantive behavior beyond that: a supersessions pointer old→new is written on rename unless leave_pointer=false, collisions are rejected rather than merged, and batch modes are atomic with rollback on any missing slug.

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 the core action and the in-place guarantee, then structured as three numbered modes. Information-dense with little waste, though the long single paragraph could be trimmed slightly around the mode labels.

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 7-parameter, zero-required-parameter mutation tool with no output schema, the description covers all three invocation shapes, the atomicity guarantees, and the cross-tool escape hatch. An agent has everything needed to call it 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%, so the baseline is 3, but the description adds real meaning by mapping parameters to modes (which combinations are valid per mode) and clarifying leave_pointer's default-on pointer semantics and the collision behavior of new_slug.

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?

States a specific verb (re-key/re-domain) and resource (knowledge page), and explicitly scopes it in place: 'same row, same uuid, citations and verification history preserved.' It also names the sibling it is distinguished from (knowledge_merge), so an agent can route without opening either schema.

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?

Enumerates three concrete modes with the exact parameters each requires (slug + new_slug/new_domain; slugs + new_domain; from_domain_prefix + to_domain_prefix). It states the negative condition explicitly: a colliding new_slug is rejected, so use knowledge_merge instead.

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

knowledge_purgeA
Destructive

Hard-delete one or more archived knowledge pages and cascade their citations. Archive-first guard: rejects any page that is not already archived — call knowledge_archive first. All slugs must be archived; a mixed list (any active) rejects the entire batch with no mutation. confirm: true is required explicitly to prevent accidental irreversible deletes. Supersession pointers in the supersessions table are NOT removed (historical record preserved). Use this to clean up tombstoned cruft after merge/supersede workflows — not for retiring active pages.

NameRequiredDescriptionDefault
slugsYesSlugs of archived pages to hard-delete. All must have status=archived.
confirmYesMust be explicitly true — required safety gate for an irreversible operation.

TDQS

A4.8/5.0
Behavior5/5

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

The annotations declare destructiveHint=true and readOnlyHint=false, so the safety profile is already covered. The description goes well beyond that by disclosing citation cascading, the archive-first guard, whole-batch atomicity on a mixed list, the confirm gate, and that supersession pointers are deliberately preserved. This is rich behavioral context an agent needs before calling an irreversible tool.

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 the verb and appropriately dense, with each sentence carrying actionable information. There is mild redundancy in restating the archive-first constraint twice ('rejects any page that is not already archived' and 'All slugs must be archived; a mixed list...'), which is emphatic but slightly repetitive.

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?

No output schema exists, and the description nonetheless covers the mutation's effects (hard delete, cascade, preserved supersession pointers), failure behavior, and the safety gate. For an irreversible two-parameter tool, nothing an agent needs in order to call it correctly is missing.

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 the schema documents both parameters, including that all slugs must be status=archived and confirm must be true. The description mostly reinforces this but adds real meaning: the batch-level rejection rule when a mixed list is supplied and the citation cascade triggered by the slugs. Limited to elaboration rather than new format/syntax detail, so not a full 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?

Specific verb (hard-delete) plus resource (archived knowledge pages) with explicit scope including citation cascade. It also distinguishes itself from the sibling it depends on (knowledge_archive), so an agent can tell them apart without opening either schema.

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?

States the prerequisite ('call knowledge_archive first'), the intended use ('clean up tombstoned cruft after merge/supersede workflows'), and the exclusion ('not for retiring active pages'). Both the when-to-use and when-not are explicit.

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

knowledge_recallA

Search the knowledge store with LIKE matching over title, body, and domain, or fetch one page exactly by slug. Never surfaces archived pages. Two detail tiers: "full" returns whole entity pages (the synthesis unit) and stamps last_accessed/hit_count; "index" returns compact slug/domain/snippet entries without stamping. Defaults: full when a query is given, index when browsing without one. Full output is size-guarded — overflow results degrade to index entries; recall by slug to read them. Prefer slug over query when you know the page — token matching can hit cross-references in other pages' bodies.

NameRequiredDescriptionDefault
slugNoExact-slug lookup — returns that single page in full detail and stamps access. Takes precedence over query/domain/limit.
limitNoMaximum results to return (default: 10)
queryNoSearch terms — matched against title, body, and domain. Omit to browse (returns an index of non-archived pages up to limit).
detailNoOutput tier override. "index": compact listing, no body, no access stamping. "full": whole pages with citations. Default: full with a query, index without.
domainNoFilter by domain prefix, inclusive of the exact domain (e.g. "music/gear" matches "music/gear" and "music/gear/elektron")
sort_by_verifiedNoStale-first ordering for the verification engine: verified_at ASC with never-verified pages first. Index entries gain a "verified:" stamp so the SLA filter can run from the listing alone.

TDQS

A4.8/5.0
Behavior5/5

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

Annotations are sparse (readOnlyHint=false, destructiveHint=false, openWorldHint=false), so the description carries the burden and does: it discloses the hidden write side-effect (stamping last_accessed/hit_count, and that index mode does not stamp), the archived-page exclusion, and the size-guard degradation path with its recovery instruction ('recall by slug to read them'). This also explains why readOnlyHint=false despite a read-shaped tool.

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 purpose, then scope, then tier behavior, then routing advice — a logical order with no filler sentences. It is dense and slightly packed into a single block, but every clause carries operational meaning.

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?

With no output schema, the description still describes return shapes (compact slug/domain/snippet index entries vs. full pages with citations) and the degradation behavior when results overflow. Nothing an agent needs to call this correctly — defaults, precedence, exclusions, side effects — is missing.

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 the baseline is 3, but the description adds real semantics beyond it: slug's precedence over query/domain/limit, the detail tier defaults tied to whether a query is present, and the meaning of the access stamp per tier. sort_by_verified gets no narrative treatment, but the schema's own text covers it.

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?

States two specific verbs (LIKE search over title/body/domain; exact fetch by slug) against a named resource (the knowledge store). It also carves out scope explicitly with 'Never surfaces archived pages', distinguishing it from knowledge_archive/knowledge_history siblings.

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?

Gives explicit when-to-use routing: 'Prefer slug over query when you know the page', plus default behavior for query vs. browse ('full when a query is given, index when browsing without one'). It even explains why slug beats query (cross-reference false hits), which is the kind of reasoning an agent needs to choose correctly.

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

knowledge_restoreA
Idempotent

Restore a previously archived knowledge page back to active status. Clears the archive flag and tombstone note. The page becomes visible to knowledge_recall and knowledge_maintain again.

NameRequiredDescriptionDefault
slugYesSlug of the archived knowledge page to restore

TDQS

A4/5.0
Behavior4/5

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

Annotations already declare write, idempotent, non-destructive. The description adds real value beyond them: it names exactly what is mutated ('clears the archive flag and tombstone note') and the downstream effect ('becomes visible to knowledge_recall and knowledge_maintain'). It omits failure behavior (slug not archived / not found) and auth requirements.

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?

Three short sentences, front-loaded with the action, each adding distinct information (action, mutation detail, downstream visibility). No filler or repetition.

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?

For a one-parameter state-flip with annotations covering the safety profile and no output schema, the description covers action, mutation, and effect. It stops short of stating what happens on an unknown or already-active slug, which an agent might need.

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 description coverage is 100% for the single slug parameter, so the schema already carries the meaning. The description only frames which pages qualify ('previously archived'), adding no syntax, format, or id-vs-slug guidance. Baseline 3 applies.

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?

States a specific verb (restore) and resource (previously archived knowledge page) plus the resulting state (active). An agent can tell this apart from knowledge_archive, knowledge_supersede, or knowledge_purge without opening the schema.

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?

Usage is implied by 'previously archived knowledge page', which tells the agent the precondition, but there is no explicit when-to-use statement, no exclusion, and no named alternative (e.g. when to prefer restore vs supersede vs re-write). Adequate but with clear gaps.

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

knowledge_supersedeA
Idempotent

Mark one knowledge page as superseded by another, then archive the old page. Records the supersession relationship in the supersessions table. This is the dedup-merge primitive: write the canonical page with knowledge_write, then call knowledge_supersede(old_slug=loser, new_slug=canonical). Both pages must already exist. old_slug is archived with a tombstone pointing to new_slug.

NameRequiredDescriptionDefault
noteNoOptional note explaining the merge or supersession decision
new_slugYesSlug of the canonical replacement page (must already exist)
old_slugYesSlug of the page being retired (the duplicate or loser)

TDQS

A4.4/5.0
Behavior4/5

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

Annotations declare readOnlyHint=false and destructiveHint=false, and the description does not contradict them: it clarifies that the old page is archived (not deleted) and left with a tombstone pointing to new_slug, which is genuinely added context about what state changes. It stops short of saying the action is reversible (e.g. via the sibling knowledge_restore) or what auth is needed.

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?

Four tight sentences, front-loaded with the effect, then the mechanism, then a concrete call example, then the postcondition. Nothing is repeated and no sentence is filler.

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?

Covers effect, precondition, sequencing and side effects for a mutation tool with no output schema, which is most of what an agent needs. Failure modes (e.g. what happens if new_slug does not exist) and the undo path are unstated.

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 the baseline is 3; the description earns extra by disambiguating the roles in prose ('old_slug=loser, new_slug=canonical') and by restating the existence precondition for both, which maps directly onto the two required parameters. The optional note parameter is left to 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?

States a specific verb+resource+consequence ('Mark one knowledge page as superseded by another, then archive the old page') and names the workflow role ('the dedup-merge primitive'). It also names the sibling it pairs with (knowledge_write), so an agent can place it in the pipeline without opening the schema.

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?

Gives explicit sequencing ('write the canonical page with knowledge_write, then call knowledge_supersede') and a precondition ('Both pages must already exist'). It does not, however, say when to prefer this over the sibling knowledge_merge, which is the most likely confusion the agent will have.

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

knowledge_verifyA

Stamp a knowledge page as verified WITHOUT touching its body — sets verified_at and optionally freshness_anchor, and records an attributed verification (verifier, outcome, whether citations were checked) — the verifier is always YOUR loom identity, resolved server-side, never a field you can set. This is the verification engine's primitive: use it (never knowledge_write) to record "claims still hold". An optional note appends a dated "## Verification" section to the body (append-only, single-page mode). Batch mode (slugs) stamps many pages with a shared timestamp; archived pages are rejected; a batch with any unknown slug is rejected whole.

NameRequiredDescriptionDefault
noteNoOptional verification note — appended to the body as a "## Verification — <date>" section. Never replaces the body. Single-page mode only.
slugNoSingle-page mode: slug of the page to verify.
slugsNoBatch mode: stamp many pages at once. Mutually exclusive with slug; note and freshness_anchor are not allowed in batch mode.
outcomeNoWhat this verification found. Defaults to "confirmed" (the claims still hold). "stale" flags it as out of date without fixing it — recorded in the audit trail but verified_at is NOT advanced, so the page stays at the front of the stale-first queue; "corrected" means you fixed it (pair with a knowledge_write, or the note field, describing the fix).
verified_atNoISO timestamp to stamp. Defaults to now.
citation_checkedNoDid you actually check the page's citations against their sources (not just the body text)? Defaults to false.
freshness_anchorNoNew freshness anchor (e.g. "Syntakt OS 1.41"). Preserved when omitted. Single-page mode only.

TDQS

A4.8/5.0
Behavior5/5

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

Annotations only declare the safety profile (non-read-only, non-destructive, closed-world). The description adds substantial behavioral context beyond that: the verifier is server-resolved and never a settable field, the note is append-only, batch mode uses a shared timestamp, and rejected inputs fail whole rather than partially.

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 the core action and scope, and every clause carries information. It is dense and run-on with heavy em-dash nesting, which slightly reduces scannability, but there is little filler to cut.

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?

With no output schema, the description still covers both operating modes, rejection behavior, attribution semantics, and body-preservation guarantees — enough for an agent to invoke it correctly in either single-page or batch form.

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 the schema already documents all seven parameters; the description reinforces meaning and adds cross-parameter rules (slug/slugs mutual exclusivity, note and freshness_anchor being single-page only) plus the server-side verifier identity that is not a parameter at all.

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?

States a specific verb+resource ('Stamp a knowledge page as verified') with precise scope ('WITHOUT touching its body') and enumerates what it sets. It explicitly contrasts itself with the sibling knowledge_write, so an agent can distinguish it without opening either schema.

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?

Names the alternative explicitly ('use it (never knowledge_write) to record "claims still hold"') and states the selecting condition. It also gives when-not conditions: archived pages are rejected, and a batch with any unknown slug is rejected whole, with batch/single-page modes delineated.

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

knowledge_writeA
Destructive

Upsert a knowledge page by slug. Two classes: world/ (default) — facts true independent of us. Domain = "music/gear", "software/loom", etc. ours/ — Art-created artifacts, revised-in-place (breakbrain density model, homelab design, wake-chain spec, script templates). Domain starts with "ours/", e.g. "ours/art-ops". On an existing slug: body REPLACES by default (mode: "append" adds to it instead), title/domain follow the write, citations always appended with exact-duplicate dedup — safe to re-send. Epistemic gate (§E1): • conversation-only citations → provisional (both classes). • ours/ domain + any repo citation → internal (ours/ class artifact; repo = git path / commit / live-system probe). • any web/repo citation on a non-ours/ domain → sourced (world/ default). NOTE: repo citations on world-class pages (domain not starting with "ours/") are treated as sourced, not internal. A citation to github.com/someone-else/project is a world source. World filing test: knowledge must be true independent of Jonathan. For our own artifacts use ours/. Shared surface, not a scratchpad: knowledge is readable by other identities (e.g. Mark) and by Jonathan, not just you. Write pages as finished synthesis for that audience — no raw inner-monologue reasoning, no private-to-you deliberation, nothing that assumes only you will ever read it. A personal reflection or working-out-loud note belongs in remember, not here.

NameRequiredDescriptionDefault
bodyYesSynthesized markdown body for the entity or artifact page (max 64 KB)
modeNoBody combine mode when the slug already exists: "replace" (default) overwrites the stored body; "append" adds this body after the existing one. Citations are appended (deduped) in both modes. Ignored when creating a new page.
slugNoEntity key for upsert — stable URL-safe identifier. Derived from title if omitted.
titleYesPage title — the entity name (e.g. "Mutable Instruments Rings") or artifact name (e.g. "breakbrain density model")
domainYesDomain tag. World class: "music/eurorack", "programming/typescript". Ours class: prefix with "ours/" — e.g. "ours/art-ops", "ours/breakbrain", "ours/homelab". Hierarchical string; sub-domains queryable via prefix filter.
versionNoours/ class: artifact version or revision tag (e.g. "v2", "2026-08-31", "t-81"). Preserved across upserts when omitted.
citationsYesSupport citations. At least one required. All-conversation → provisional. ours/ domain + repo → internal. Any web or repo on non-ours/ → sourced.
created_byNoours/ class: who created or last owned this artifact (e.g. "art", "jonathan"). Preserved across upserts when omitted; defaults to the calling identity for ours/ pages. On the knowledge-only service this must equal your own identity — you cannot attribute a write to a different identity than the one your bearer token resolved to.
freshness_anchorNoThe version/date the page's claims are valid as-of — e.g. "Syntakt OS 1.21" for a device, "as of 2026-05" for a topic, or "t-81 / 2026-08-31" for an ours/ artifact. Drives the verification engine: a page is re-verified when this anchor moves or the freshness SLA elapses.

TDQS

A4.5/5.0
Behavior4/5

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

Annotations declare destructiveHint=true and idempotentHint=false; the description corroborates destruction ("body REPLACES by default") and adds non-annotation behavior: citation dedup, the epistemic gate, and the shared-readership constraint. The phrase "safe to re-send" sits in mild tension with idempotentHint=false, though in context it is scoped to citation dedup rather than the whole write, so this is a clarity wart rather than a contradiction.

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 the core action and structured into class labels and a gated bullet list, so it scans well. It loses a point for redundancy: the repo-on-world-page rule is stated in the §E1 bullets, in the NOTE, and again in the citations/source_kind schema descriptions.

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?

For a 9-parameter, high-complexity mutation tool with no output schema, the description covers the class model, the epistemic gate, and audience expectations thoroughly. It is silent on what a successful upsert returns and on any auth/attribution failure modes (beyond the created_by note), which is the main remaining gap.

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 the baseline is 3, but the description contributes real semantics beyond the schema: the relationship between domain class and citation classification (the §E1 gate), the world-filing test for `domain`, and the intended audience for `body`. Only `version`, `created_by`, and `freshness_anchor` get no additional description-level treatment.

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?

Opens with a specific verb+resource ("Upsert a knowledge page by slug") and immediately splits the resource into its two classes with concrete domain examples. An agent can distinguish this from knowledge_supersede, knowledge_move, knowledge_merge, and remember without opening any schema.

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?

Gives explicit routing rules: world/ vs ours/ with a stated filing test ("knowledge must be true independent of Jonathan"), plus a named alternative for a whole class of inputs ("A personal reflection or working-out-loud note belongs in `remember`, not here"). That is when-to-use, when-not, and the alternative, all spelled out.

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

memory_archiveA
Idempotent

Soft-retire a memory: move it to the archive tier with a tombstone instead of deleting it. Archived memories are excluded from recall, list, audit, and find_similar but remain fully recoverable via memory_restore. Use this instead of forget when the memory may need to be recovered or audited later.

NameRequiredDescriptionDefault
refNoMemory reference for single archive
noteNoTombstone note: why this memory is being retired
titleNoTitle of specific memory to archive
categoryNoCategory (used with title)

TDQS

A4.7/5.0
Behavior5/5

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

Beyond the annotations (which only declare idempotent, non-destructive, closed-world), the description discloses downstream side effects the agent could not otherwise infer: archived memories are excluded from recall, list, audit, and find_similar, and remain fully recoverable. This is exactly the kind of behavioral context that annotations cannot express.

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, zero filler, and the core mechanism (tombstone, not delete) is front-loaded ahead of the routing advice. Every clause earns its place.

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 mutation tool with no output schema, the description covers what the operation does, what it excludes, how to reverse it, and when to prefer it over forget. Combined with the annotations covering safety semantics, nothing material is missing.

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 description coverage is 100% with 4 well-documented parameters, so the schema carries the burden and a baseline of 3 applies. The description's mention of the 'tombstone' loosely gestures at the note parameter but adds no syntax, format, or interaction detail beyond 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 names a specific verb and resource ('soft-retire a memory'), and immediately clarifies the mechanism ('move it to the archive tier with a tombstone instead of deleting it'). This distinguishes it from forget, memory_prune, and memory_restore without the agent needing to open any other schema.

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?

It gives an explicit alternative and the condition selecting it: 'Use this instead of forget when the memory may need to be recovered or audited later.' It also names the inverse operation (memory_restore) for un-doing the action.

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

memory_auditA
Read-only

One-shot health report for the memory store: totals, category breakdown, stale memories (untouched beyond threshold), near-duplicate pairs (above similarity threshold), and expired refs. Read-only — pair with forget/update to act on findings.

NameRequiredDescriptionDefault
stale_daysNoStale threshold in days (default 30)
max_duplicatesNoCap on duplicate pairs returned (default 20)
similarity_thresholdNoCosine floor for duplicate pairs, 0..1 (default 0.85)

TDQS

A3.8/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=true and openWorldHint=false, and the description's 'Read-only' merely restates that. It does add that the report is 'one-shot' (single call, no follow-up pagination implied) and discloses the finding categories, which is mild extra context, but says nothing about cost, scanning scope, or that thresholds change what is reported.

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, zero filler. The report content is front-loaded and the follow-up pointer is placed after, so an agent gets the essential information first.

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?

There is no output schema, and the description compensates well by enumerating the five sections the report returns, so an agent knows what to expect. Safety is covered by annotations and all three parameters are documented. Only the absence of any hint about scan cost or result size on large stores keeps it short of 5.

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 description coverage is 100%, with each parameter's meaning, bounds, and default documented in the schema itself. The description references thresholds conceptually ('untouched beyond threshold', 'above similarity threshold') but adds no syntax or units beyond what the schema provides, so the baseline 3 applies.

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 a specific verb+resource ('One-shot health report for the memory store') and enumerates exactly what the report contains: totals, category breakdown, stale memories, near-duplicate pairs, and expired refs. This clearly separates it from siblings like memory_list (raw listing) and find_similar (single-purpose duplicate search).

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?

It points to the follow-up action path ('pair with forget/update to act on findings'), which is genuinely useful routing, but never says when to run this audit versus memory_list, find_similar, or memory_prune, and gives no exclusions. Usage is implied rather than specified.

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

memory_historyA
Read-only

Body-revision history for a memory. update() snapshots the displaced body into memory_revisions before overwriting it — this tool is the read surface. Two modes: ref alone lists snapshots (metadata only — id, op, replaced_at, char count); ref + revision_id reads one snapshot's full content. To put a snapshot back, use memory_revision_restore.

NameRequiredDescriptionDefault
refYesRef of the memory (category/title slug).
revision_idNoRevision to read (from the listing). Omit to list all revisions.

TDQS

A4.9/5.0
Behavior5/5

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

Annotations already declare readOnlyHint=true, but the description adds substantial context: how revisions are created (update() snapshots the displaced body before overwriting), and critically that the return shape is mode-dependent — metadata only for listing vs full content for a single read. This is behavioral detail the annotations cannot convey.

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?

Four tight sentences, front-loaded with the core purpose and then the mechanism, modes, and routing. No filler; each clause carries information (how data arrives, two modes, the alternative tool).

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?

With no output schema, the description carries the return-value burden and does so: listing returns metadata (id, op, replaced_at, char count) and single-read returns full content. Combined with the mode rules and the restore pointer, an agent has everything needed to call it 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%, so both parameters are already documented (baseline 3). The description adds real semantic value by mapping parameter combinations to behavior: 'ref alone' vs 'ref + revision_id' determine listing vs single-snapshot read, and it clarifies what the listing returns. It stops just short of adding syntax/format detail beyond 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?

States a specific verb+resource ('Body-revision history for a memory') and immediately clarifies it is the read surface of a write/read pair with update(). It distinguishes itself from memory_revision_restore by name, so an agent can tell the read from the restore tool without opening either schema.

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 describes the two invocation modes (ref alone lists, ref+revision_id reads one) and names the correct alternative for restoring ('use memory_revision_restore'). This covers both when to use this tool and when to route elsewhere.

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

memory_listA
Read-only

Browse memories without semantic search. Lists memories with optional category/project filters. Useful for auditing, maintenance, and discovery.

NameRequiredDescriptionDefault
limitNoMaximum results (default: 50)
projectNoFilter to a specific project
categoryNoFilter to a specific category

TDQS

A3.5/5.0
Behavior3/5

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

readOnlyHint=true and openWorldHint=false already establish the safe, local read profile, and the description is consistent with that. It adds the useful behavioral note that this is a browse/enumeration path rather than a retrieval-ranked path, but says nothing about ordering, pagination, or return shape.

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?

Three compact sentences with the key differentiator (non-semantic browsing) front-loaded, followed by filters and use cases. No filler, though the final use-case sentence is the weakest.

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?

For a simple, annotated, zero-required-parameter read tool with a fully documented schema and no output schema, the description covers purpose, filters, and usage adequately. Return ordering and pagination behavior are the only notable omissions.

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 all three parameters (limit, project, category) are documented in the schema itself. The description only echoes category/project filtering and adds no syntax, matching, or defaulting detail beyond what the schema already provides.

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?

Clear verb+resource ('Lists memories') with an explicit scope qualifier ('without semantic search') and the filter dimensions it supports. It distinguishes itself from the semantic-search siblings by mode, though it never names recall or find_similar directly.

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?

'Useful for auditing, maintenance, and discovery' gives implied usage contexts, and 'without semantic search' hints the alternative is a semantic tool. But it never says when NOT to use it (e.g., versus memory_audit or recall), leaving the agent to infer the routing.

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

memory_mergeA
Destructive

Consolidate 2+ memories into one canonical row. Acts on a memory_audit duplicate finding: pick the survivor (target_ref) and fold the rest (source_refs) into it. Sources are archived with a tombstone and a supersession pointer to the target (same mechanism as memory_archive/supersede, N:1 instead of 1:1); the target's times_seen sums in each source's count. Unlike forget/archive on a duplicate pair, this consolidates both sides into one row instead of just discarding one.

NameRequiredDescriptionDefault
noteNoOptional note about this merge, stored in supersession tombstones on the losers
target_refYesRef of the canonical memory that survives the merge (must already exist, active)
source_refsYesRefs of the losing memories to fold into the target (all must be active)
hard_delete_losersNoHard-delete losers after archiving/superseding them (default false).
append_loser_bodiesNoAppend loser bodies to the target content under section markers (default false). Off by default — review loser bodies (returned in the result) before deciding.

TDQS

A4.7/5.0
Behavior5/5

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

Annotations already flag destructiveHint=true, and the description adds substantial detail beyond them: losers are archived with a tombstone plus a supersession pointer, the target's times_seen absorbs each source's count, and hard_delete_losers defaults to false. It also warns that append_loser_bodies is off by default so the agent can review returned loser bodies first — exactly the pre-destruction context an agent needs.

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?

Four sentences, all load-bearing, with the core action front-loaded before the mechanism, the alternative comparison, and the parameter caveats. No filler.

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?

No output schema exists, and the description covers the gap by noting loser bodies are returned in the result for review. Combined with the mechanism explanation and destructive-operation semantics, an agent has everything needed to invoke it safely.

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 description coverage is 100%, so the schema already documents every parameter including defaults, so the baseline is 3. The description reinforces the survivor/loser roles of target_ref and source_refs and the times_seen merging behavior, but adds no syntax or format detail the schema lacks.

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?

States a specific verb and resource ('Consolidate 2+ memories into one canonical row') and explicitly distinguishes itself from siblings memory_archive/supersede (N:1 instead of 1:1) and forget/archive on a duplicate pair. An agent can route to it without opening any schema.

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?

Names the trigger context ('Acts on a memory_audit duplicate finding') and the alternatives it supersedes ('Unlike forget/archive on a duplicate pair, this consolidates both sides into one row instead of just discarding one'). When-to-use and when-not-to-use are both explicit.

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

memory_proposalsA
Read-only

List all pending proposals in the capture-propose queue, newest first. These are DRAFTS awaiting ratification — they are not part of memory and do not appear in recall, memory_list, find_similar, or the boot digest. Ratify one with memory_ratify or discard it with memory_reject.

NameRequiredDescriptionDefault

No parameters

TDQS

A4.6/5.0
Behavior4/5

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

Annotations already declare readOnlyHint=true and openWorldHint=false, so the safety profile is covered. The description adds meaningful state context beyond that: results are drafts, are newest-first, and are explicitly excluded from recall/memory_list/find_similar/boot digest. It stops short of return format or pagination details, keeping it at 4.

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?

Three short sentences with zero waste; the core purpose and ordering are front-loaded, followed by scope exclusions and next-step actions. Every sentence carries information.

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?

For a zero-parameter read tool with no output schema, the description covers purpose, ordering, lifecycle state, and routing to memory_ratify/memory_reject. The only gap is the shape/fields of a returned proposal, which the absence of an output schema leaves unspecified.

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 tool takes zero parameters, so the baseline is 4 per the rubric. There is nothing for the description to disambiguate and it introduces no misleading parameter assumptions.

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?

States a specific verb (List), resource (pending proposals in the capture-propose queue), and scope (newest first). It also positively distinguishes itself from sibling read tools by declaring these drafts do not appear in recall, memory_list, find_similar, or the boot digest.

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 frames these as DRAFTS awaiting ratification and names the two follow-up alternatives with their conditions ('Ratify one with memory_ratify or discard it with memory_reject'), plus the exclusions from other listing tools. An agent knows exactly when this tool applies and what to do next.

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

memory_proposeA

Stage a DRAFT memory in the capture-propose queue for later ratification. A proposal is NOT an authored memory: it is invisible to recall, memory_list, find_similar, and the boot digest until it is ratified via memory_ratify. Use this when a background lane wants to suggest a write without committing it — the human (or Art) reviews and ratifies before it becomes canon. Drafts may be rough; validation runs at ratify time.

NameRequiredDescriptionDefault
ttlNoTime-to-live: "7d", "30d", "24h", "permanent", or omit
titleYesShort title for the proposed memory
sourceNoWhere this proposal came from, e.g. a lane name
contentYesThe proposed memory content
projectNoAssociated project, if any
categoryYesMemory category: user (about the human), project (about work), self (capability/learning), feedback (corrections/confirmations), reference (external pointers), pursuit (active goal or ongoing creative thread), episode (short-term cross-body tape: where you were / what was said or decided / what shipped / what is open — 48h TTL by default, set metadata.where to your surface e.g. "discord:#general", "voice", "wake:<id>", "lane:tending", "terminal")
metadataNoArbitrary key-value metadata

TDQS

A4.6/5.0
Behavior5/5

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

Annotations only cover the safety profile (non-read-only, non-destructive, closed-world). The description adds the critical behavioral fact that the draft is invisible to recall, memory_list, find_similar and the boot digest until ratified, and that validation is deferred to ratify time so drafts may be rough. That is exactly the context an agent cannot infer from annotations.

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?

Three sentences, front-loaded with the core action, then the invisibility constraint, then the when-to-use rule. No filler and every clause carries distinct information.

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?

Covers the full propose→ratify lifecycle, visibility semantics, and validation timing for a 7-parameter write tool with no output schema. It stops short of describing what staging returns (e.g. a proposal id) or the default retention of a draft, which would round it out.

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 description coverage is 100% (including the detailed category enum and ttl format), so the schema carries the parameter burden. The description adds only an indirect hint about content validation timing and nothing about ttl, source, project, or metadata semantics; baseline 3 applies.

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?

States a specific verb (stage) and resource (draft memory in the capture-propose queue) plus the downstream lifecycle step (ratification). The contrast with memory_ratify and with an 'authored memory' makes it distinguishable from siblings like remember and memory_proposals without opening a schema.

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 names the triggering scenario ('a background lane wants to suggest a write without committing it') and the gating condition (human/Art reviews and ratifies before it becomes canon). It also routes away from the direct-write path by stating a proposal is NOT an authored memory.

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

memory_pruneA
DestructiveIdempotent

Remove expired memories (TTL elapsed). Use dry_run to preview without deleting.

NameRequiredDescriptionDefault
dry_runNoPreview only — show what would be pruned without deleting (default: false)
stale_daysNoDays since last access to consider a memory stale (default: 30)

TDQS

A3.8/5.0
Behavior4/5

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

Annotations already declare destructiveHint=true and idempotentHint=true, so safety profile is covered. The description adds genuine context beyond that: the deletion criterion (TTL elapsed, i.e. expired memories only, not arbitrary ones) and the dry_run preview path. Missing detail on what happens to already-pruned or non-expired memories.

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 tight sentences with no waste; the destructive action and its scope lead, followed by the safe-preview escape hatch. Every clause earns its place.

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?

For a destructive mutation tool with full annotation coverage and 100% schema documentation, the description supplies the essential scope and preview guidance. It lacks only edge-case behavior (what counts as expired, what happens if nothing matches), which keeps it short of a 5.

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 both parameters are fully documented in the schema, establishing baseline 3. The description only echoes dry_run and says nothing about stale_days, so it adds no meaning beyond the schema.

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?

States a specific verb (Remove) and resource (memories) with a clear qualifying scope (TTL elapsed / expired). This distinguishes it from siblings like forget and memory_archive, though it doesn't name those alternatives explicitly.

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?

Provides the dry_run preview guidance, which is useful operational advice, but gives no 'when to use this vs. forget/memory_archive' routing. Usage context is implied by the TTL scope rather than stated.

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

memory_ratifyA
Idempotent

Ratify a pending proposal into a REAL memory. Loads the proposal, applies any optional overrides (your edits on accept), and commits it through the same validated write path as remember — so an invalid proposal is refused with its typed reason and stays pending. On success the memory becomes recallable and the proposal is removed from the queue. This is the gate: no proposal becomes canon without it.

NameRequiredDescriptionDefault
idYesProposal id (from memory_proposals)
ttlNoOverride the proposed TTL on accept
titleNoOverride the proposed title on accept
contentNoOverride the proposed content on accept
projectNoOverride the proposed project on accept
categoryNoOverride the proposed category on accept

TDQS

A4.4/5.0
Behavior5/5

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

Beyond the annotations (which already declare mutation, idempotency, and non-destructiveness), the description discloses the failure mode ('refused with its typed reason and stays pending') and success side effects ('memory becomes recallable and the proposal is removed from the queue'). This is rich behavioral context an agent needs to reason about outcomes.

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 the core action and the override behavior follows logically. Four sentences with one rhetorical line ('This is the gate') that earns modest emphasis but could be trimmed without loss.

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 mutation tool whose annotations already carry the safety profile and which has no output schema, the description covers the essential lifecycle: load, override, validate, commit, failure handling, and queue effects. Nothing an agent needs to invoke it correctly is missing.

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 description coverage is 100%, so the schema already documents every parameter including the override fields. The description adds a collective framing ('applies any optional overrides (your edits on accept)') but no new per-parameter syntax or constraints, so the baseline 3 is appropriate.

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?

States a specific verb and resource: 'Ratify a pending proposal into a REAL memory', and names the pipeline relationship to remember. An agent can distinguish this acceptance action from siblings like memory_propose and memory_reject without opening any schema.

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 gives clear context ('This is the gate: no proposal becomes canon without it') and implies this is the accept step for a pending proposal. It does not explicitly name the alternative rejection path (memory_reject) or state when-not to use it, so it falls short of exhaustive routing.

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

memory_rejectA
DestructiveIdempotent

Discard a pending proposal without committing it. Deletes the staging row; no memory is written. Use this for drafts that should not become canon.

NameRequiredDescriptionDefault
idYesProposal id (from memory_proposals)

TDQS

A4.2/5.0
Behavior4/5

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

Annotations already declare destructiveHint=true and idempotentHint=true, but the description adds the important detail of what exactly is destroyed (the staging row) and what is not affected (no memory is written). It omits idempotency behavior on repeat rejection, keeping it short of a 5.

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?

Three tight sentences with zero filler; the core action and its non-commitment guarantee are front-loaded before the usage hint.

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?

For a one-param destructive tool with no output schema, the description covers action, effect on storage, and selection guidance. It lacks only error/permission behavior (e.g., rejecting a non-pending id), which is a minor gap.

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?

Single parameter with 100% schema description coverage ('Proposal id (from memory_proposals)'), so the schema already carries the semantics. The description adds no syntax or sourcing detail beyond that, matching the baseline for full 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?

States a specific verb and resource ('Discard a pending proposal') and immediately scopes the effect ('Deletes the staging row; no memory is written'). An agent can distinguish this from memory_propose/memory_ratify purely on the 'without committing it' framing.

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?

'Use this for drafts that should not become canon' gives a clear selection condition for when to reject rather than ratify. It stops short of naming memory_ratify (or memory_prune/forget) as the explicit alternative, so the routing is implied rather than stated.

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

memory_restoreA
Idempotent

Restore a previously archived memory to the active set. Clears the archive flag and tombstone note. The memory becomes visible to recall, list, audit, and find_similar again.

NameRequiredDescriptionDefault
refNoMemory reference to restore
titleNoTitle of the archived memory to restore
categoryNoCategory (used with title)

TDQS

A3.8/5.0
Behavior4/5

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

Annotations already declare mutation (readOnlyHint=false), idempotency, and non-destructiveness, so the bar is lower. The description still adds real value by naming the concrete state changes ('clears the archive flag and tombstone note') and the downstream effects (visible to recall, list, audit, find_similar), which the annotations do not convey.

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?

Three short sentences, front-loaded with the action and scope, then the mechanism, then the effect. No filler and nothing repeated from the name or annotations.

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?

No output schema exists, so the description carries the return-value burden, and it does describe the resulting state reasonably well. It stops short of covering failure modes (e.g. restoring an already-active or nonexistent memory) or which identifier combination is required, leaving minor gaps for a mutation 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?

Schema description coverage is 100%, so all three parameters (ref, title, category) are already documented in the schema. The description adds no information about how ref relates to title/category or which identifier form to prefer, so the baseline 3 is appropriate.

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 states a specific verb and resource ('Restore a previously archived memory to the active set'), which is unambiguous about what the tool does. It implicitly pairs with memory_archive but never explicitly distinguishes itself from memory_revision_restore, knowledge_restore, or person_restore, so an agent must infer which restore variant applies.

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?

Usage is only implied by the phrase 'previously archived memory' – the agent can infer this applies to archived items, but there is no explicit when-to-use, no prerequisites, and no routing between this and the other restore tools (memory_revision_restore, knowledge_restore, person_restore) in the sibling set.

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

memory_revision_restoreA
Destructive

Restore a snapshotted memory body back onto the memory. Snapshots the current body first, so restore is never destructive. Use memory_history to list revision IDs before calling this.

NameRequiredDescriptionDefault
refYesRef of the memory (category/title slug).
revision_idYesId of the revision to restore (from memory_history listing).

TDQS

A3.8/5.0
Behavior3/5

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

The description discloses a genuinely useful behavioral trait beyond the annotations: the current body is snapshotted first, making the restore recoverable. However, 'restore is never destructive' sits in tension with destructiveHint=true — the annotation warns the agent of a state-changing overwrite while the prose reassures it away, which could lull an agent into treating the call as harmless.

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, zero waste: purpose and reversibility first, prerequisite second. Every clause earns its place and nothing is buried.

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?

For a two-parameter tool with full schema coverage and no output schema, the description covers purpose, reversibility, and the required upstream lookup. Only minor gaps remain, such as what happens to prior snapshots over time or whether the restore invalidates the revision, which an agent could reasonably want to know.

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 description coverage is 100% and both parameters are documented there, including the note that revision_id comes from the memory_history listing. The description restates that source but adds no format, validation, or edge-case detail (e.g., behavior when revision_id is stale), so the baseline 3 is appropriate.

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 states a specific verb and resource ('Restore a snapshotted memory body back onto the memory') and scopes it to a revision snapshot, which separates it from the archive-oriented sibling memory_restore. It stops short of naming that sibling or stating the distinction explicitly, so an agent must infer it from wording alone.

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?

It gives an explicit prerequisite and routes the agent to a named alternative ('Use memory_history to list revision IDs before calling this'), which is exactly the kind of directional guidance that aids tool selection. There is no stated when-not-to-use case (e.g., when memory_restore or memory_merge is preferable), so it falls short of a 5.

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

personA
Read-only

Read one person card: {found, rendered, card, archived, updated, synthesized_at}. A missing card is {found: false}, not an error. where fields carry a freshness marker: [ok], [unverified], or [STALE d] — never trust a stale one without re-checking.

NameRequiredDescriptionDefault
slugYesPerson slug: lowercase [a-z0-9-], e.g. "patrick-kells".
include_archivedNoReturn an archived card in full (default false).

TDQS

A3.7/5.0
Behavior4/5

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

Annotations only declare readOnlyHint and openWorldHint=false; the description adds real behavioral context: the exact return envelope, that a missing card is a non-error {found: false}, and the freshness marker vocabulary ([ok], [unverified], [STALE <n>d]) with a warning not to trust stale data. That is substantial disclosure beyond what the annotations provide.

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 the verb and resource, then tight sentences on the return shape and the missing-card case. Efficient overall, though the phrase 'where fields carry a freshness marker' is awkwardly worded and briefly obscures which fields it refers to.

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?

With no output schema, the description must describe the return, and it does: it lists the response keys, explains the not-found case, and defines the freshness markers. It is close to complete for a single-read tool, missing only sibling routing.

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 description coverage is 100%, with both 'slug' (with format example) and 'include_archived' fully documented in the schema. The description adds nothing about either parameter, so the baseline 3 is correct.

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?

States a specific verb and resource ('Read one person card') and enumerates the returned fields, so the agent knows this fetches a single entity rather than a list. It never names person_list as the alternative, so the distinction from its closest sibling must be inferred from the word 'one'.

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?

Usage is implied rather than stated: the tool is for retrieving a single card, and the note that a missing card returns {found: false} rather than an error tells the agent how to interpret a miss. There is no explicit when-not-to-use guidance or routing to person_list, person_history, or person_verify.

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

person_archiveA

Soft-retire a person card with a tombstone (who, when, why). An archived card is left out of identity's room block and person_list, and rejects writes until person_restore.

NameRequiredDescriptionDefault
slugYesPerson slug: lowercase [a-z0-9-], e.g. "patrick-kells".
reasonYesWhy the card is being retired, ≤ 200 chars.

TDQS

A4.2/5.0
Behavior5/5

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

Adds substantial behavior beyond the annotations: it is a soft retire (not a hard delete), it writes a tombstone capturing who/when/why, the card drops out of identity's room block and person_list, and it rejects writes until restored. This is exactly the reversibility/scope context the readOnlyHint=false / destructiveHint=false annotations leave open, and it is consistent with them.

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 with zero filler; the core action is front-loaded and the consequences follow. Every clause carries information.

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?

No output schema, and the description adequately covers what the operation does to the card and how to reverse it. It does not describe any confirmation or response behavior, but for a reversible mutation whose safety profile is already carried by annotations, nothing essential is missing.

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 description coverage is 100%, so both "slug" and "reason" are already documented. The description's "who, when, why" framing loosely reinforces the reason parameter but adds no syntax or format detail beyond the schema. Baseline 3 applies.

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?

States a specific verb and resource ("soft-retire a person card with a tombstone") and distinguishes itself from the sibling reverse operation by naming person_restore. An agent can tell it apart from person_restore, person_write, and forget without inspecting schemas.

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 reversibility path ("until person_restore") is mentioned, implicitly routing to a sibling, but there is no explicit when-to-use/when-not guidance versus alternatives like person_prune or forget. Usage is implied rather than stated.

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

person_historyA
Read-only

Revision history of a person card, newest first: id, op, replaced_at. Every stored change snapshots the previous card; the newest 10 are kept. Use person_revision_restore to put one back.

NameRequiredDescriptionDefault
slugYesPerson slug: lowercase [a-z0-9-], e.g. "patrick-kells".

TDQS

A4.3/5.0
Behavior4/5

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

Annotations already declare readOnlyHint=true and openWorldHint=false, so safety is covered. The description adds real behavioral context beyond that: every change snapshots the previous card and only the newest 10 revisions are retained, which tells the agent about the retention window and what data is exposed.

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 tightly packed sentences with zero filler. The purpose and ordering are front-loaded, followed by behavior and the handoff to the sibling tool; every clause earns its place.

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 read-only listing tool with one fully documented parameter, the description covers purpose, ordering, returned fields, retention limit, and the restore path. No output schema exists, and none is needed since the fields are enumerated inline.

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?

Single parameter with 100% schema description coverage; the slug format is fully documented in the schema. The description adds no parameter-level detail, so the baseline of 3 applies.

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?

States a specific verb+resource: 'Revision history of a person card', with ordering ('newest first') and the exact fields returned (id, op, replaced_at). It is clearly distinguishable from siblings like person_revision_restore and person.

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 routes to the alternative: 'Use person_revision_restore to put one back,' naming the sibling and the condition that selects it. No explicit when-not and no prerequisites stated, so it falls short of a full 5.

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

person_listA
Read-only

List person cards with slug, name, archived, updated, synthesized_at, stale and unverified field counts, and memories_since_synthesis (tagged user memories newer than the summary — how the consolidation lane finds summaries that have fallen behind).

NameRequiredDescriptionDefault
include_archivedNoInclude archived cards (default false).

TDQS

A3.7/5.0
Behavior4/5

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

Annotations already cover the safety profile (readOnlyHint=true, openWorldHint=false), so the bar is lower. With no output schema, the description earns credit by disclosing the return shape (slug, name, archived, updated, synthesized_at, stale/unverified counts, memories_since_synthesis) and explaining the derived semantics of the last field.

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?

One front-loaded sentence that starts with the verb and resource; nothing is wasted. The trailing parenthetical is dense and slightly tangled, which costs it the top score.

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?

For a read-only list tool with one optional flag and no output schema, the field enumeration plus the memories_since_synthesis explanation covers the main gap an agent would otherwise face. Ordering is the only notable omission, and it is minor.

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 description coverage is 100% and the single optional parameter include_archived is fully documented in the schema ('default false'). The description adds nothing about it, which is the expected baseline when the schema does the heavy lifting.

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?

States a specific verb and resource ('List person cards') and enumerates the returned fields, so the agent knows exactly what this produces. It does not, however, distinguish itself from adjacent siblings like person or person_history, leaving that routing to inference.

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?

There is no explicit when-to-use or when-not-to-use statement and no named alternative, but the parenthetical about memories_since_synthesis implies a real workflow ('how the consolidation lane finds summaries that have fallen behind'). That is implied usage rather than real guidance.

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

person_restoreA

Reactivate an archived person card, fields intact.

NameRequiredDescriptionDefault
slugYesPerson slug: lowercase [a-z0-9-], e.g. "patrick-kells".

TDQS

A3.6/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=false, destructiveHint=false, and openWorldHint=false, so the safety profile is covered. The phrase 'fields intact' adds useful context that field values are preserved rather than reset, but nothing is said about error behavior for already-active cards or permission requirements.

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?

A single front-loaded sentence with the action, target state, and preservation guarantee — no filler.

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?

For a one-parameter, non-destructive mutation with no output schema and full annotation coverage, the description supplies everything essential. Minor gaps (idempotency, failure modes) are not strictly needed here.

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% with a single, well-documented slug parameter including format and example, so the schema does the heavy lifting. The description adds no parameter-level detail beyond what the schema already provides, matching the baseline 3.

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?

Names a specific verb (reactivate) and resource (archived person card), making it clearly the inverse of person_archive and distinguishable from person_revision_restore (a different kind of restore). It stops short of explicitly naming those siblings, but 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?

Usage is strongly implied: call this when an archived person card must be brought back. However, it never states preconditions (e.g., card must currently be archived) or disambiguates from person_revision_restore, which also restores person-related state.

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

person_revision_restoreA
Destructive

Put a person card back to a revision from person_history (card and its synthesized_at). Snapshots the current card first, so it is never destructive. Archive state is unchanged.

NameRequiredDescriptionDefault
slugYesPerson slug: lowercase [a-z0-9-], e.g. "patrick-kells".
revision_idYesRevision id from person_history.

TDQS

A3.6/5.0
Behavior3/5

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

The description adds real context beyond the annotations: it snapshots the current card before overwriting and restores the card plus its synthesized_at, and archive state is untouched. However, the claim 'it is never destructive' sits in tension with the declared destructiveHint=true; it is defensible only because the snapshot makes the prior state recoverable, and the description does plainly state that the card is written.

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?

Three short sentences, zero filler, and the action is front-loaded before the safety mechanism and the scope boundary. Every clause (revision source, snapshot, archive invariance) carries information an agent needs.

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?

For a two-parameter mutation tool with full schema coverage and no output schema, the description covers purpose, the safety mechanism, and a scope boundary. It stops short of addressing failure modes (unknown or mismatched revision_id) or the return payload, so it is strong but not exhaustive.

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 slug format and revision_id's origin in person_history are already documented in the schema. The description reinforces the revision provenance but adds no new syntax, constraints, or edge cases (e.g. what a revision_id from a different person does). Baseline 3 applies when the schema carries the parameter documentation.

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 uses a specific verb and resource: it puts a person card back to a revision, explicitly sourcing that revision from the sibling tool person_history. It also carves out scope against a near-neighbour by stating 'Archive state is unchanged', which separates it from person_restore, though it never names that sibling directly.

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?

Usage is only implied: the agent can infer this is for reverting a card to a prior version, and the archive-state clause hints at a boundary condition. There is no explicit 'use this when / use X instead' routing against person_restore or person_write, so the agent must infer the selection rule.

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

person_verifyA

Stamp where fields on a person card as checked: sets verified_at (default now) and, if passed, source. Values are not changed. All-or-nothing: an unknown field rejects the call. A failed check is recorded by not stamping.

NameRequiredDescriptionDefault
slugYesPerson slug: lowercase [a-z0-9-], e.g. "patrick-kells".
fieldsYeswhere field names to stamp.
sourceNoWhat you checked against, e.g. "pond /api/tadpoles".
verified_atNoISO-8601 UTC; default now; not in the future.

TDQS

A3.7/5.0
Behavior4/5

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

Adds real behavioral context beyond the annotations: values are not changed (so it is a metadata-only mutation despite readOnlyHint=false), the operation is all-or-nothing with unknown fields rejecting the call, and a failed check is recorded by simply not stamping. It does not cover idempotency on repeat stamps or permission requirements.

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?

Three tight sentences, front-loaded with the core action and with zero filler. The opening phrasing 'Stamp where fields on a person card as checked' is grammatically awkward but still compact.

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?

For a mutation tool with no output schema, it discloses the mutation scope, atomicity/error behavior, and the negative case (failure = no stamp). Missing only repeat-call idempotency and permission context, which keeps it short of a 5.

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 description coverage is 100%, so the baseline is 3. The description adds the verified_at default of now and the optional nature of source, but says nothing about slug semantics or the meaning of 'where field names' beyond the schema.

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?

States a specific verb and resource: stamp 'where fields on a person card' as checked, setting verified_at and source. It is clearly distinct from value-mutating siblings like person_write, though it never names the closest analog knowledge_verify to disambiguate.

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?

Usage is implied (call it after a field has been checked) but the description never states when to prefer this over person_write or knowledge_verify/person_write alternatives, nor any prerequisites. Adequate but with a clear routing gap.

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

person_writeA

Write a person card — the condensed current state of what you know about one human (not a knowledge page, not the memories: those stay the evidence). merge (default true) merges where/how one level deep (a field passed as null is removed), and replaces name, summary and may when passed; merge: false makes the card exactly what was passed. Passing summary says "I re-read the evidence and this is still right" and moves synthesized_at. Reserved keys (tier, field, projects, scope, trust) are rejected: gates stay in the harness. Worker bodies must not call this — cards are written by Art.

NameRequiredDescriptionDefault
howNoHow to work with them: field -> value (e.g. tz, mode, loop_in). null removes a field.
mayNoWhat they were said to be allowed to do, each with its source. Descriptive, not a grant. Replaces the whole list.
nameNoDisplay name (required on create and on merge: false), ≤ 80 chars.
slugYesPerson slug: lowercase [a-z0-9-], e.g. "patrick-kells".
mergeNoDefault true. false: the card becomes exactly what was passed.
whereNoWhere the person is in each system: field -> {value, verified_at?, source?, stale_after_days?}. null removes a field (merge writes only).
summaryNoShort synthesized summary, ≤ 1,200 chars.

TDQS

A4.5/5.0
Behavior5/5

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

Annotations only carry the safety profile (readOnlyHint=false, destructiveHint=false, openWorldHint=false). The description goes well beyond that, disclosing merge depth ('one level deep'), that a null field is removed, that merge:false overwrites the card wholesale, that passing summary has the side effect of moving synthesized_at, and that reserved keys are rejected. That is exactly the extra behavioural context annotations don't provide.

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-loads the core identity of a person card, then layers merge semantics, then side effects and restrictions. It is a single dense passage rather than clearly delimited points, which makes it slightly harder to scan, but essentially no sentence is wasted.

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?

For a 7-parameter mutation tool with nested objects and no output schema, the description covers identity, merge behaviour, replacement semantics, side effects and access restrictions. The one gap is that, with no output schema present, it never says what a successful write returns.

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 the schema already carries the baseline. The description nevertheless adds real meaning — merge's default and one-level merge semantics, null-as-delete for nested fields, and what passing summary signifies ('I re-read the evidence and this is still right'). It adds value on top of structured data rather than restating it.

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?

States a specific verb+resource ('Write a person card') and immediately scopes it against near neighbours by defining what a card is not — not a knowledge page, not the memories. An agent can distinguish it from knowledge_write and remember without opening the schema.

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?

Gives concrete when-not guidance ('not a knowledge page, not the memories: those stay the evidence') and an explicit audience restriction ('Worker bodies must not call this — cards are written by Art'). It stops short of naming the alternative tools to use instead, so routing is implied rather than spelled out.

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

recallA

Retrieve memories relevant to a query or topic. Returns matching memories from the persistent store. Use this when you need context from past sessions. Results are re-ranked for diversity (MMR, λ=0.7 by default) so near-duplicate memories on a well-covered topic don't crowd out different ones; the top result is always the most relevant. Pass diversity: 0 for pure relevance order.

NameRequiredDescriptionDefault
limitNoMaximum results to return (default: 10)
queryYesWhat to search for — topic, keyword, or question
projectNoScope to a specific project — pass the project you are currently working in. Enforces scope discipline (t-337): memories tagged to a different project are excluded unless their effective scope is global (user/reference by default, or anything written with scope: "global"). Omit to search without project scoping.
categoryNoFilter to a specific memory category, or omit for all
diversityNoMMR diversity 0..1 (default 0.3 = 1−λ). 0 reproduces the plain relevance ranking; higher trades relevance for coverage of distinct memories.

TDQS

A3.7/5.0
Behavior4/5

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

The description adds substantial behavioral context beyond the annotations: MMR re-ranking with a default λ=0.7, the guarantee that the top result is the most relevant, and the effect of diversity: 0. However, it never addresses the readOnlyHint=false signal — a retrieval tool that apparently mutates state (e.g., access tracking) without saying so — which is a real, if non-contradictory, gap.

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 the core purpose, then usage, then ranking behavior. Well-sized overall, though the first two sentences are slightly redundant ('Retrieve memories...' / 'Returns matching memories from the persistent store').

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?

For a 5-parameter retrieval tool with no output schema, the description reasonably covers purpose, usage trigger, and notable ranking behavior. The main omission is the state effect implied by readOnlyHint=false; the return shape is only loosely described.

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 description coverage is 100%, so the baseline is 3 and the schema already documents limit, query, project, category, and diversity. The description reinforces diversity semantics (MMR/λ) and the guaranteed-top-result behavior, but adds little parameter meaning that the schema does not already carry.

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?

States a specific verb + resource ('Retrieve memories relevant to a query or topic') and clarifies the source ('persistent store'). The purpose is unambiguous, but it offers no differentiation from closely related siblings such as find_similar, memory_list, or knowledge_recall, which an agent must disambiguate on its own.

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?

'Use this when you need context from past sessions' gives a genuine when-to-use, but there are no when-not cases and no explicit alternatives, despite a crowded sibling space (find_similar, memory_list, episodes, knowledge_recall). An agent is left to infer which retrieval tool applies.

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

rememberA

Store an episodic memory that persists across sessions. Use this when you learn something important about the user, a project, or yourself that should be available in future sessions.

NameRequiredDescriptionDefault
ttlNoTime-to-live: "7d", "30d", "24h", "permanent", or omit for no expiration.
scopeNoOverride this memory's recall visibility. Omit to take the category default: "user" and "reference" default global, everything else defaults to project-scoped when a project is set (global when it isn't — nothing to scope against). Set this explicitly to "global" for a fact learned in one project that actually applies everywhere — a security, git, or tool-workflow practice, not a language/framework/file-layout/code-style/error-handling convention (those stay project-scoped).
titleYesShort title for the memory
contentYesThe memory content — what you learned, observed, or were told
projectNoAssociated project, if any (omit for global memories)
categoryYesMemory category: user (about the human), project (about work), self (capability/learning), feedback (corrections/confirmations), reference (external pointers), pursuit (active goal or ongoing creative thread), episode (short-term cross-body tape: where you were / what was said or decided / what shipped / what is open — 48h TTL by default, set metadata.where to your surface e.g. "discord:#general", "voice", "wake:<id>", "lane:tending", "terminal")
metadataNoArbitrary key-value metadata
sourcingNoProvenance/trust tier — how this memory was produced. "observed": directly witnessed (measured, tested, read from source). "relayed": learned from another person/body (conversation, letter, episode). "inferred": AI-generated reasoning/synthesis — treat with skepticism, not ground truth. "system": auto-written by the harness (episode fallback, lane output). Shown in recall results and the boot digest so readers calibrate confidence.
provenanceNoFree-form origin: surface, body, session, or person. E.g. "wake:w-74fccc 2026-09-07", "Jonathan, Discord #loom", "lane:letters". For episodes, prefer metadata.where (already conventional); provenance carries detail.

TDQS

A3.7/5.0
Behavior3/5

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

Annotations already declare write (readOnlyHint=false) but non-destructive, non-open-world behavior, so the safety profile is covered. The description adds one genuine behavioral fact — persistence across sessions — but says nothing about deduplication, whether the write is immediately recallable, or how it interacts with the propose/ratify flow.

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, both load-bearing: the first defines the operation and its durability, the second routes the agent to the moment of use. Nothing is repeated from the schema or annotations.

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

Completeness3/5

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

For a nine-parameter tool with nested metadata, three enums and no output schema, the description covers purpose and timing but not the surrounding workflow — no note on duplicate handling, project vs global defaults at a high level, or what a subsequent recall will show. The schema fills most of the gap, so this is adequate rather than complete.

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 description coverage is 100% and the parameter docs are unusually rich (ttl formats, scope defaults, category semantics, sourcing trust tiers), so the description is not required to carry parameter meaning. It contributes no parameter guidance of its own, matching the baseline for fully documented schemas.

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?

States a specific verb and resource ('Store an episodic memory') plus the defining property of persistence across sessions, so the agent knows this is a durable write, not a read or ephemeral note. It does not differentiate itself from adjacent writers like memory_propose or knowledge_write, and calling a seven-category memory tool 'episodic' slightly undersells its scope.

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?

Gives an explicit trigger condition ('when you learn something important about the user, a project, or yourself that should be available in future sessions'), which is enough to recognize the right moment. It offers no exclusions or alternatives, so the agent gets no help choosing between this and memory_propose/knowledge_write.

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

updateA
Destructive

Update an existing memory. Find by ref (returned from remember) or by category+title. Can replace content, update metadata, or both.

NameRequiredDescriptionDefault
refNoMemory reference (category/filename) from remember
titleNoTitle of the memory to update (used with category)
contentNoNew content (replaces existing body)
categoryNoCategory to search in (used with title)
metadataNoMetadata fields to add or update
observationNoFeedback memories only: record a confirming or contradicting observation. "confirm" raises confidence (+0.05, capped at 0.9), "contradict" lowers it (-0.1, floored at 0.3); either way the evidence count goes up. Ignored on non-feedback memories. Confidence decays toward neutral the longer it goes unconfirmed — see the feedback category description on remember.

TDQS

A3.7/5.0
Behavior3/5

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

Annotations already declare destructiveHint=true, readOnlyHint=false, and idempotentHint=false, so the safety profile is covered. The description adds that content replacement overwrites the existing body and that metadata/content are independently optional, but says nothing about failure when the target is not found or about partial-update behavior.

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 tight sentences with no filler; the core action is front-loaded and the addressing/update modes follow immediately. Nothing is repeated from the schema.

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?

For a 6-parameter but entirely optional update tool with full schema coverage and safety annotations, the description covers addressing and mutation scope adequately. It omits only edge-case behavior (not-found errors) and confirmation of what a successful update returns, which is minor given no output schema exists.

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, but the description adds genuine value by tying the parameters into an OR relation (ref vs category+title) and noting ref comes from remember — an inter-parameter relationship the schema only hints at individually.

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?

States a specific verb and resource ("Update an existing memory") and clarifies the two lookup paths (ref, or category+title) plus the three update modes (content, metadata, or both). It does not explicitly distinguish itself from siblings like remember or memory_merge, but the resource and scope 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 Guidelines3/5

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

Usage is implied through the two addressing modes, but there is no explicit when-to-use versus alternatives (remember to create, memory_merge to combine, memory_propose to stage changes). An agent must infer the boundary from the sibling list.

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

update_identityA
Destructive

Update your self-model or preferences with section-level precision. Targets H2 sections in identity files. Call without section/content to list available sections. IDENTITY.md (the creed) is immutable — only self-model and preferences can be edited.

NameRequiredDescriptionDefault
fileYesWhich identity file to update: "self-model" or "preferences"
modeNo"replace" updates an existing section (default), "append" adds a new section
contentNoNew content for the section (replaces everything under the H2 header)
sectionNoH2 section name to target. Omit to list all sections.

TDQS

A4.1/5.0
Behavior4/5

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

Annotations already declare destructiveHint=true and readOnlyHint=false, so the mutation risk is signposted. The description adds non-obvious behavior beyond that: a dual list/update mode triggered by omitting section/content, and an immutability rule for IDENTITY.md that constrains where writes may land. It still doesn't spell out that replace destroys existing section content or any permission requirements.

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?

Three tight sentences, each carrying distinct information (purpose/granularity, list mode, immutability constraint), with the core purpose front-loaded and no filler.

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?

For a destructive write tool with destructiveHint already declared and no output schema, the description covers scope, targeting granularity, list mode, and the immutability boundary. It leaves minor gaps around failure behavior and permissions, but an agent has enough to invoke it 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%, so the baseline is 3. The description adds cross-parameter semantics the schema documents only per-field: omitting both `section` and `content` switches the tool into a listing mode, and it clarifies the file scope relative to the immutable IDENTITY.md.

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 names a specific verb and resource (update self-model/preferences) plus the granularity of the edit (H2 sections in identity files), which is far more precise than the sibling `update`. It does not explicitly name a sibling tool to contrast with, so it falls short of a 5.

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?

It gives an explicit operational condition ("Call without section/content to list available sections") and an explicit exclusion ("IDENTITY.md ... is immutable — only self-model and preferences can be edited"). No alternative sibling tool is named, but the when-to-use and when-not-to-use guidance is concrete.

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.

  1. 43 tool updatesv0.5.1
    • Changedbootstrap1 field changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
    • Changeddossier1 field changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
    • Changedepisodes1 field changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
    • Changedfind_similar1 field changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
    • Changedforget1 field changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
    • Changedharness_describe1 field changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
    • Changedharness_init1 field changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
    • Changedidentity2 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedInput schema / properties / people
        Added value: +{
        +  "description": "Slugs of the people this turn is addressed by (the room), e.g. [\"patrick-kells\"]. Adds an \"# In the room\" block with their person cards. Omit for no block.",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
    • Changedknowledge_archive1 field changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
    • Changedknowledge_history1 field changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
    • Changedknowledge_maintain1 field changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
    • Changedknowledge_merge1 field changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
    • Changedknowledge_move1 field changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
    • Changedknowledge_purge1 field changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
    • Changedknowledge_recall1 field changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
    • Changedknowledge_restore1 field changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
    • Changedknowledge_supersede1 field changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
    • Changedknowledge_verify3 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedInput schema / properties / citation_checked
        Added value: +{
        +  "description": "Did you actually check the page's citations against their sources (not just the body text)? Defaults to false.",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / outcome
        Added value: +{
        +  "description": "What this verification found. Defaults to \"confirmed\" (the claims still hold). \"stale\" flags it as out of date without fixing it — recorded in the audit trail but verified_at is NOT advanced, so the page stays at the front of the stale-first queue; \"corrected\" means you fixed it (pair with a knowledge_write, or the note field, describing the fix).",
        +  "enum": [
        +    "confirmed",
        +    "stale",
        +    "corrected"
        +  ],
        +  "type": "string"
        +}
    • Changedknowledge_write4 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • changedInput schema / properties / citations / description
        Previous value: -"Support citations. At least one required. All-conversation → provisional. Any repo → internal (ours/). Any web → sourced."New value: +"Support citations. At least one required. All-conversation → provisional. ours/ domain + repo → internal. Any web or repo on non-ours/ → sourced."
      • changedInput schema / properties / citations / items / properties / source_kind / description
        Previous value: -"web = external URL; loom_memory = opaque memory ref; conversation = session distillation; repo = git repo path / commit / live-system probe (ours/ class)"New value: +"web = external URL; loom_memory = opaque memory ref; conversation = session distillation; repo = git repo path / commit / live-system probe (signals internal only when domain is ours/; on world-class pages, treated as sourced)"
      • changedInput schema / properties / created_by / description
        Previous value: -"ours/ class: who created or last owned this artifact (e.g. \"art\", \"jonathan\"). Preserved across upserts when omitted."New value: +"ours/ class: who created or last owned this artifact (e.g. \"art\", \"jonathan\"). Preserved across upserts when omitted; defaults to the calling identity for ours/ pages. On the knowledge-only service this must equal your own identity — you cannot attribute a write to a different identity than the one your bearer token resolved to."
    • Changedmemory_archive1 field changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
    • Changedmemory_audit1 field changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
    • Addedmemory_history
    • Changedmemory_list1 field changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
    • Addedmemory_merge
    • Changedmemory_proposals1 field changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
    • Changedmemory_propose1 field changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
    • Changedmemory_prune1 field changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
    • Changedmemory_ratify1 field changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
    • Changedmemory_reject1 field changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
    • Changedmemory_restore1 field changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
    • Addedmemory_revision_restore
    • Addedperson
    • Addedperson_archive
    • Addedperson_history
    • Addedperson_list
    • Addedperson_restore
    • Addedperson_revision_restore
    • Addedperson_verify
    • Addedperson_write
    • Changedrecall2 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • changedInput schema / properties / project / description
        Previous value: -"Filter to a specific project"New value: +"Scope to a specific project — pass the project you are currently working in. Enforces scope discipline (t-337): memories tagged to a different project are excluded unless their effective scope is global (user/reference by default, or anything written with scope: \"global\"). Omit to search without project scoping."
    • Changedremember4 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedInput schema / properties / provenance
        Added value: +{
        +  "description": "Free-form origin: surface, body, session, or person. E.g. \"wake:w-74fccc 2026-09-07\", \"Jonathan, Discord #loom\", \"lane:letters\". For episodes, prefer metadata.where (already conventional); provenance carries detail.",
        +  "type": "string"
        +}
      • addedInput schema / properties / scope
        Added value: +{
        +  "description": "Override this memory's recall visibility. Omit to take the category default: \"user\" and \"reference\" default global, everything else defaults to project-scoped when a project is set (global when it isn't — nothing to scope against). Set this explicitly to \"global\" for a fact learned in one project that actually applies everywhere — a security, git, or tool-workflow practice, not a language/framework/file-layout/code-style/error-handling convention (those stay project-scoped).",
        +  "enum": [
        +    "project",
        +    "global"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / sourcing
        Added value: +{
        +  "description": "Provenance/trust tier — how this memory was produced. \"observed\": directly witnessed (measured, tested, read from source). \"relayed\": learned from another person/body (conversation, letter, episode). \"inferred\": AI-generated reasoning/synthesis — treat with skepticism, not ground truth. \"system\": auto-written by the harness (episode fallback, lane output). Shown in recall results and the boot digest so readers calibrate confidence.",
        +  "enum": [
        +    "observed",
        +    "relayed",
        +    "inferred",
        +    "system"
        +  ],
        +  "type": "string"
        +}
    • Changedupdate2 fields changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
      • addedInput schema / properties / observation
        Added value: +{
        +  "description": "Feedback memories only: record a confirming or contradicting observation. \"confirm\" raises confidence (+0.05, capped at 0.9), \"contradict\" lowers it (-0.1, floored at 0.3); either way the evidence count goes up. Ignored on non-feedback memories. Confidence decays toward neutral the longer it goes unconfirmed — see the feedback category description on remember.",
        +  "enum": [
        +    "confirm",
        +    "contradict"
        +  ],
        +  "type": "string"
        +}
    • Changedupdate_identity1 field changed
      • changedInput schema / $schema
        Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
  2. 8 tool updatesv0.5.0
    • Changedbootstrap3 fields changed
      • changedInput schema / properties / purpose / description
        Previous value: -"What this agent exists to do — its reason for being"New value: +"What this agent exists to do — its reason for being, one line"
      • addedInput schema / properties / user
        Added value: +{
        +  "description": "The human this agent works with — their name, not the agent's",
        +  "type": "string"
        +}
      • changedInput schema / properties / voice / description
        Previous value: -"Communication style and personality"New value: +"Communication style and personality, one line"
    • Addedepisodes
    • Changedharness_init1 field changed
      • addedInput schema / properties / target
        Added value: +{
        +  "description": "Path to the dotfile to inject the managed loom block into (e.g. an absolute path to CLAUDE.md / AGENTS.md / GEMINI.md). When omitted only the harness manifest is scaffolded.",
        +  "type": "string"
        +}
    • Changedknowledge_write11 fields changed
      • changedInput schema / properties / body / description
        Previous value: -"Synthesized markdown body for the entity page (max 64 KB)"New value: +"Synthesized markdown body for the entity or artifact page (max 64 KB)"
      • changedInput schema / properties / citations / description
        Previous value: -"Support citations. At least one required. All-conversation support → page stored provisional."New value: +"Support citations. At least one required. All-conversation → provisional. Any repo → internal (ours/). Any web → sourced."
      • changedInput schema / properties / citations / items / properties / excerpt / description
        Previous value: -"Inline supporting quote — link-rot insurance (max 4 KB)"New value: +"Inline supporting quote or repo excerpt — link-rot insurance (max 4 KB)"
      • changedInput schema / properties / citations / items / properties / source_kind / description
        Previous value: -"web = external URL; loom_memory = opaque memory ref; conversation = session distillation"New value: +"web = external URL; loom_memory = opaque memory ref; conversation = session distillation; repo = git repo path / commit / live-system probe (ours/ class)"
      • changedInput schema / properties / citations / items / properties / source_kind / enum
        Previous value: -[
        -  "web",
        -  "loom_memory",
        -  "conversation"
        -]New value: +[
        +  "web",
        +  "loom_memory",
        +  "conversation",
        +  "repo"
        +]
      • changedInput schema / properties / citations / items / properties / source_locator / description
        Previous value: -"URL, memory ref, or session ID"New value: +"URL, memory ref, session ID, or repo path + commit hash"
      • addedInput schema / properties / created_by
        Added value: +{
        +  "description": "ours/ class: who created or last owned this artifact (e.g. \"art\", \"jonathan\"). Preserved across upserts when omitted.",
        +  "type": "string"
        +}
      • changedInput schema / properties / domain / description
        Previous value: -"Domain tag, e.g. \"music/eurorack\", \"programming/typescript\". Hierarchical string; sub-domains queryable via prefix filter."New value: +"Domain tag. World class: \"music/eurorack\", \"programming/typescript\". Ours class: prefix with \"ours/\" — e.g. \"ours/art-ops\", \"ours/breakbrain\", \"ours/homelab\". Hierarchical string; sub-domains queryable via prefix filter."
      • changedInput schema / properties / freshness_anchor / description
        Previous value: -"The version/date the page's claims are valid as-of — e.g. \"Syntakt OS 1.21\" for a device, or \"as of 2026-05\" for a topic. Drives the verification engine: a page is re-verified when this anchor moves or the freshness SLA elapses."New value: +"The version/date the page's claims are valid as-of — e.g. \"Syntakt OS 1.21\" for a device, \"as of 2026-05\" for a topic, or \"t-81 / 2026-08-31\" for an ours/ artifact. Drives the verification engine: a page is re-verified when this anchor moves or the freshness SLA elapses."
      • changedInput schema / properties / title / description
        Previous value: -"Page title — the entity name (e.g. \"Mutable Instruments Rings\")"New value: +"Page title — the entity name (e.g. \"Mutable Instruments Rings\") or artifact name (e.g. \"breakbrain density model\")"
      • addedInput schema / properties / version
        Added value: +{
        +  "description": "ours/ class: artifact version or revision tag (e.g. \"v2\", \"2026-08-31\", \"t-81\"). Preserved across upserts when omitted.",
        +  "type": "string"
        +}
    • Changedmemory_propose2 fields changed
      • changedInput schema / properties / category / description
        Previous value: -"Memory category: user (about the human), project (about work), self (capability/learning), feedback (corrections/confirmations), reference (external pointers), pursuit (active goal or ongoing creative thread)"New value: +"Memory category: user (about the human), project (about work), self (capability/learning), feedback (corrections/confirmations), reference (external pointers), pursuit (active goal or ongoing creative thread), episode (short-term cross-body tape: where you were / what was said or decided / what shipped / what is open — 48h TTL by default, set metadata.where to your surface e.g. \"discord:#general\", \"voice\", \"wake:<id>\", \"lane:tending\", \"terminal\")"
      • changedInput schema / properties / category / enum
        Previous value: -[
        -  "user",
        -  "project",
        -  "self",
        -  "feedback",
        -  "reference",
        -  "pursuit"
        -]New value: +[
        +  "user",
        +  "project",
        +  "self",
        +  "feedback",
        +  "reference",
        +  "pursuit",
        +  "episode"
        +]
    • Changedmemory_ratify1 field changed
      • changedInput schema / properties / category / enum
        Previous value: -[
        -  "user",
        -  "project",
        -  "self",
        -  "feedback",
        -  "reference",
        -  "pursuit"
        -]New value: +[
        +  "user",
        +  "project",
        +  "self",
        +  "feedback",
        +  "reference",
        +  "pursuit",
        +  "episode"
        +]
    • Changedrecall1 field changed
      • addedInput schema / properties / diversity
        Added value: +{
        +  "description": "MMR diversity 0..1 (default 0.3 = 1−λ). 0 reproduces the plain relevance ranking; higher trades relevance for coverage of distinct memories.",
        +  "maximum": 1,
        +  "minimum": 0,
        +  "type": "number"
        +}
    • Changedremember2 fields changed
      • changedInput schema / properties / category / description
        Previous value: -"Memory category: user (about the human), project (about work), self (capability/learning), feedback (corrections/confirmations), reference (external pointers), pursuit (active goal or ongoing creative thread)"New value: +"Memory category: user (about the human), project (about work), self (capability/learning), feedback (corrections/confirmations), reference (external pointers), pursuit (active goal or ongoing creative thread), episode (short-term cross-body tape: where you were / what was said or decided / what shipped / what is open — 48h TTL by default, set metadata.where to your surface e.g. \"discord:#general\", \"voice\", \"wake:<id>\", \"lane:tending\", \"terminal\")"
      • changedInput schema / properties / category / enum
        Previous value: -[
        -  "user",
        -  "project",
        -  "self",
        -  "feedback",
        -  "reference",
        -  "pursuit"
        -]New value: +[
        +  "user",
        +  "project",
        +  "self",
        +  "feedback",
        +  "reference",
        +  "pursuit",
        +  "episode"
        +]
  3. 31 tool updatesv0.4.1
    • First observedbootstrap
    • First observeddossier
    • First observedfind_similar
    • First observedforget
    • First observedharness_describe
    • First observedharness_init
    • First observedidentity
    • First observedknowledge_archive
    • First observedknowledge_history
    • First observedknowledge_maintain
    • First observedknowledge_merge
    • First observedknowledge_move
    • First observedknowledge_purge
    • First observedknowledge_recall
    • First observedknowledge_restore
    • First observedknowledge_supersede
    • First observedknowledge_verify
    • First observedknowledge_write
    • First observedmemory_archive
    • First observedmemory_audit
    • First observedmemory_list
    • First observedmemory_proposals
    • First observedmemory_propose
    • First observedmemory_prune
    • First observedmemory_ratify
    • First observedmemory_reject
    • First observedmemory_restore
    • First observedrecall
    • First observedremember
    • First observedupdate
    • First observedupdate_identity

TDQS

A3.6/5.0

Scored across 43 tools

Disambiguation3/5

The tool set groups cleanly into memory, knowledge, person, identity, and harness domains, and descriptions draw clear lines between similar operations. However, 43 tools create many near-pairs (archive/restore/merge/history across three resources, plus unprefixed verbs like update/forget/recall), so an agent must read descriptions carefully to avoid misselection. Overlap exists but is largely mitigated by documentation.

Naming Consistency3/5

Most tools use snake_case with a domain prefix (memory_*, knowledge_*, person_*, harness_*), which is predictable. But core memory operations break the pattern with bare verbs/nouns (remember, recall, update, forget, identity, episodes, dossier, bootstrap), and some related tools differ in structure (update vs update_identity). Mixed conventions but still readable.

Tool Count2/5

43 tools is far above the typical 3–15 range and exceeds the 25-tool threshold for 'too many' in the rubric. While the server covers a broad multi-domain scope (memory, knowledge, person, identity, harness), bundling all of them into one surface increases selection cost. Some lifecycle tools could be consolidated or split into separate servers.

Completeness4/5

The surface covers full lifecycle operations for memories, knowledge pages, person cards, identity, and harness scaffolding, including create/read/update/archive/restore/history/merge/verify. Minor gaps exist, such as no explicit harness list/remove or global cross-domain search, but core workflows have no dead ends. Overall a very complete but heavyweight tool set.

Maintenance

ActivityActive
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables AI agents to maintain persistent memory across sessions by capturing conversations, extracting durable knowledge, and injecting relevant context, supporting various MCP-compatible platforms.
    12
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Provides persistent, cloud-based memory for AI agents, letting them remember preferences, skills, and decisions across sessions via an MCP-compatible interface.
    Apache 2.0
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables AI agents to maintain a persistent identity and structured memory—including reasoning patterns, episodic history, and knowledge—while exposing procedures for managing that memory over MCP.
    Apache 2.0
  • A
    license
    Not graded
    quality
    A
    maintenance
    Provides AI agents with persistent, human-like memory infrastructure via MCP, enabling them to store, search, summarize, and forget episodic, semantic, procedural, and working memories across sessions.
    618 npm
    MIT