Skip to main content
Glama
Pseudogiant-xr

PseudoLife-MCP

Official

Pseudolife-MCP

PyPI CI License: Apache-2.0 Python 3.10+

简体中文 · 日本語 · 한국어 · Português (BR) · Español

Persistent long-term memory for Claude Code, Codex, and other MCP clients.

An MCP server that gives coding agents a long-term memory that persists across sessions — surviving context compactions and fresh tasks. Your coding agent is the intelligence; this server is its memory on disk.

Cortex Console — Observatory view

What you get:

  • Associative memory with honest forgetting — a flat similarity store ranked by hybrid dense-plus-lexical retrieval, with conflict detection that admits potential updates while preserving earlier source notes; whole-note replacement is explicit. (The measured verdict: a preregistered ablation campaign found the previous 8-band continuum tied a flat store on every gate, so the simpler structure ships; the continuum remains one config line away.)

  • Canonical facts, not vibes — one current value per entity.attribute slot (or a member set, for slots that hold many concurrent values); corrections supersede rather than silently overwrite, and the full version history survives.

  • Dreams — a bundled local extractor, or any OpenAI-compatible endpoint (a Claude model on your Max plan, a GPT-5.6 model on a ChatGPT plan, LM Studio, Ollama, vLLM), consolidates the memory stream into facts and a knowledge graph while you're not looking.

  • Lessons from its own work — successes, dead-ends, and your corrections become do/avoid guidance surfaced at the start of every session.

  • A web console to watch it think — the Cortex Console above, plus cited world facts, session episodes, and document RAG.

Measured, with receipts — the full 500-question LongMemEval sweep, all six question types, and every number ships with its committed run artifact:

LongMemEval oracle, 500 questions

naive RAG

commit-gated cascade

accuracy, all six question types

0.688

0.690

context tokens per question

~1210

~883

knowledge-update slice (78 of the 500)

0.859

0.936 (retired — see below)

Equal accuracy to naive RAG across the whole benchmark on ~73% of the context, and better calibrated about what it does not know: on BEAM-100K's abstention questions the fact spine scores 0.950 against naive RAG's 0.775, unchanged under two independent judges. Read that as calibration, not recall — in the budget-matched five-arm run of 2026-09-02 (rag 0.725 there; one replicate, local judge) an arm served no memory at all scores 1.000 on the same questions, because refusing is the right answer there and an empty context always refuses. The fact spine loses where an answer has to be aggregated across sessions. The second claim to survive a judge swap is a win rather than a wash: re-run on 2026-09-04 with the hybrid arm budget-matched to the control at 6 turns, the same 500 questions give hybrid 0.730 against naive RAG's 0.690 under the local judge and 0.736 against 0.694 under claude-opus-5 — paired +0.040 / +0.042, p 0.015 / 0.013 — bought with more context, ~1229 tokens against the control's ~1124, not less, and carried mostly by temporal-reasoning questions. Graded by a local, byte-reproducible judge (the cross-judge check names its second judge) — compare within rows, never against GPT-judged leaderboards.

Retired 2026-08-25 (#188): the 0.936 knowledge-update headline. It was measured on the 2026-07-30 bench stack (Qwen3.6-27B answerer and judge). Re-running the same 78 questions after the 2026-08-17 migration to Qwen3.8-27B puts the cascade at 0.846, below the naive-RAG control — which lands on 0.859 on both stacks. The cascade serves the fact-spine answer unless that channel says "I don't know", so it measures the answerer's abstention behaviour as much as the memory: 32/78 abstentions at 46/46 commit precision on the old stack, 22/78 at 0.839 on the new one. The 500-question table above is on the older judge and has not been re-judged, so read its cascade row as an upper bound.

Full tables, the per-type breakdown, both stacks side by side, and every artifact: Benchmarks.

Quickstart

Install and register the lite tier. No Docker, no database to set up, no container runtime:

pip install "pseudolife-mcp[lite]"
claude mcp add --scope user pseudolife-memory -- pseudolife-mcp

Codex instead of Claude Code — same shape:

pip install "pseudolife-mcp[lite]"
codex mcp add pseudolife-memory --env PSEUDOLIFE_WRITER_ID=codex -- pseudolife-mcp

For Codex, finish setup before starting a fresh task. In the existing [mcp_servers.pseudolife-memory] table in ~/.codex/config.toml, add startup_timeout_sec = 240, tool_timeout_sec = 240, and required = true. The shim can wait up to 180 seconds for a cold daemon; Codex's default startup budget is 10 seconds. required makes missing memory visible at startup and waits for its initial catalog. These are starting budgets, not a promise that a first model download fits. The tool budget leaves time for the shim's 180-second deadline to report a failure before the host cancels it; prewarm with pseudolife-mcp serve in a terminal if needed.

The MCP handshake delivers compact recall/capture/reflection instructions. For the complete standing guidance, copy the bundled memory block into your project AGENTS.md or ~/.codex/AGENTS.md. For session briefings and per-turn reminders, follow Codex hooks and verification. Use one MCP registration and one hook source; an installed plugin may already provide either. After the daemon is running, execute pseudolife-mcp doctor from the same environment as the registered command. It checks the handshake and annotations without calling bank tools.

Then in either coding agent: "remember that my staging box is haze-02" → the agent calls memory_store; next session, "which box is staging?"memory_search finds it. Browse everything at the Cortex Console: http://127.0.0.1:8765/ui/.

The first session auto-starts the daemon, which provisions an embedded PostgreSQL 18 (pgvector included, via pg0-embedded) under a stable per-user data dir and downloads the embedding model (~1.2 GB, one-time). It is a real Postgres bank, not a cut-down one: pseudolife-mcp backup writes a standard owner-free pg_dump archive (plus a state archive, 7-day rotation) that restores into any PostgreSQL 18 target regardless of role — the Docker tier included — so outgrowing lite is a dump/restore, not a migration project (backups). For a tier- and Postgres-version-independent copy, pseudolife-mcp export / import move the whole bank as portable JSONL (logical export / import). Windows needs an ASCII-only data path (PSEUDOLIFE_MCP_DATA_DIR).

What lite gives you, and the one thing it doesn't

lite (pip)

durable (Docker)

Associative store, hybrid search, supersession, version history

yes

yes

Cortex facts, knowledge graph, lessons, world facts, episodes

yes

yes

Cortex Console, document RAG, pseudolife-mcp backup

yes

yes

Dream consolidation filling the cortex on its own

no extractor ships

yes — bundled local CPU sidecar

External volumes, health-checked services, deploy/rollback tooling

no

yes

The gap, stated plainly. Lite ships no extractor, so the dream pass still runs, prunes, and acknowledges its input batch, but writes no canonical facts: on this path memory_fact_set is the only cortex writer. Everything else above works. Nothing about this is silent — curl http://127.0.0.1:8765/health reports "extractor": "none", and the stdio shim says the same on stderr at session start.

Any OpenAI-compatible endpoint closes it. The daemon inherits the environment it starts from, so two variables are the whole fix — with a local Ollama:

export PSEUDOLIFE_DREAM_BASE_URL=http://localhost:11434/v1
export PSEUDOLIFE_DREAM_MODEL=qwen2.5:7b
pseudolife-mcp serve
$env:PSEUDOLIFE_DREAM_BASE_URL = "http://localhost:11434/v1"
$env:PSEUDOLIFE_DREAM_MODEL    = "qwen2.5:7b"
pseudolife-mcp serve

/health then reports "extractor": "configured". One gotcha: a daemon that is already running keeps the environment it started with, and the shim reattaches to it rather than spawning a new one — stop the old daemon first. A hosted endpoint works too, and costs you the zero-egress property: memory text leaves the machine. Extractor tiers, quality, and the trade-offs: Dreaming.

Related MCP server: agent-mem0

Everything above plus the bundled extractor, external volumes, health-checked services, and backup/rollback tooling. Requires Docker and at least one MCP-capable coding agent — Claude Code, Codex, and Gemini CLI are wired end-to-end; anything else gets paste-ready config (provider matrix). One command from clone to first memory:

git clone https://github.com/Pseudogiant-xr/Pseudolife-MCP.git
cd Pseudolife-MCP
ops/install.sh          # Linux / macOS
ops\install.ps1         # Windows (pwsh 7+)
# Codex: add --client codex / -Client codex
# Codex defaults to automatic hook-source detection and asks once for approval.
# Unattended hook approval: --codex-hook-trust yes / -CodexHookTrust yes
# Instructions only: --codex-hooks skip --instructions append
# PowerShell equivalent: -CodexHooks skip -Instructions append
# Both:  add --client both  / -Client both
# Gemini: add --client gemini — or several: --client claude,codex,gemini
# Other MCP agents (Cursor, Windsurf, Zed, ...): --client generic

The installer asks which agents to wire (multi-select, with a capability matrix showing exactly what each one gets — session briefing, per-turn discipline, standing file), runs the preflight (one exact fix line per missing prerequisite), then asks which dream extractor should consolidate memories —

  • sidecar — the bundled local CPU model; no Claude plan needed, works for everyone, and keeps every memory on the box (~11.8 GB image);

  • sonnet-only — the lightest install: a Claude model via a CLI shim (claude-opus-5 by default; the mode name is historical. Needs a logged-in Max-plan claude CLI); the sidecar image is never built or pulled (~11.8 GB lighter; dreams pause while the shim is down);

  • sonnet-fallback — the Claude shim primary, the bundled sidecar as automatic fallback (Max-plan CLI plus the ~11.8 GB image);

  • codex-only / codex-fallback — the same two shapes on an OpenAI subscription: a GPT-5.6 model (Sol / Terra / Luna) via the Codex CLI shim on a signed-in ChatGPT plan (extraction quality unmeasured — see the dreaming guide) —

then brings the stack up, installs the selected clients' session hooks (where the client has a hook system), registers the MCP transport (the stdio shim by default, with a per-provider writer id; direct HTTP via --transport http), and health-checks the daemon — finishing with a per-agent ladder of what got wired and what that agent's platform cannot support. Codex setup offers one choice to enable automatic memory briefings, reminders, and session cleanup, use standing instructions only, or skip. Automatic setup reuses an enabled PseudoLife plugin or installs the three lifecycle hooks, backs up configuration, approves only their exact current definitions, and verifies execution. If verification fails, the same approval allows the standing memory block as a fallback; setup reports the remaining repair step. Hook-less providers (Gemini CLI and generic agents) are offered the standing block. --instructions append always writes the block from examples/CLAUDE.memory.md into ~/.claude/CLAUDE.md / ~/.codex/AGENTS.md / ~/.gemini/GEMINI.md (useful for subagent visibility even with hooks). Idempotent — re-run any time; --extractor <mode> switches extractor setups. Non-interactive example: ops/install.sh --extractor sidecar --client codex --codex-hook-trust yes. Without explicit hook approval, unattended setup does not grant trust; use --codex-hooks skip --instructions append for instructions only. Explicit --instructions skip prevents fallback edits. Linux (Docker Engine): your user must be in the docker group — sudo usermod -aG docker $USER, then log out/in (the preflight checks this).

Image sizes, the Windows WSL2 memory cap, and what the installer automates: the containerized install below.

ops/preflight.sh --client codex    # or ops\preflight.ps1 -Client codex
docker volume create pseudolife-mcp-bank
docker volume create pseudolife-mcp-state
docker compose -f ops/docker-compose.yml up -d --build   # first build, once

# ...or pull the prebuilt images instead of building (releases >= 0.14.0):
docker compose -f ops/docker-compose.yml -f ops/docker-compose.ghcr.yml pull pseudolife-pg pseudolife-daemon
docker compose -f ops/docker-compose.yml -f ops/docker-compose.ghcr.yml up -d

# Verify, then wire the transport into one or both clients.
curl http://127.0.0.1:8765/health

# Stdio shim (the installer's default — per-session episode identity).
# PSEUDOLIFE_MCP_NO_SPAWN=1 makes the shim wait for the container instead
# of spawning a host fallback that can shadow the Docker bank after a
# reboot; set it on Docker-tier registrations like these.
pip install pseudolife-mcp
claude mcp add --scope user pseudolife-memory --env PSEUDOLIFE_MCP_NO_SPAWN=1 -- pseudolife-mcp
codex mcp add pseudolife-memory --env PSEUDOLIFE_MCP_NO_SPAWN=1 -- pseudolife-mcp

# ...or direct HTTP (no pip package needed; fine for single-session setups):
claude mcp add --transport http --scope user pseudolife-memory http://127.0.0.1:8765/mcp
codex mcp add pseudolife-memory --url http://127.0.0.1:8765/mcp

# Reinforce the protocol-level memory loop with a global standing instruction:
cat examples/CLAUDE.memory.md >> ~/.claude/CLAUDE.md
cat examples/CLAUDE.memory.md >> ~/.codex/AGENTS.md
# (PowerShell: Add-Content "$env:USERPROFILE\.claude\CLAUDE.md" (Get-Content examples\CLAUDE.memory.md -Raw))

Optional knobs live in ops/.env (cp ops/.env.example ops/.env — the install/update scripts scaffold it too; every value is commented, a missing file runs entirely on defaults).

What this is

A memory engine exposed over MCP. There's no chat UI and no LLM doing the thinking — your coding agent is the intelligence; these are tools it calls to store and recall what matters. (Models are bundled as plumbing: baked embedding weights for retrieval, and the optional CPU extractor sidecar that consolidates memories into facts while you sleep.)

Where it sits among the common approaches to agent memory — each column is a fair tool for what it's for; this table is about what question each one answers, not who's wrong:

notes file (CLAUDE.md)

auto-journaling plugin

plain vector store

Pseudolife-MCP

Survives sessions and compactions

yes

yes

yes

yes

"What is X now?" has one current answer

if you curate it

no — replays what happened

no — every stored version competes at recall

yes — slot-keyed cortex

A canonical-fact correction replaces the old value

you edit the file

appended beside it

old and new both retrievable, unranked by recency of truth

cortex supersedes, with full version history kept

Facts know their age and go stale

no

no

no

dated, freshness-decayed, quarantined when stale

Distils do/avoid lessons from its own outcomes

no

no

no

yes

Benchmark numbers ship with their raw run artifacts

typically no

typically no

every published number, test-enforced

Auto-journaling records what the agent did; Pseudolife curates what it learned. Both are useful — they answer different questions. Named alternatives — Mem0, Zep/Graphiti, Letta, Cognee, memU, Memori — and the cases where one of them is the better pick: Comparison.

It layers several complementary stores: the associative store (a flat embedding store ranked by cosine similarity fused with a BM25 lexical pool (on by default), with conflict-aware admission and explicit source-note replacement; an 8-tier banded layout is available as an opt-in preset); the cortex (slot-keyed canonical facts — one current value per entity.attribute, or a member set for set-valued slots — with provenance tiers and contender parking instead of silent overwrites); a typed knowledge graph over those facts with a closed relation vocabulary and on-read inference; the world cortex (durable cited facts about external reality, age-decayed trust); procedural lessons learned from the agent's own work; and a ChromaDB reference bank for document RAG. The canonical layers in depth: the memory model; the graph and multi-hop recall: retrieval.

State lives in Postgres (the durable source of truth) behind a single long-lived daemon; every session attaches through a thin stdio shim (installer default — per-session identity) or directly over HTTP (single-session setups). The result: Claude can pick up where it left off, correct itself when facts change, and reason over relationships — without you re-explaining context each session.

Documentation

This README is the front door — install, wiring, and the basic loop. The deep material lives in the user guide:

Page

What's in it

Configuration

Env vars, tuned defaults, toolset tiers, stdio shim, LAN sharing, data layout, backups, schema history

Providers

Capability matrix per coding agent, memory instruction layers, AGENTS.md standard, Codex hook setup and verification, writer ids

Retrieval

Reranker, BM25 hybrid, abstention floors, ranking-trace debugging, memory_recall, the knowledge graph

Dreaming

Extractor tiers, the bundled sidecar, upgrading the extractor, Sonnet-fallback, cadence, deep dream, consolidation

Episodes & sessions

Daemon-owned session episodes, the briefing hook, nested sub-episodes, tags

The memory model

Cortex slots, provenance contenders, world cortex, lessons, temporal/HLC stamps

Benchmarks

LongMemEval results; why extraction quality dominates

Comparison

Mem0, Zep/Graphiti, Letta, Cognee, memU, Memori — the axes, and when to use something else

Security posture

Memory poisoning (ASI06): every shipped mitigation, and what is not defended

Plus evals/README.md (full benchmark methodology) and CONTRIBUTING.

Tools exposed

The surface was consolidated 2026-07-02 (55 → 32 tools; now 37 with memory_toolset, the set-slot pair and coordination): lifecycle families became verb-dispatched tools (memory_dream, memory_forget, memory_graph_review), and dump/introspection views moved to the Cortex Console (REST) — the manifest is agent context every session, so it stays lean.

Tool

Purpose

memory_store(text, source?, tags?, origin?, episode?, authority?, distortion_tolerance?)

Remember one durable fact / decision / observation (canonical facts reach the cortex via the dream pass or memory_fact_set); authority/distortion_tolerance label the speech act and how exactly it must survive — auto (default) is a deterministic form heuristic, no model call, and both labels are inherited through supersession unless restated

memory_search(query, top_k?, filters..., rerank?, bm25?, explain?, verbose?)

Associative retrieval; canonical cortex facts surface ahead of recall hits, each dated (asserted_at / last_confirmed / human age, plus stale when it has rotted); explain=True attaches a ranking trace

memory_recent(n?, sources?, episodes?, tags?, verbose?)

Newest stores, timestamp-ordered (debug + session catch-up)

memory_supersede(old_text?, new_text, entry_id?)

Correct the selected entry by ID, or one unique exact-text match; ambiguous/missing targets fail closed. Keep the old entry as history; derived_flagged names canonical facts built on it (flagged, never rewritten)

memory_forget(scope, ...)

Forget from one store: memory (by text/substring/source/episode/tag) and fact hard-delete; world and lesson (by entity/attribute) retire the slot with an audit row — reversible via memory_graph_review(action="restore_slot")

memory_stats()

Store occupancy, hit rates, totals

memory_agents(action, project?, task?, status?)

Experimental, opt-in peer awareness or update of the caller's registered context; unknown episode scope stays unknown, and activity is not a resource reservation

memory_message(action, to?, text?, request_id?, reply_to?, after?, message_id?)

Experimental addressed mail: send, non-destructive receive, or explicit recipient ack; requires authenticated adapter binding, remains outside memory retrieval, and never grants user approval

memory_get(entry_id) / memory_reinforce(entry_id)

Dereference a memory id to its full episode (+ consolidated_into); reinforce it after finding it useful

memory_fact_get(entity, attribute)

The one CURRENT canonical value at a slot (+ parked contenders); on an empty slot returns ranked candidates (same-entity, then similar slots); aged/contested facts carry a ready-made correct_with call (as do memory_search / memory_world_search hits)

memory_fact_set(entity, attribute, value, origin?, confidence?, episode?, freshness_class?, authority?, distortion_tolerance?)

Assert a canonical fact deliberately (insert / confirm / supersede / contest); freshness_class (auto default) says how fast the slot rots — auto infers it from the entity's kind; authority/distortion_tolerance (auto = deterministic form heuristic, no model call) inherit the slot's labels unless restated

memory_fact_resolve(entity, attribute, accept)

Settle a contested slot — adopt (true) or discard (false) the contender

memory_set_add(entity, attribute, member) / memory_set_remove(entity, attribute, member)

Add/confirm or retract one member of a set-valued slot (many concurrent values, e.g. tags — not one NOW value); a scalar there converts to a set one-way on first memory_set_add, except a number-led aggregate scalar ("32", "$1,500"), which is protected — the add parks as a contender instead. Read with memory_fact_get, which returns {kind: "set", members, removed} for these slots

memory_history(entity, attribute?)

With attribute: version timeline at a slot, with writer/temporal stamps. Without: the entity's causal chain — dated fact/entry/edge/lesson events ("what led to X")

memory_world_set(entity, attribute, value, source_url?, ...)

Assert a cited WORLD fact (external knowledge; age-decayed trust by freshness class)

memory_world_search(query, top_k?, verbose?)

Search world facts — each carries effective_confidence, a stale flag, and its citation

memory_outcome(task, outcome, about?, detail?, polarity?, episode?, used_ids?)

Record a procedural outcome signal (success/failure/correction); the dream distils signals into lessons. used_ids names the search hits the work actually turned on — each credits every retrieval_events row in the session window that served it with a retrieval_uses label (used_via=outcome), the relevance signal a learned reranker trains on; same session, within use_window_seconds, or nothing is credited

memory_lesson_search(query, top_k?, verbose?)

Recall learned lessons for the task at hand — heed polarity - dead-ends; re_verify flags lessons whose subject facts changed since

memory_dream(action, limit?, commit_token?, apply?, snippets?, run_id?)

Drive the dream: status / pull / commit / run (server-side extractor) / runs (audit trail of recent passes) / rollback (revert the latest committed pass from its pre-image journal) / deep (full-corpus graph consolidation; dry-run unless apply, which snapshots the graph tables first; snippets=false omits candidate evidence; responses carry evidence-enriched merge_proposals for near-duplicate triage)

memory_graph_review(action, proposal_id?, proposal_ids?, proposals?, scope?, src?, dst?, relation?, store?)

Work the review queue: list / propose / relate (link a pair and dismiss its duplicate proposal in one call) / dismiss_pair / dismiss_slot_pair / restore_slot / accept_link / reject_link / accept_merge / accept_junk / reject_entity (merge/entity decisions are audit-stamped decided_by=agent over MCP, human via Console); proposal_ids settles many id-actions in one call; restore_slot undoes a memory_forget(scope="lesson"/"world") retirement — store + the retired `entity

memory_session_title(title, episode?)

Name THIS session's auto-opened episode (default titles are generic); episode is your session handle from the briefing — concurrent sessions share one HTTP connection, so pass it to land the rename on your own episode

memory_episode_start(title, hint?, episode?) / memory_episode_end(episode?)

Open/close a nested sub-episode for a substantial task; entries stored while open carry its id; episode is your session handle so the nest/pop lands in your own tree when several sessions run concurrently

memory_episode_summary(id)

Stats + tag/source distribution + recent entries within an episode

memory_consolidation_candidates(query?, episode?, ...)

Cluster near-duplicate memories ripe for consolidation

memory_consolidate(replaces?, new_text, source?, tags?, entry_ids?)

Replace selected entries with one canonical note; validate every ID (or unique exact text) before any changes

memory_graph_relate(src, relation, dst, ...)

Assert a typed edge (closed relation vocabulary; re-assertion bumps confidence)

memory_graph_unrelate(src, relation, dst)

Retract an edge (superseded, kept for audit)

memory_alias(entity, alias)

Bind an alternative name — lookups resolve aliases first

memory_graph(entity, depth?, include_facts?, to?, relation_filter?)

Entity neighborhood (≤3 hops) with derived transitive/inverse edges and per-edge EXTRACTED/INFERRED/AMBIGUOUS provenance tags; to returns the shortest path between two entities

memory_recall(query, hops?, top_k?, verbose?)

Multi-hop retrieval for relational questions; low_confidence: true → fall back to memory_search

memory_relation_define(name, description, ...)

Grow the closed relation vocabulary (deliberate, rare act)

document_ingest(path, source?)

Index a file (txt/md/pdf/html) verbatim in the reference bank — the lossless complement to agent-side distillation (division of labor)

document_search(query, top_k?)

RAG search over the reference bank only

memory_toolset(action)

Check or change this principal's visibility tier: status / expand / collapse

Each tool returns plain JSON. See pseudolife_memory/mcp_server.py for docstrings — those are what Claude reads to decide when to call which tool. The five recall-path tools return compact entries by default (result payloads are agent context on every retrieval); pass verbose=true for full metadata. Full-table dumps and topology views live in the Cortex Console (/api/*) and the pseudolife-mcp briefing CLI.

Toolset tiers. Three visibility tiers — minimal (9 tools), core (24), full (37) — filtered per principal at tools/list; a principal (the named bearer-token identity, or the writer id for single-token installs) steps its own tier up or down with memory_toolset before calling a hidden tool. Defaults, per-client mapping, and weak-model deployments: Configuration — toolset tiers.

Architecture

One memory daemon owns the bank and serves MCP over streamable HTTP at /mcp; every Claude Code session (and any LAN agent) attaches to it. Postgres 18 + pgvector (in Docker on the durable tier; the lite tier runs the same Postgres embedded, no container) is the durable source of truth — the in-memory store is a write-through cache hydrated at startup (a small weights.pt persists only counters — there are no MLP weights).

The daemon runs either containerized (recommended — portable, no host Python) or as a host process. Claude Code attaches through a thin torch-free stdio shim (the installer default — per-session identity, needed for concurrent sessions) or directly over HTTP (simpler for a single session):

Claude session A ─┐  stdio shim (installer default) or HTTP
Claude session B ─┼───────────────────► pseudolife-mcp daemon ─► Postgres (Docker)
LAN agent ────────┘  or stdio shim         (single writer)        pgvector
                     (per session)         host proc OR Docker

This kills two v0.1 hazards by construction: a single writer means concurrent sessions can't clobber each other, and entries are transactional so a crash can't wipe the bank. On top of the associative store sit the canonical layers — cortex, world facts, lessons, temporal/HLC stamps (the memory model) — joined to a typed knowledge graph walkable via memory_graph and multi-hop memory_recall (retrieval & the graph).

Install — containerized (any OS)

What the durable tier installer above does, by hand. The whole stack — Postgres and the memory daemon — runs in Docker. No host Python, no torch install, no version skew; the daemon image bakes in CPU-only torch and the embedding weights — Qwen/Qwen3-Embedding-0.6B (the default retrieval backbone since schema v25) plus all-MiniLM-L6-v2 (kept baked for the ONNX-parity test path) — so it runs identically on Windows / macOS / Linux. Requires only Docker; built once: ~5.0 GB daemon image (measured 2026-07-29 on the deployed build) + ~0.6 GB Postgres + ~11.8 GB extractor sidecar (measured 2026-08-20 with the v3 multi-task bake; skip the sidecar entirely with the installer's sonnet-only mode). The ~12.6 GB and ~10.4 GB figures published before 2026-07-29 are retired: both were inflated by a CUDA torch build that a dependency-resolution bug pulled into the image (see the CHANGELOG); the daemon has always been CPU-only.

git clone https://github.com/Pseudogiant-xr/Pseudolife-MCP.git
cd Pseudolife-MCP

# 1. One-time: create the two persistent volumes (bank + daemon state).
docker volume create pseudolife-mcp-bank
docker volume create pseudolife-mcp-state

# 2. Build + start all three services (Postgres, extractor, then the daemon).
docker compose -f ops/docker-compose.yml up -d --build

Or skip the ~5 GB daemon build entirely and pull the prebuilt images (releases ≥ 0.14.0):

docker compose -f ops/docker-compose.yml -f ops/docker-compose.ghcr.yml pull pseudolife-pg pseudolife-daemon
docker compose -f ops/docker-compose.yml -f ops/docker-compose.ghcr.yml up -d

The extractor sidecar is not published and still builds locally; updates on the pull path are pull + up -d, not ops/update.ps1.

Upgrading from a pre-rename install (volumes ops_pseudolife_pgdata / ops_pseudolife_data)? Don't rename those volumes — keep pointing at them by creating ops/.env with PSEUDOLIFE_BANK_VOLUME=ops_pseudolife_pgdata and PSEUDOLIFE_STATE_VOLUME=ops_pseudolife_data before up. See the compose header.

Windows: cap Docker Desktop's WSL2 VM, which otherwise claims up to ~50% of host RAM — how much the stack actually needs, the ops/wslconfig.example template, and the daemon container's own memory cap: Configuration — Windows / WSL2 memory.

The daemon serves MCP at http://127.0.0.1:8765/mcp and restarts with Docker — no logon task needed. First build downloads the model into the image (once); every container start after that is offline and fast. Wire Claude Code in via the stdio shim (installer default) or directly over HTTP (both below). Where the data actually lives, and how to back it up: Configuration — data layout.

Host-process install (Windows, for GPU / dev): run Postgres in Docker but the daemon on host Python — for hacking on the daemon or running the embedder on a local GPU. Steps, the pseudolife-mcp CLI modes, and the logon autostart task: Configuration — host-process install.

Updating

Lite tier: one command, bank untouched:

pip install -U "pseudolife-mcp[lite]"

Docker tier: after a git pull (or local code change), redeploy the daemon only — safely, without touching Postgres or the extractor:

.\ops\update.ps1        # Windows
./ops/update.sh         # Linux / macOS

It backs up the bank (pg_dump + a state-volume tar), tags a rollback image (when a previous one exists — it says so loudly when there isn't), rebuilds + recreates only the daemon, and waits for /health. It never runs down -v. (Host-process install: just restart the daemon — pip install -e . is editable.) Build cache is pruned automatically after every healthy deploy; see Docker disk retention for the weekly Scheduled Task and the manual .vhdx compact. Never run docker system prune --volumes, which deletes volumes.

Two upgrades are not automatic, because neither can be done safely in place. Both have a step-by-step runbook — backup, dry run, apply, verify, roll back — and a fresh install needs neither:

  • A bank older than 0.11.0 (schema v25): every embedding column moved from vector(384) to vector(1024), so the daemon refuses to start rather than half-migrate. Re-embed offline with ops/migrate_embeddings.pythe v25 migration runbook.

  • A Docker-tier bank created before 2026-08-14 (PostgreSQL 16 → 18): a Postgres major bump cannot reuse the old data volume. Run pwsh ops/migrate-pg18.ps1the PostgreSQL 18 migration runbook.

Wire into your coding agent

Plugin (hooks + commands). With the daemon running, two commands inside Claude Code wire the session hooks (briefing + episode identity), the memory-loop instructions, and the /dream + /memory-status commands:

/plugin marketplace add Pseudogiant-xr/Pseudolife-MCP
/plugin install pseudolife-memory@pseudolife-mcp

The plugin replaces the settings.json hook and the CLAUDE.md block below — the same standing instructions arrive as session context from the daemon. It deliberately does not bundle the MCP server: Claude Code loads a plugin server alongside any user-registered one with no deduplication, which doubled every session's tool namespace next to the installer's registration — so the transport is registered exactly once, by ops/install.* (stdio shim by default — per-session episode identity) or the one-liner below. Details, non-default ports/tokens, and migration: plugin/README.md.

Manual transport registration. The installer's default (shim mode) registers a thin stdio shim — one shim process per session, so every session carries its own tier-1 identity. The same wiring by hand:

pip install pseudolife-mcp    # daemon in Docker; add [lite] for the pip tier
claude mcp add --scope user pseudolife-memory --env PSEUDOLIFE_MCP_NO_SPAWN=1 -- pseudolife-mcp

PSEUDOLIFE_MCP_NO_SPAWN=1 belongs on Docker-tier registrations: the shim then waits for the container instead of spawning a host-side fallback whose port bind can race a still-booting Docker and shadow the real bank. On the [lite] pip tier drop the --env — there the spawn fallback is the zero-config path.

Direct HTTP works too — the daemon serves MCP over HTTP natively (no shim, no host command, nothing OS-specific; concurrent sessions then share one episode identity, so it fits single-session setups best):

claude mcp add --transport http --scope user pseudolife-memory http://127.0.0.1:8765/mcp

(--scope user registers it for every project; drop it to register for the current project only.) Or write the equivalent JSON yourself — into ~/.claude.json under the top-level mcpServers key for user scope, or into a .mcp.json at a project root for project scope:

{
  "mcpServers": {
    "pseudolife-memory": {
      "type": "http",
      "url": "http://127.0.0.1:8765/mcp"
    }
  }
}

For a token-protected daemon, add a headers key to that Claude JSON entry: "headers": { "Authorization": "Bearer <your-token>" }.

Codex — the installer's default (shim mode) wires the same stdio shim, so a Codex session gets its own tier-1 identity instead of inheriting a concurrent Claude session's episode:

pip install pseudolife-mcp
codex mcp add pseudolife-memory --env PSEUDOLIFE_MCP_NO_SPAWN=1 -- pseudolife-mcp

(Same Docker-tier note as the Claude wiring above: keep PSEUDOLIFE_MCP_NO_SPAWN=1 when the daemon runs in Docker; drop it on the [lite] pip tier.)

The HTTP one-liner works too (no pip package needed):

codex mcp add pseudolife-memory --url http://127.0.0.1:8765/mcp

Or add the equivalent user-level entry to ~/.codex/config.toml:

[mcp_servers.pseudolife-memory]
url = "http://127.0.0.1:8765/mcp"
bearer_token_env_var = "PSEUDOLIFE_MCP_TOKEN"

For that Codex HTTP configuration, export PSEUDOLIFE_MCP_TOKEN in the environment that launches Codex. The token stays out of config.toml, and Codex reads it when connecting. This is unnecessary for the default stdio shim.

Gemini CLI — same shape (-s user matters: Gemini defaults to project scope; the -e env gives Gemini sessions their own write attribution, and the same Docker-tier PSEUDOLIFE_MCP_NO_SPAWN=1 note as above applies):

pip install pseudolife-mcp
gemini mcp add -s user -e PSEUDOLIFE_WRITER_ID=gemini -e PSEUDOLIFE_MCP_NO_SPAWN=1 pseudolife-memory pseudolife-mcp

Or HTTP, no pip package needed:

gemini mcp add -s user -t http pseudolife-memory http://127.0.0.1:8765/mcp

Note: since 2026-06-18 Google no longer serves individual-tier accounts (free, AI Pro, AI Ultra) through Gemini CLI — OAuth sign-in fails and points at Antigravity. The wiring above stays correct, but individual accounts need API-key auth (GEMINI_API_KEY) to actually run sessions — or use Google Antigravity itself, which connects to the same bank via ~/.gemini/config/mcp_config.json; both are covered in the providers guide.

Any other MCP-capable agent (Cursor, Windsurf, Zed, Copilot CLI, …) — add the generic mcpServers entry to that tool's MCP config (ops/install.sh --client generic prints both shapes ready to paste):

{
  "mcpServers": {
    "pseudolife-memory": {
      "command": "pseudolife-mcp",
      "env": {
        "PSEUDOLIFE_WRITER_ID": "mcp-client",
        "PSEUDOLIFE_MCP_NO_SPAWN": "1"
      }
    }
  }
}

What each agent gets — and what its platform can't support (hooks, per-turn discipline): the provider matrix.

Verify: run claude mcp list, codex mcp list, or gemini mcp list (the server should report connected), then ask the agent to "store a memory that this install works" and check it appears in the Stream tab of the Console at http://127.0.0.1:8765/ui/.

Preferring stdio (this is what the installer wires by default, for per-session identity)? A thin torch-free shim proxies stdio to the daemon: stdio shim · LAN sharing · backups & restore rehearsal · agent mailbox recovery.

The server's value depends on the agent using it. The MCP server advertises the core loop through protocol-level instructions; the SessionStart hook delivers the full memory policy with a live briefing. The default hook policy and bundled standing memory block contain the same instructions. Hooks add per-prompt reminders and session bookkeeping; neither delivery method guarantees that the model performs every requested memory operation.

With verified hooks, a standing copy is optional. If you want it instead — or additionally, for subagent visibility (subagents read CLAUDE.md but not hook output) — append it to Claude's global ~/.claude/CLAUDE.md, Codex's global ~/.codex/AGENTS.md, Gemini's global ~/.gemini/GEMINI.md, or a per-project CLAUDE.md / AGENTS.md:

cat examples/CLAUDE.memory.md >> ~/.claude/CLAUDE.md
cat examples/CLAUDE.memory.md >> ~/.codex/AGENTS.md
cat examples/CLAUDE.memory.md >> ~/.gemini/GEMINI.md
Add-Content "$env:USERPROFILE\.claude\CLAUDE.md" (Get-Content examples\CLAUDE.memory.md -Raw)
Add-Content "$env:USERPROFILE\.codex\AGENTS.md" (Get-Content examples\CLAUDE.memory.md -Raw)

For hook-less providers this standing block supplies the full memory policy, but it cannot provide a live briefing or run session cleanup. AGENTS.md is the cross-vendor standard for standing agent instructions (Linux Foundation-governed; read by Codex, Copilot, Cursor, Gemini CLI, Zed, and 30+ others), so a per-project AGENTS.md carrying the block reaches almost every agent at once. Claude Code is the holdout — it reads CLAUDE.md — but a CLAUDE.md whose first line is @AGENTS.md imports the shared file, so one copy serves every tool.

The block (examples/CLAUDE.memory.md) teaches the loop: RECALL at the start (memory_search / memory_lesson_search / memory_fact_get / memory_world_search), CAPTURE as you go (memory_store with an honest origin, memory_fact_set for canonical facts, memory_world_set for cited external facts, source="status" for verbose logs so they stay out of the dream), REFLECT at the end (memory_outcome, with used_ids naming the hits you actually used — the dream distils these signals into the lessons surfaced at your next session start).

For an existing Codex installation, run python ops/setup-codex-hooks.py. The helper asks once, detects the hook source, backs up changed configuration, persists scoped trust through Codex, and verifies startup briefing, prompt reminder, and session cleanup. The Docker installer runs this step for you. See Codex setup options and fallback.

For Claude Code, use the plugin, or the legacy ops/install-hook.ps1 -Client claude / ops/install-hook.sh --client claude for briefing and reminder hooks. The legacy --client codex path remains available but only writes hook definitions; it does not complete trust and verification. Session episodes also work without hooks through the daemon: Episodes & sessions.

Current Codex runtimes enable hooks by default, including Windows. Availability depends on the application/runtime and policy, not the model. If [features] hooks = false is intentional, keep it and use the standing AGENTS.md block. Windows plugin hooks use native PowerShell 7 commands. See the official hook protocol.

Codex hook trust: setup approval is limited to PseudoLife's three current hook definitions. It does not approve other plugins or bypass future trust checks. Changed definitions need approval again. If automatic setup cannot use the installed runtime's trust interface, it reports the problem and asks you to open /hooks to review and trust the definitions. Approved standing instructions remain available as fallback. Installed files alone do not establish that hooks are working.

Usage patterns

At session start — loads what you've worked on before, persistent across compactions:

memory_search("project context for X")

During work — store real decisions; skip fleeting chatter (the shipped store gate is permissive, so deliberate, durable claims only):

memory_store("Decided to use stdio transport for the MCP because no port conflicts", source="pseudolife")

When corrected — marks the old fact superseded and stores the correction; both surface in future retrieval, the new one ranked higher. Select the entry by the id carried on the search or recent hit:

memory_supersede(
  entry_id=417,
  new_text="Provider interface uses async calls — sync version was the v0.7 prototype only"
)

old_text= still selects by the full stored text when that text is exactly unique among live entries; it is the legacy selector and the only one file mode has. Ambiguous or missing targets change nothing.

Hygienememory and fact scopes hard-delete (at least one filter is required for scope memory, preventing accidental wholesale deletion); lesson and world scopes retire the slot with an audit row and are reversible with memory_graph_review(action="restore_slot", store=..., src="entity|attribute"); for "keep the history but mark it wrong" use memory_supersede instead:

memory_forget(scope="memory", source="test-noise")
memory_forget(scope="fact", entity="test-entity")

Discovering what's in the bank: open the Cortex Console — sources, tags, episodes, and full-table views all live there. Going deeper: reranking, BM25, abstention, and trace debugging · episodes + tags · canonical facts, contenders, world facts, lessons · the consolidation workflow.

Dreaming — consolidating memories into facts

A dream distils the recent associative stream into canonical cortex facts while you're not looking: pull unconsolidated memories → extract (entity, attribute, value) → acknowledge those exact entries durably. New entries remain pending regardless of their timestamps; failed acknowledgement can replay claim application. Manual commits use the token returned by pull. Extraction is pluggable:

Tier

How it runs

Needs

Quality

0 — none

no extractor configured — the dream still runs, prunes, and acknowledges input batches, but writes no canonical facts

nothing

none (memory_fact_set is your only cortex writer)

1 — agent-driven

the agent itself is the gateway: the /dream judgment session (its manual-extraction branch fires only when no endpoint is configured)

the agent you already run

highest

2 — shipped default

daemon auto-sweep → the bundled CPU sidecar, or any OpenAI-compatible endpoint

nothing (sidecar)

high; free if local

The stack ships tier 2 preconfigured (the bespoke Gemma 4 E4B extractor fine-tune in a llama.cpp sidecar, internal-only). The sweep cadence, pointing dreams at a bigger local model or at Claude Sonnet with automatic sidecar fallback, the full-corpus deep dream graph pass, and the privacy/cost trade-offs: Dreaming.

Benchmarks

The headline is the whole benchmark, not a slice: all six LongMemEval question types, 500 questions, oracle variant, run end to end through the memory (qwen-27b extraction under the v25 embedding backbone, BM25-on turn retrieval). Single pass, graded by the local Qwen3.6-27B bench judge (2026-08-03):

arm

accuracy

context tokens/question

naive RAG (top-6 turns)

0.688

~1210

cortex facts only

0.416

~158

hybrid (facts + top-3 turns)

0.664

~842

commit-gated cascade

0.690

~883

The cascade is a serving policy, not a fourth pipeline: answer from the consolidated facts when that channel commits, fall back to raw-turn RAG when it abstains. Overall this is a wash on accuracy at ~73% of the context — 0.690 vs 0.688 is one question in 500 on a single pass, and nobody should read it as a win. The fact spine alone answers at ~13% of RAG's token budget, at a large accuracy cost outside the types it is built for. The structure is per type:

question type

n

naive RAG

commit-gated cascade

knowledge-update (facts change)

78

0.859

0.936 (retired — why)

single-session-user

70

0.929

0.943

single-session-assistant

56

0.911

0.929

single-session-preference

30

0.800

0.700

temporal-reasoning

133

0.526

0.526

multi-session

133

0.504

0.474

The consolidated spine helps where a fact changes and where the answer sits inside one session; it loses where the answer must be aggregated across sessions or ordered in time, because per-fact consolidation is exactly what discards that structure. BEAM-100K reproduces the same shape independently. Its abstention questions are where the spine looks best — the fact-spine arm scores 0.950 against naive RAG's 0.775, identical under the local judge and under an independent Opus-class judge — but the 2026-09-02 five-arm run bounds that reading: a no-memory arm scores 1.000 there, so the edge is calibration (a small fact context refuses where raw turns confabulate), not evidence that the memory recalled anything. Setup, caveats, both bench stacks side by side, and the evidence that extraction quality is the dominant factor: Benchmarks; full methodology: evals/README.md.

Retrieval itself was re-measured on the same corpus before the v25 backbone swap (150 questions, 74,183 haystack turns, 299 gold turns; pure recall — no reader, no judge): Qwen/Qwen3-Embedding-0.6B reaches R@10 0.809 against bge-base-en-v1.5's 0.742 and the previously-shipped all-MiniLM-L6-v2's 0.572, and beats bge-base head-to-head +32/−12 at k=10 (p=0.004). Artifacts: embedder-recall-shootout-20260727.json, embedder-recall-qwen-vs-bge-20260728.json.

Cortex Console (web UI)

An operator dashboard served by the daemon itself — point a browser at http://127.0.0.1:8765/ui/ (the /health and /mcp endpoints are unchanged; the console is additive). It's a read-mostly instrument panel for seeing and steering the memory a human otherwise can't observe: Observatory (health, per-layer counts, the memory store's capacity meter, dream gauges), Cortex (canonical facts with provenance, version-history timelines, inline Accept/Discard for contested slots), World / Lessons / Episodes, Stream (live search with rerank/BM25 toggles and a ranking-trace debugger), Graph (interactive force-directed visualiser, with a review drawer that can Accept/Reject merges or — for a source file and its own bare concept, band.pyband — record an implements edge instead of forcing merge-or-dismiss; proposals a background dream has already judged carry a verdict chip — accept/reject/leave with confidence, the model's reason in the tooltip — as a lead, never a decision), and Console (every safe config.yaml scalar with live-vs-restart badges, diff-preview, and atomic save).

Auth mirrors /mcp: /ui (static shell) and /health are open; /api/* requires the same PSEUDOLIFE_MCP_TOKEN bearer when one is set (the console prompts for it and stores it locally). No build step, no CDN, fully offline — vanilla ES modules + vendored OFL fonts served straight from the daemon. Developing the UI? A fixture-backed dev server (no Postgres, no torch) renders the real frontend against canned data: python -m pseudolife_memory.web.devserverhttp://127.0.0.1:8770/ui/. Its payloads self-announce ("fixtures": true on /health), and the topbar shows a "DEMO DATA — fixture server, not a real bank" chip in place of the live chip, so a fixture run is never mistaken for a real bank.

Capabilities at a glance

Capability

Status

Transport

Streamable-HTTP MCP daemon (/mcp); stdio shim is the installer default (per-session identity) — HTTP remains for single-session setups

Storage

Postgres 18 + pgvector (source of truth); ChromaDB for the reference bank

Associative store

Flat similarity store (default since the 2026-08-15 measured verdict; the 8-tier banded preset remains opt-in); hybrid dense + BM25 ranking (BM25 on by default); contradiction detection admits potential updates, including a deterministic slot-identity path regardless of embedding similarity, while retaining earlier source notes; whole-note supersession requires an explicit replacement operation

Canonical-fact cortex

Single-writer: LLM dream pass + memory_fact_* (regex auto-promote opt-in, default off)

Set-valued slots

memory_set_add / memory_set_remove for many-current-value slots; one-way scalar→set conversion, aggregate scalars guarded (park as contender); an assistant-origin add cannot convert or join another tier's set, and cannot retract another tier's member

Provenance contenders

Tier-rank guard user > action > agent > assistant; memory_fact_resolve

Fact currency

Every cortex fact is dated (asserted_at / age); freshness_class (evergreen / slow / volatile) decays effective_confidence and flags stale. Left auto, the class is inferred from the entity's kind (schema v24 entity_kinds) — only system entities can rot; artifacts and concepts stay evergreen

Write-time labels

authority (directive / observation / quoted — the speech act, orthogonal to the origin tier) and distortion_tolerance (constraint / procedural / belief / preference / episodic) on entries and facts, set at write time (explicit, or a deterministic heuristic under auto) and inherited through supersession unless restated. A constraint source is carried verbatim through the dream (with a post-dream guard) and pinned ahead of cosine in memory_search's cortex block and memory_recall when the query names its entity; a quoted source is low-trust for the two-man rule (schema v35)

Knowledge graph

Typed entities/edges, closed relation vocab, on-read closure (Postgres + NetworkX, no AGE/Cypher)

World cortex

memory_world_* — cited external facts + age-decayed freshness (manual ingest)

Procedural memory

memory_outcome (signals) → dream-synthesised lessons via memory_lesson_search; prefers/avoids graph edges; single-writer

Sense of time + multi-writer

Per-write stamp (tx/valid time, HLC ordering, writer/session); memory_history; relative age on reads; write_mode seam (snapshot live, occ Phase-2)

Episodes + tags

Session episodes daemon-owned, keyed by a resolved five-tier session identity; hook/shim eager-open or lazy-open + idle reaper + prune-empty + resume-after-reap; nested sub-episodes with subtree-expanded recall; multi-valued tags=[...]

Session briefing

SessionStart hook injects unsure-graph + lessons + verified world facts + last-session recap (pseudolife-mcp briefing)

Consolidation

memory_consolidation_candidates + memory_consolidate

Optional components

Cross-encoder reranker (rerank=True, ~80 MB); ONNX embedding backend (pip install .[onnx] — load-only and auto-selected when installed, ~3x faster CPU encode on MiniLM. The configured artifact must already exist locally: the daemon image provisions MiniLM's while building, while a pip install stays on torch until you provision it yourself. Models whose Transformer module loads from a subfolder fall back to torch on native Windows, and the default Qwen3-Embedding-0.6B has no ONNX export at all); NLI contradiction scorer (pip install .[nli], ~278 MB)

Web console

Cortex Console at /ui/ — health/stats, fact review + history, graph visualiser, search/trace, config editor (read-mostly, token-gated like /mcp)

Schema version

v40 (Postgres meta version) — additive ADD COLUMN IF NOT EXISTS migrations on daemon start, except v25: the vector(384)vector(1024) move is not additive, so the daemon refuses to start against an older-dimensioned bank until you run ops/migrate_embeddings.py; legacy file-mode .pt banks auto-migrate into Postgres; full version history

Troubleshooting

Start with curl http://127.0.0.1:8765/health — it reports the schema version, storage backend, auth state, and persist_errors (non-zero means writes are failing to reach Postgres; check docker logs pseudolife-mcp-daemon).

  • The cortex stays empty (canonical facts never appear on their own). /health reporting "extractor": "none" means no extractor is configured, so the dream writes no facts and memory_fact_set is the only cortex writer — expected on the lite tier. Point the daemon at an OpenAI-compatible endpoint (Quickstart) or use the Docker tier's bundled sidecar. "extractor": "disabled" instead means dreaming itself is switched off in config.

  • Lite daemon refuses to start on Windows with a message about the data path: the embedded Postgres runtime needs an ASCII-only data directory. Set PSEUDOLIFE_MCP_DATA_DIR to one (e.g. C:\pseudolife-data) — Configuration.

  • First build is slow / big. The daemon image (~5.0 GB, several minutes to build) bakes in CPU torch and the embedding weights (Qwen3-Embedding-0.6B plus MiniLM); the extractor sidecar adds a ~5.3 GB model download on its first build. Every start after that is offline and fast — if a rebuild is re-downloading models, the Docker layer cache was pruned.

  • Daemon unreachable after wsl --shutdown (Windows): the host port forward is gone — docker restart pseudolife-mcp-daemon re-establishes it.

  • Docker eating RAM (Windows): the WSL2 VM (Vmmem) claims up to ~50% of host memory by default. Copy ops/wslconfig.example to %USERPROFILE%\.wslconfig, tune memory=, then wsl --shutdown.

  • Port already in use: the stack binds 127.0.0.1:8765 (daemon) and 127.0.0.1:5433 (Postgres). Change the host side in ops/docker-compose.yml if either collides.

  • Console shows "offline" / Unauthorized: "offline" means the daemon isn't reachable (see above); a 401 prompt means it runs with PSEUDOLIFE_MCP_TOKEN — paste that token into the Console's Token dialog.

  • The coding agent doesn't see the tools: claude mcp list or codex mcp list should show pseudolife-memory ✓ connected. If not, re-check the URL (http://127.0.0.1:8765/mcp — the /mcp path matters) and the bearer header when a token is set. The daemon preloads the embedder on a warmup thread at start (~5–10 s); a very early first call can race it and take a few seconds.

  • Tools vanish after an upgrade / the client log says "Connection closed": the shim's registered command can live outside the repo venv, and the MCP SDK v2 migration set an mcp>=2.1 floor — an older SDK in that environment crashes the shim on start. The shim detects this and prints the interpreter path and the exact fix on stderr: pip install -U "mcp>=2.1,<3" in that interpreter, or re-run the installer (which registers the project venv's shim).

  • A harness "removed tools" notice is not an outage. A resumed session can carry a larger tool roster in its transcript than the current toolset tier serves — that's a visibility filter, not a disconnect. Make one memory_search call before concluding the MCP is down.

Uninstall

Lite tier: remove the MCP registration (claude mcp remove pseudolife-memory / codex mcp remove pseudolife-memory), then pip uninstall pseudolife-mcp. If you also want the bank gone, delete the per-user data directory (%LOCALAPPDATA%\pseudolife-mcp on Windows, ~/.local/share/pseudolife-mcp on Linux, ~/Library/Application Support/pseudolife-mcp on macOS — or wherever PSEUDOLIFE_MCP_DATA_DIR points). Back it up first: pseudolife-mcp backup works on lite too.

Docker tier — deletion is deliberate at every step:

# 1. Optional: take a final backup first (ops/backup.ps1 or ops/backup.sh).
# 2. Stop and remove the containers (volumes survive this).
docker compose -f ops/docker-compose.yml down
# 3. Remove the MCP registration.
claude mcp remove pseudolife-memory
codex mcp remove pseudolife-memory
gemini mcp remove pseudolife-memory -s user
# 4. Only when you're sure: delete the data volumes (THIS is the memory).
docker volume rm pseudolife-mcp-bank pseudolife-mcp-state

Host-process installs: also unregister the logon task (Unregister-ScheduledTask -TaskName "Pseudolife-MCP Daemon") and remove the SessionStart briefing hook — plus, Claude client, the UserPromptSubmit discipline hook — from ~/.claude/settings.json and/or ~/.codex/hooks.json (a timestamped .bak-* sits next to each edited file).

Testing

pip install -e .[dev], then pytest tests/. The suite covers every layer, from the MemoryService surface to the Cortex Console REST API; model-heavy pieces are stubbed so it stays fast and offline. The PG-backed suites each target a throwaway per-run pseudolife_memory_test_<pid> database on the bundled dev container (never your real bank; concurrent runs can't collide), dropped on exit, and skip cleanly without Postgres. Full dev setup: CONTRIBUTING.

What's not built yet

  • Reflection via MCP sampling — would let the dream borrow Claude itself as the extractor; Claude Code doesn't yet support it.

  • Cross-machine sync — memory lives on one PC's disk; syncing via rclone / syncthing is left as an exercise.

  • Automated world-knowledge ingestion — populating the world cortex from the live web needs a web-fetch tool the standalone server doesn't ship; an agent with web access can automate the fetch+cite step today via memory_world_set.

Support

Solo-maintained, best-effort. One person builds, tests, and runs this; there is no support contract and no response-time commitment. That said, issues are read and most get an answer.

  • Something is broken → open a bug report. The form asks for your /health output, schema version, install tier, and client, because those four answer most questions before any back-and-forth.

  • Something is missing → open a feature request. Say what you were trying to do, not only what to add.

  • A security problem → do not open a public issue. Use GitHub's private vulnerability reporting — SECURITY.md. Memory integrity specifically: security posture.

  • Sending a patchCONTRIBUTING and CODE_OF_CONDUCT. The bar is "surgical, tested, and explained", not "big".

If you need someone to call, Comparison — use something else if names vendors who sell support.

License

Apache-2.0 — see LICENSE and NOTICE.

Available Tools

35 tools
document_ingestA

Index a file into the reference bank — a separate store for background documents (papers, manuals, codebases) retrieved by pure cosine similarity, kept apart from conversational memory.

Returns: {source, chunks_stored, chunks_total}.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYesPath to a .txt / .md / .pdf file, resolved on the SERVER's filesystem — with the Docker daemon, a path visible inside the container (e.g. a mounted volume), not a host path.
sourceNoSource tag for the chunks; defaults to the filename.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.2/5.0
Behavior4/5

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

With no annotations provided, the description carries the full behavioral burden. It discloses that the operation writes to a separate reference bank and returns a specific object {source, chunks_stored, chunks_total}, giving the agent a clear outcome model. It does not mention overwrite/idempotency behavior or error conditions, but the core mutation and return contract are transparent.

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

Conciseness5/5

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

The description is compact and front-loaded: the first sentence establishes the action and store semantics, and the second sentence gives the return contract. There is no filler or redundant restatement; every sentence contributes.

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 2-parameter tool with complete schema descriptions and an output schema, the description provides sufficient context: the store purpose, the file domain, and the return shape. Minor gaps remain around duplicate handling and failure modes, but an agent can invoke this tool correctly with the supplied information.

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. Both path and source are already fully described in the schema: path is server-side and container-aware, and source defaults to the filename. The main description adds no parameter-level detail beyond what the 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?

The description states a specific action, 'Index a file into the reference bank,' and defines that bank as a separate store for background documents (papers, manuals, codebases) kept apart from conversational memory. This clearly differentiates document_ingest from the many memory_* siblings and from document_search, which is the retrieval counterpart.

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 for when to use the tool: for background reference documents such as papers, manuals, and codebases, and it explicitly distinguishes these from conversational memory. It does not name the alternative tool (e.g., memory_store), but 'kept apart from conversational memory' strongly implies the boundary between this tool and the memory_* family.

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

memory_aliasA

Bind an alternative name to an entity (e.g. pgpostgres) so facts and graph lookups under either name land on the same node. Returns the entity's full alias list.

ParametersJSON Schema
NameRequiredDescriptionDefault
aliasYesThe alternative name.
entityYesThe canonical entity to bind onto.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.5/5.0
Behavior3/5

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

No annotations are provided, so the description carries the behavioral burden. It discloses the core effect—facts and graph lookups under either name land on the same node—and the return value, but does not mention edge cases like overwriting existing alias bindings, behavior for missing entities, or reversibility.

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, front-loaded with the action, containing a helpful example and a clear statement of the return value. No redundant repetition of schema 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 simple tool with two required parameters and an output schema, the description adequately covers what it does, how it behaves, and what it returns. The main gaps are usage routing and mutation edge cases, which are not essential for basic invocation.

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

Parameters4/5

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

Schema coverage is 100%, so the baseline is 3, but the description adds relational meaning beyond the schema: the example illustrates the direction alias → canonical entity and explains that both names resolve to the same node. This enriches the minimal schema descriptions.

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 action, 'Bind an alternative name to an entity', with a concrete example 'pg → postgres', clearly identifying it as alias management rather than generic memory storage. It is distinct from siblings by function, though it does not explicitly call out any sibling by name.

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

Usage Guidelines2/5

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

Provides no explicit guidance on when to use this tool versus alternatives such as memory_supersede or memory_graph_relate. Usage is only implied by the purpose, with no exclusions, prerequisites, or alternative routing.

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

memory_consolidateA

Replace a cluster of near-duplicate memories with one canonical note. Every entry matching replaces is marked superseded by new_text, which is stored fresh — the bank gets shorter without losing the audit trail.

Returns: {superseded_count, superseded_texts, new_memory_stored}.

ParametersJSON Schema
NameRequiredDescriptionDefault
tagsNoLabels for the new note.
sourceNoSource tag for the new note.
new_textYesThe canonical note that replaces them.
replacesYesThe memories being folded in; each is matched by exact text or close paraphrase.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.8/5.0
Behavior4/5

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

With no annotations provided, the description carries full responsibility for behavioral disclosure. It clearly states that matched entries are marked superseded, the new text is stored fresh, and the memory bank shrinks without losing the audit trail. This gives the agent a solid model of side effects without overclaiming.

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?

The description is compact and front-loaded, with the primary action stated first and no filler. The return shape is included as a separate line, and every sentence adds information relevant to invoking the tool.

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 4-parameter tool with an output schema and full schema coverage, the description covers the operation, side effects, and return value. It is slightly incomplete only in not explicitly guiding selection among the many closely related memory tools.

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 input schema already documents every parameter. The description adds contextual color ('canonical note', 'stored fresh') but does not need to duplicate parameter-level detail, 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 ('Replace') and resource ('a cluster of near-duplicate memories'), making the core purpose immediately clear. It is not a tautology and is distinguishable from related tools like memory_store or memory_forget, though it does not explicitly name a sibling for comparison.

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 phrase 'cluster of near-duplicate memories' implies the appropriate context, and the tool clearly is meant for consolidation rather than simple storage. However, it does not explicitly say when to prefer this over siblings like memory_supersede or memory_consolidation_candidates, leaving some routing to inference.

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

memory_consolidation_candidatesA

Find clusters of near-duplicate memories ripe for consolidation — the same thing phrased five ways across five sessions. Anchor with a query or an episode; read the clusters, synthesise one canonical note, then commit it via memory_consolidate.

Returns: {count, clusters: [{cohesion, size, members}]}.

ParametersJSON Schema
NameRequiredDescriptionDefault
tagsNoConsider only entries carrying one of these tags.
queryNoTopic-driven anchor: cluster memories near this description.
top_kNoHow many candidate entries to cluster over.
episodeNoSession-driven anchor: cluster within this episode id.
sourcesNoConsider only entries with one of these source tags.
max_clustersNoMax clusters returned.
min_cohesionNoMinimum intra-cluster cosine — raise it to flag only near-duplicates.
min_cluster_sizeNoDrop clusters with fewer members than this.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.2/5.0
Behavior4/5

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

With no annotations provided, the description carries the behavioral disclosure burden. It does so well by framing the tool as a read-only finder ('read the clusters') and explicitly deferring the mutation to memory_consolidate. It also discloses the return shape. It could be stronger by explicitly stating the tool does not modify memories and clarifying what happens when both query and episode are supplied, but it is not misleading.

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?

The description is compact and front-loaded. The first sentence states the core purpose, the second gives the actionable workflow, and the third states the return shape. Every clause earns its place, and the bolded instruction to synthesize and commit via memory_consolidate adds valuable workflow context without padding.

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

Completeness4/5

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

Given eight optional parameters, full schema coverage, and an output-schema hint, the description is sufficiently complete for an agent to use it correctly. It supplies the return format, workflow, and anchor strategy. The only notable gaps are the lack of an explicit 'read-only/no side effects' statement and no guidance on query/episode mutual exclusivity, but these are minor because the workflow implies them.

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 minimal parameter-specific meaning beyond the schema: it re-emphasizes query and episode as anchors but does not explain tags, sources, top_k, max_clusters, min_cohesion, or min_cluster_size in more depth. The schema already handles parameter semantics adequately.

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

Purpose5/5

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

The description opens with a specific verb-resource pair: 'Find clusters of near-duplicate memories ripe for consolidation.' It clearly differentiates this from memory_consolidate by positioning it as the discovery step before commit. The concrete example phrase 'the same thing phrased five ways across five sessions' makes the purpose vivid and unambiguous.

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

Usage Guidelines4/5

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

The description gives clear usage context: anchor with query or episode, inspect clusters, synthesize a canonical note, then commit via memory_consolidate. It explicitly names the related sibling tool for the follow-up action. It does not enumerate exclusions versus memory_search or memory_recent, but the consolidation-specific framing is enough to guide selection.

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

memory_dreamA

Drive the dream — consolidation of recent memories into canonical facts and graph structure.

Actions: status: backlog + whether a sweep would fire. Read-only. pull: unconsolidated memories, oldest first; write facts via memory_fact_set, then commit. run: a server-side dream with the configured extractor (loop to drain). deep: full-corpus graph consolidation; dry run unless apply. Settle candidates via memory_graph_review; duplicate lesson/world slots are listed for hand curation. runs: recent dream passes (tallies, status). rollback: revert a committed pass from its journal (facts + events; traces/cursor kept).

Returns: per-action dict; {error} on bad input.

ParametersJSON Schema
NameRequiredDescriptionDefault
applyNodeep: True writes the consolidation (graph tables are snapshotted first); the default is a dry run.
limitNopull/run: how many memories to process (pull defaults to 40). runs: how many passes to list (defaults to 10).
actionYes
cursorNocommit: the newest pulled timestamp. Required for that action.
run_idNorollback: which pass to revert; defaults to the newest committed pass.
snippetsNodeep: False omits the evidence snippets.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.9/5.0
Behavior4/5

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

With no annotations, the description carries the behavioral burden and discloses side effects: status is read-only, pull writes facts via memory_fact_set and then commits, deep can write with a snapshot, and rollback reverts facts/events while keeping traces/cursor. It does not address idempotency or commit as a standalone behavior, but nothing contradicts 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?

The description front-loads a one-line purpose, then presents a scannable action list with no redundant prose. Every bullet adds operational information, and the return note is appropriately brief.

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 complex seven-action tool with no annotations, the description covers most behavioral and workflow context, and the output schema covers return values. It is slightly incomplete because the commit action has no bullet of its own and there is no direct comparison to memory_consolidate, but the schema fills the commit cursor requirement and the overall picture is actionable.

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 83%, so the baseline is 3, but the description adds real value by decoding the action enum and linking parameter semantics to workflow (pull then commit, dry run unless apply, rollback targeting a pass). It leaves snippets to the schema, which already documents it, so the description complements rather than restates 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?

The opening sentence states the tool's purpose — consolidating recent memories into canonical facts and graph structure — and the action list makes the operational scope concrete. It does not explicitly contrast itself with sibling tools like memory_consolidate, so it stops short of full sibling differentiation.

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?

Each action bullet provides usable context, including status being read-only, deep being a dry run unless apply is set, and rollback reverting a committed pass. However, there is no when-not or selection guidance against likely alternatives such as memory_consolidate, so the agent must infer when this orchestration tool is preferred.

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

memory_episode_endA

Close the current open sub-episode and pop back to its parent.

ParametersJSON Schema
NameRequiredDescriptionDefault
episodeNoYour session handle — pops only within your own session's subtree; the session root is never closed.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.2/5.0
Behavior4/5

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

With no annotations provided, the description carries the full burden of behavioral disclosure. It states the state transition ('closes', 'pops') and the scope limitation ('only within your own session's subtree; the session root is never closed'). It does not specify behavior when no sub-episode is open, but the core mutating behavior is clearly disclosed.

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?

The description is one front-loaded sentence that states the action, target, and result with no filler. The important constraint is placed in the parameter schema, which is the right location for it. Every word 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 one-parameter tool with a well-documented schema and an output schema, the description covers the normal invocation scenario and the key limitation. It does not spell out edge cases like calling with no open sub-episode, but the root-never-closed note partially covers boundary behavior. Overall, it is complete enough for an agent to select and use the tool correctly in typical cases.

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?

The input schema has 100% description coverage and explains the single optional parameter well, including that 'episode' acts as a session handle and that the root is never closed. The tool description itself does not add parameter-level meaning beyond the schema, but it does not need to because the schema already handles it. Baseline 3 is appropriate here.

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 action ('Close'), a specific resource ('current open sub-episode'), and the outcome ('pop back to its parent'). This clearly differentiates it from sibling tools like memory_episode_start and memory_episode_summary. There is no ambiguity about what the tool does.

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

Usage Guidelines4/5

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

The description states a clear condition for use: a sub-episode is currently open and should be closed while returning to its parent. The parameter description adds a useful exclusion by noting that the session root is never closed and that only the caller's own session subtree is affected. It does not explicitly name alternative tools, but the start/end relationship is obvious 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.

memory_episode_startA

Open a named sub-episode; it nests under the session episode, and memories stored while it is open carry its id + title for episode-scoped search. memory_episode_end closes it and pops back.

ParametersJSON Schema
NameRequiredDescriptionDefault
hintNoOptional note on what the task is about.
titleYesShort name for the task, used in later recaps.
episodeNoYour session handle (from the session-start briefing) — anchors the sub-episode to YOUR session when several run concurrently.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.2/5.0
Behavior4/5

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

With no annotations, the description carries the burden of behavioral disclosure. It states that the operation is stateful, nests under the session episode, attaches id/title to memories stored while open, and that memory_episode_end pops back. It leaves some edge behavior implicit, such as repeated starts while a sub-episode is already open, but the core side effects are clearly disclosed.

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?

The description is two compact sentences that front-load the purpose and then give the lifecycle and close behavior. Every clause earns its place; there is no filler, repetition, or redundant per-parameter prose.

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 stateful scoping tool with a complete schema and an output schema, the description covers the operation, the reason to use it, and the complementary end call. The only omissions are edge-case behaviors such as what happens if no session episode exists or if called when a sub-episode is already open, which would push it to full completeness.

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 input schema already documents title, hint, and episode. The description only reinforces that title is carried by stored memories and adds no new parameter semantics. Baseline 3 is appropriate here.

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

Purpose5/5

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

Description uses an active verb ('Open') with a clear resource ('a named sub-episode') and explains that it nests under the session episode. It also distinguishes itself from the sibling close/summary/session-title tools by describing the episode-scoped storage effect. An agent can tell at a glance what this tool is for.

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 a clear use context: open a sub-episode when you want subsequently stored memories to carry its id + title for episode-scoped search. It names the paired closing tool, memory_episode_end, but does not explicitly list when-not-to-use or alternatives, so it stops just short of full guidance.

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

memory_episode_summaryA

Stats, tag/source distribution, and recent entries for one episode — "summarise what we worked on". Returns {found: false} for an unknown id.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesAn episode id, as it appears on search/recent results.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.9/5.0
Behavior4/5

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

With no annotations provided, the description carries the transparency burden. It does well by stating what the tool returns and explicitly documenting the unknown-id fallback of `{found: false}`. It does not explicitly state that the tool has no side effects, but 'summary' and the return behavior strongly imply a read-only operation.

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?

The description is compact and front-loaded: it lists the key content, gives a natural-language usage cue, and includes the important edge-case return value. No sentence is wasted.

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 one-parameter tool with an output schema, the description is sufficiently complete. It covers what the call returns, how to identify an unknown episode, and the source of valid ids (via the schema). Nothing critical is missing for correct invocation.

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?

The input schema already documents the only parameter with a clear description ('An episode id, as it appears on search/recent results'), and schema coverage is 100%. The tool description adds little beyond the schema, so the baseline score of 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 clearly identifies the tool's focus: stats, tag/source distribution, and recent entries for one episode. The plain-language cue 'summarise what we worked on' makes the intent obvious, though it does not explicitly distinguish this from sibling tools like memory_stats or memory_recent.

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 context is implied: you use this when you want a summary of a single episode, and the id should come from search/recent results. However, the description does not explicitly state when to prefer this tool over alternatives or when not to use it.

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

memory_fact_getA

Look up the one CURRENT value at an (entity, attribute) slot. One value per slot. A null record means EMPTY, not unknown — memory_search still finds context. A set-valued slot returns {kind: "set", members, removed} instead — members: [] means EMPTY too.

Returns: {record | null, contenders} (+ entity_ref when the entity has a graph node). Non-empty contenders = unsettled conflict (see memory_fact_resolve); on an empty slot, candidates lists nearby slots — ranked leads, not answers. re_verify = a memory this fact was derived from has since been corrected; the value still stands but check it before acting. Set slots carry it too, at the slot. Its absence is not a guarantee: the flag is read from evidence that still exists, so it stops once the corrected memory is evicted or deleted.

ParametersJSON Schema
NameRequiredDescriptionDefault
entityYesThe slot's subject; the (entity, attribute) match is case- and separator-insensitive.
attributeYesThe slot's attribute.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.7/5.0
Behavior5/5

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

With no annotations provided, the description fully carries the behavioral burden. It reveals the meaning of null versus unknown, set-valued slot behavior, empty-set semantics, conflict signaling via contenders, the candidates field on empty slots, the re_verify flag, and its eviction/deletion limitation. This is unusually transparent and leaves little to guess.

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?

Although the description is long, it is densely packed with essential behaviors: value cardinality, null semantics, set handling, return fields, conflict resolution, and re_verify caveats. It front-loads the core purpose and spends every sentence on operationally relevant details. No filler is present.

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?

This is a nuanced tool with edge cases, and the description addresses all major ones: empty-vs-unknown, set-valued slots, unresolved conflicts, candidate leads, graph-node references, and the re_verify flag. Since an output schema exists, describing the full return shape is less critical, but the description still adds valuable semantic context about what each flag means in practice.

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 meaning beyond the schema by clarifying that entity and attribute jointly define a slot with exactly one current value, and that attribute types (scalar vs set) change the returned shape. This is useful enrichment rather than repetition of 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 states a specific action (look up the one CURRENT value) and a specific resource ((entity, attribute) slot). It clearly distinguishes this from memory_search by explaining that a null record means EMPTY, not unknown, and that memory_search still finds context. This is far beyond a vague purpose.

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 for when this tool is appropriate: retrieving the current value at a slot. It points to memory_search for continued context on empty slots and to memory_fact_resolve for unsettled conflicts. It stops short of an explicit exclusion list or a direct 'use X instead' statement for a sibling like memory_get, but the guidance is largely present.

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

memory_fact_resolveA

Settle a CONTESTED fact slot after checking with the human.

Returns: {resolved, accepted, action, current, record} or {resolved: false, reason: "no_contender"}.

ParametersJSON Schema
NameRequiredDescriptionDefault
acceptYesTrue adopts the parked contender as the new current value (the old value is kept as history); False discards the contender and keeps the current value.
entityYesThe contested slot's subject.
attributeYesThe contested slot's attribute.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4/5.0
Behavior4/5

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

With no annotations, the description plausibly carries the burden of explaining behavior. It adds a useful return contract showing success keys and the no-contender failure case, and it signals a human-in-the-loop requirement. It does not explicitly describe the mutation effect itself, but the accept parameter schema and the return keys together provide enough behavioral context.

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?

The description is two short, purposeful sentences: the first explains what the tool does, and the second gives the return shapes. There is no filler, and the core purpose is front-loaded.

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 three-parameter tool with a fully described input schema and an output schema present, the description is largely complete: it names the contested-slot context, the human-check requirement, and the possible outcomes. It could be more complete by explicitly stating side effects and exclusions, but it is not missing anything critical.

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 tool description itself adds no parameter-level meaning beyond what the input schema already provides, although the schema's 'accept' description is already rich.

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 ('Settle') and resource ('a CONTESTED fact slot') plus the human-check prerequisite. It is clear about what the tool does, but it does not explicitly differentiate itself from sibling tools such as memory_fact_set or memory_supersede.

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 capitalized 'CONTESTED' and the phrase 'after checking with the human' give a clear trigger condition: this tool is for resolving contested fact slots only after human input. It provides clear context but stops short of naming alternatives or explicitly saying when not to use it.

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

memory_fact_setA

Assert a canonical fact — insert, confirm, or correct a slot.

A new value at an existing slot supersedes the old (history kept). A conflicting write parks as a contender (action="contested", winner under current) — check with the human, settle via memory_fact_resolve.

authority / distortion_tolerance inherit the slot's labels unless restated.

Returns: {action: inserted|confirmed|superseded|contested, ...record}.

ParametersJSON Schema
NameRequiredDescriptionDefault
valueYesThe value that is canonical NOW.
entityYesThe slot's subject; the (entity, attribute) match is case- and separator-insensitive.
originNoWho asserted it: "user" = the human told you; otherwise "action"/"agent". Omitted records "agent".
episodeNoEpisode handle for attribution.
attributeYesThe slot's attribute.
authorityNoSpeech act of the source: "directive" / "quoted" (doc or third party) / "observation"; "auto" infers.auto
confidenceNoHow sure you are, 0..1.
freshness_classNoHow fast the value rots. "auto" infers the decay rate from the entity kind.auto
distortion_toleranceNo"constraint" = verbatim, pinned in recall; "auto" infers only that.auto

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.6/5.0
Behavior5/5

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

With no annotations provided, the description carries the full burden, and it delivers: it discloses that new values supersede old ones with history kept, that conflicting writes park as contenders with action='contested', that authority and distortion_tolerance inherit slot labels unless restated, and it states the return shape. This goes well beyond a simple mutation one-liner.

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?

The description is front-loaded with the core purpose, followed by two short behavior paragraphs and a return line. Every sentence carries distinct information; there is no filler or repetition of schema content.

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 tool with an output schema and no annotations, the description covers the key behavioral edge cases (supersede vs contest), the resolution path, and the return enum. It could be slightly more explicit about what triggers a 'contested' classification (e.g., conflicting values on the same slot), but overall it is sufficient for an agent to invoke and interpret the tool.

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

Parameters4/5

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

Schema coverage is 100%, so the baseline is 3. The description adds extra meaning to authority and distortion_tolerance by explaining the inheritance behavior, and it clarifies the semantic of 'value' as the canonical NOW. Other parameters are already well-described in the schema.

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

Purpose5/5

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

The description opens with a specific verb and resource: 'Assert a canonical fact — insert, confirm, or correct a slot.' It clearly defines the operation and its three modes, and distinguishes itself from the related resolver by naming memory_fact_resolve as the settlement path for contested writes.

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 provides a clear context for use — asserting or correcting a canonical slot — and gives an explicit alternative when a write comes back contested: 'check with the human, settle via memory_fact_resolve.' It does not, however, state when to prefer this over nearby siblings like memory_store, memory_supersede, or memory_set_add, so it falls short of full when/when-not guidance.

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

memory_forgetA

Forget from one memory store. memory and fact hard-delete (cleanup for junk/test data — no audit trail); world and lesson RETIRE the slot with an audit row, undone by memory_graph_review( action="restore_slot"). For "now wrong, keep history" use memory_fact_set (facts) or memory_supersede (memories) instead.

scope="memory" needs at least one of text/substring/ source/episode/tag, and those OR-combine — ANY match deletes, unlike memory_search's AND. The other scopes need entity.

Returns: {deleted_count | removed, ...}; {error} on bad input.

ParametersJSON Schema
NameRequiredDescriptionDefault
tagNomemory scope: delete entries carrying this tag.
textNomemory scope: delete entries whose text matches this exactly.
scopeYesWhich store to delete from.
entityNofact/world scope: the slot's subject. lesson scope: the task.
sourceNomemory scope: delete entries with this source tag.
episodeNomemory scope: delete entries stamped with this episode id.
attributeNofact/world scope: one slot's attribute; omit to purge the whole entity. lesson scope: the aspect.
substringNomemory scope: delete entries whose text contains this.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A5/5.0
Behavior5/5

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

With no annotations provided, the description carries the full behavioral burden. It discloses that memory/fact entries are hard-deleted with no audit trail, world/lesson slots are retired with audit rows, that retirement is undone via memory_graph_review, and that ANY matching criterion deletes. This is substantial beyond what the schema conveys.

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?

The description is dense but every sentence earns its place: primary action, scope-specific destructive behavior, alternatives, matching semantics, and return/error shape. It is front-loaded with the core purpose and contains 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?

For an 8-parameter, four-scope destructive tool, the description covers scope behavior, conditional parameters, audit implications, undo path, alternatives, and return values. With an output schema present, no critical operational information is missing.

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

Parameters5/5

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

Schema coverage is 100%, but the description adds critical parameter interplay: scope='memory' requires at least one of text/substring/source/episode/tag and these OR-combine, while other scopes require entity. This is exactly the kind of conditional semantics an agent needs and cannot infer from the schema alone.

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

Purpose5/5

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

The description opens with 'Forget from one memory store,' naming a specific verb and resource. It then distinguishes hard-delete vs. retire semantics across scopes and explicitly contrasts with memory_fact_set and memory_supersede, making the tool's purpose clear relative to 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?

It explicitly states when to use alternatives: for 'now wrong, keep history' use memory_fact_set or memory_supersede instead. It also gives scope-specific parameter requirements and contrasts memory_forget's OR-combining matches with memory_search's AND behavior, giving clear selection guidance.

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

memory_getA

Dereference a memory id to the full stored episode plus consolidated_into — the canonical facts it produced. Reading it gently reinforces it. Returns {found: false, faded: true} when the episode has since been forgotten.

ParametersJSON Schema
NameRequiredDescriptionDefault
entry_idYesA memory id, as returned by search results or by a fact's ``source_entries``.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4/5.0
Behavior4/5

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

With no annotations, the description carries the full transparency burden. It responsibly discloses a non-obvious side effect ('Reading it gently reinforces it') and a special forgotten-state return ({found: false, faded: true}). It does not elaborate on invalid-id behavior or exact reinforcement, but for a one-parameter getter this is meaningful disclosure.

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 front-loaded sentences with no filler: the first defines the action and payload, the second captures the relevant side effect and edge case. Every sentence 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?

The definition covers purpose, parameter source, side effect, and the main stale-episode edge case, while the output schema can handle return shape details. It is enough for a low-complexity get-by-id tool; the slight gap is absence of routing to sibling search/recent tools, but that is more a usage-guidance concern.

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?

The only parameter entry_id is already fully described in the schema (memory id from search results or source_entries), so the description adds little parameter-specific meaning. The phrase 'Dereference a memory id' reinforces that the id is a reference, but this is minor; 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 opening verb 'Dereference' plus object 'memory id' and result 'full stored episode plus consolidated_into' states a precise operation. It clearly identifies the tool as id-based retrieval rather than search or fact lookup, even without naming a sibling.

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

Usage Guidelines3/5

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

The description implies the tool should be used when an entry_id is already available ('Dereference a memory id'), but it never names alternatives or says when not to use it (e.g., use memory_search without an id). Thus usage guidance is only implicit.

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

memory_graphA

Read an entity's graph neighborhood: nodes, typed edges, and each node's canonical facts. Transitive/inverse edges arrive pre-derived (marked derived: true with rule provenance).

Returns: {found, entity, nodes, edges, paths}.

ParametersJSON Schema
NameRequiredDescriptionDefault
toNoAlso return the shortest path from ``entity`` to this entity under ``paths``; its nodes are folded into the neighborhood.
depthNoHops from the root. Max 3.
entityYesThe root entity to read out from.
include_factsNoFalse omits each node's canonical facts.
relation_filterNoKeep only edges whose relation contains this substring.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.2/5.0
Behavior4/5

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

With no annotations, the description carries the behavioral burden. It discloses a non-obvious behavior: transitive/inverse edges arrive pre-derived and are marked derived: true with rule provenance. The word 'Read' plus the Returns line also signals a non-mutating query operation.

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 no filler: the action is in the first sentence, the notable derived-edge behavior in the second, and the return contract in the third. Every sentence earns its place and is front-loaded.

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

Completeness4/5

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

Given a rich input schema, an output schema, and a return-shape overview in the description, the tool is adequately documented. A small gap is that the description does not explicitly mention depth/relation-filter behavior, though those are fully covered in the schema.

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 all five parameters. The description does not add parameter-level detail beyond what the schema provides, so the baseline of 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?

The description opens with the specific verb 'Read' and a concrete resource, 'an entity's graph neighborhood,' then enumerates what is included: nodes, typed edges, canonical facts, and paths. This clearly distinguishes it from sibling write/relate/search tools such as memory_graph_relate or memory_search.

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 makes clear this is the read-neighborhood tool: use it when you need an entity's graph neighborhood with nodes, edges, and facts. It does not explicitly exclude alternatives or name a sibling, 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.

memory_graph_relateA

Assert a typed relation between two entities, e.g. ("web-app", "runs-on", "host-1"). Entities auto-create and resolve through aliases; re-asserting an edge bumps its confidence. On a rejected relation, pick a suggestion, fall back to related-to, or grow the vocabulary deliberately via memory_relation_define.

Returns: {src, relation, dst, confidence, warnings} or {error: "unknown_relation", suggestions}.

ParametersJSON Schema
NameRequiredDescriptionDefault
dstYesThe object entity.
srcYesThe subject entity.
originNoWho asserted the edge.
dst_typeNoEntity kind for ``dst``: set when the node is created, or filled in on an existing node that has none.
relationYesFrom the closed registry: ``depends-on``, ``part-of``, ``runs-on``, ``hosts``, ``uses``, ``configures``, ``stores-data-in``, ``related-to``. Separator variants normalise; an unknown name is rejected WITH the closest matches.
src_typeNoEntity kind for ``src``: set when the node is created, or filled in on an existing node that has none.
confidenceNoHow sure you are, 0..1.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.5/5.0
Behavior5/5

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

With no annotations provided, the description carries the full disclosure burden and does so well: it states auto-creation, alias resolution, confidence bumping on re-assertion, rejected-relation handling with fallbacks, and exactly what the return value or error looks like.

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?

The description is compact, front-loaded with the core action, and every sentence adds value. The return format is cleanly separated, making it easy for an agent to parse.

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

Completeness5/5

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

Given the lack of annotations, the description is remarkably complete: it covers accepted relations, fallback behavior, alternative tool, return contract, and error shape. An agent has enough context to invoke this tool correctly without opening the schema.

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 applies. The description reinforces behavioral facts like alias resolution and confidence bumps but does not add much parameter-level meaning beyond what the schema already 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?

The description opens with the specific verb and resource: "Assert a typed relation between two entities," with a concrete example. It clearly distinguishes this from relatives like memory_graph_unrelate and memory_relation_define by showing the assertion action and mentioning vocabulary growth only as a fallback.

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 for using the tool: it asserts relations, auto-creates entities, and handles rejected relations. It explicitly names memory_relation_define as the alternative for expanding vocabulary, though it does not explicitly contrast with memory_graph_unrelate or other sibling tools.

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

memory_graph_reviewA

Work the graph review queue — deep-dream proposals that need a verdict before they touch the graph.

Actions: list: pending findings/proposals. propose: file link proposals for review. relate: related-not-duplicate verdict — writes the relation edge and dismisses the pair. dismiss_pair: mark src/dst genuinely distinct. dismiss_slot_pair: same for lesson/world duplicate listings. restore_slot: undo a lesson/world forget (forgets retire, never delete) — store + src (the retired key). accept_link/reject_link: settle an edge proposal by id. accept_merge: fold a near-duplicate into its twin. accept_junk: delete an over-extraction artifact. reject_entity: keep the entity, dismiss the proposal.

Returns: per-action dict; {error} on bad input.

ParametersJSON Schema
NameRequiredDescriptionDefault
dstNorelate/dismiss_pair: the second entity. dismiss_slot_pair: an "entity|attribute" key from the deep response.
srcNorelate/dismiss_pair: the first entity. dismiss_slot_pair: an "entity|attribute" key from the deep response; restore_slot: retired key or entity.
scopeNolist: keep only findings of this kind.
storeNodismiss_slot_pair / restore_slot: which store the key belongs to — "lesson" or "world".
actionNolist
relationNorelate: the edge relation to write, from the graph vocabulary.
proposalsNopropose: ``[{src, relation, dst, similarity?, rationale?}]``.
proposal_idNoId actions: the one proposal to settle.
proposal_idsNoId actions: settle many proposals in one call, instead of ``proposal_id``.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.5/5.0
Behavior4/5

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

With no annotations, the description carries the behavioral burden and does so well: it discloses that relate writes an edge and dismisses the pair, accept_junk deletes an artifact, restore_slot undoes a forget, and reject_entity keeps the entity. It stops short of stating irreversibility or side effects of every destructive action, but the per-action behavior is substantive.

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?

The description is long because the tool is a multi-action dispatcher with 11 operations, but every bullet earns its place with a compact one-line semantics. The purpose is front-loaded, and the action list is scannable without redundancy.

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, high-parameter tool with no annotations, the description is remarkably complete: it covers every action, notes the return shape ('per-action dict; {error} on bad input'), and relies on the existing output schema for return-value details. No critical calling context is left entirely to inference.

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 89%, so the baseline is 3. The description adds value on top by mapping actions to parameters, such as restore_slot needing store + src, and relate/dismiss_pair using src/dst. It clarifies which parameter combinations matter for which action.

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

Purpose5/5

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

The description clearly identifies a specific responsibility — working the graph review queue for deep-dream proposals requiring a verdict before graph mutation. Each action is explicitly named with a one-line purpose, which disambiguates this from direct graph-editing siblings like memory_graph_relate and memory_graph_unrelate.

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 tool handles pending proposals/findings that need a verdict. It does not explicitly name alternatives or state when not to use it, but the action list and 'before they touch the graph' framing make the intended usage obvious.

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

memory_graph_unrelateA

Retract a relation — the edge is marked superseded (kept for audit) and leaves memory_graph results. Re-asserting the same triple later revives it.

ParametersJSON Schema
NameRequiredDescriptionDefault
dstYesThe edge's object entity.
srcYesThe edge's subject entity.
relationYesThe edge's relation.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.4/5.0
Behavior5/5

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

With no annotations provided, the description carries the full burden, and it does so excellently. It discloses that the edge is not deleted but marked superseded, remains available for audit, exits memory_graph results, and can be revived by re-asserting the triple. This gives the agent a clear model of the tool's effects.

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?

The description is compact and front-loaded, with the core action in the first two words. The dash and second sentence efficiently convey the audit and revival behavior without wasted words.

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?

The tool is simple with three required string parameters, an output schema is present, and the description explains the essential behavioral outcomes: removal from active results, audit retention, and revival on re-assertion. It could additionally mention behavior when the triple does not exist, but this 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?

The input schema has 100% description coverage for src, relation, and dst. The description adds the concept of a 'triple,' which reinforces how the parameters combine, but it does not add detailed parameter semantics beyond what the schema already provides. The baseline of 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?

The description opens with a specific verb and resource: 'Retract a relation.' It clearly states the behavior: the edge is marked superseded, kept for audit, and removed from memory_graph results. It also distinguishes itself from related operations like memory_graph_relate by describing the retraction and revival semantics.

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 for when to use the tool: when a relation should be removed from active memory_graph results while preserving it for audit. It does not explicitly name alternatives such as memory_forget or memory_supersede, but the use case is unambiguous.

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

memory_historyA

Read an entity's past. SLOT mode (attribute given): every version of that canonical fact slot, oldest→newest, each with writer/session, tx/valid time, and age ("what did this used to be? who set it?") — compaction thins chains past ~30d. CHAIN mode (attribute omitted): the entity's dated fact/entry/edge/lesson events merged oldest→newest ("what led to X?").

Returns: {entity, attribute, count, versions} (slot mode) or {found, entity, count, events} (chain mode).

ParametersJSON Schema
NameRequiredDescriptionDefault
as_ofNoSlot mode only: ISO-8601 or epoch seconds; returns only versions written by then.
entityYesThe subject whose past to read.
attributeNoThe fact slot to read; omit for chain mode.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.3/5.0
Behavior4/5

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

With no annotations provided, the description carries the full disclosure burden. It does well by stating it is a read operation, disclosing compaction behavior ('compaction thins chains past ~30d'), and describing the result contents and ordering. It does not mention auth, rate limits, or error behavior, but for a history read tool the key behavioral caveat (data loss via compaction) is clearly surfaced.

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?

The description is dense but well structured: a one-line summary, two clearly labeled modes with examples, and a concise return-format breakdown. The most important usage distinction is front-loaded, and every sentence contributes either mode semantics, ordering, or data-retention caveats.

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

Completeness5/5

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

For a dual-mode read tool with a moderate parameter set and no annotations, the description is complete: it explains both modes, the as_of semantics are already in the schema, returns are specified, ordering is explicit, and the compaction caveat is disclosed. An agent has enough context to invoke this tool correctly and interpret its results.

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 reinforces the 'attribute' toggling behavior and explains the mode-dependent return object, but it does not add substantial meaning beyond what the schema already states for entity, attribute, and as_of. The extra context is mostly behavioral rather than parameter-specific.

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

Purpose5/5

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

The description opens with a specific verb and resource, 'Read an entity's past,' and then clearly differentiates the two modes (SLOT vs CHAIN) with concrete examples. This distinguishes it from sibling tools like memory_get or memory_search, which read current or searched facts rather than historical versions.

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 explicit mode-selection guidance: provide 'attribute' for SLOT mode and omit it for CHAIN mode, with a clear semantic purpose for each ('what did this used to be?' vs 'what led to X?'). It does not name sibling alternatives or state when not to use this tool, so it falls just 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.

memory_outcomeA

Record a procedural outcome — what worked, failed, or was corrected. Dream synthesises signals into lessons surfaced next session; logging stops repeated mistakes.

Returns: {recorded, signal_id, task, outcome}; needs Postgres.

ParametersJSON Schema
NameRequiredDescriptionDefault
taskYesKind of task, in stable wording ("deploy engine to host") so signals for the same work group.
aboutNoThe tool or approach concerned; aids traversal.
detailNoWhat worked, or what the dead-end was.
episodeNoEpisode handle for attribution.
outcomeYesWhat happened.
polarityNo"+" do-this or "-" avoid; usually omit — it is inferred from the outcome.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.2/5.0
Behavior4/5

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

With no annotations, the description must carry the behavioral burden, and it does by noting that logged outcomes feed Dream's next-session lessons and that the operation "needs Postgres." It also discloses the return shape. It does not discuss idempotency, permissions, or failure behavior, but for a simple logging write this is reasonable 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?

The description is two sentences with no filler; the primary action and scope are front-loaded, followed by downstream behavior and a concise dependency/return note. 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?

The description covers what the tool records, why it matters, what it returns, and its Postgres dependency, while the schema covers all parameter semantics. It does not spell out preconditions such as an active episode, so for a moderate-complexity logging tool it is nearly complete 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?

All six parameters already have descriptive schema entries, so the schema does the heavy lifting; the description adds no additional guidance beyond the return sample containing task and outcome. Baseline 3 applies because the coverage is 100% and the description neither harms nor enriches parameter understanding.

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 opening line, "Record a procedural outcome — what worked, failed, or was corrected," names a specific action and resource and narrows the tool's scope to procedural outcomes rather than general facts. This clearly separates it from siblings like memory_store and memory_reinforce without restating the tool name.

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 supplies clear context for when to call it: after a procedural attempt, so that "Dream synthesises signals into lessons surfaced next session" and "logging stops repeated mistakes." It does not name alternative tools or state when not to use it, so it stops one step 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.

memory_recallA

Multi-hop retrieval over the knowledge graph, for RELATIONAL questions whose answer is reached by following links — "what does X ultimately run on?", "how does A reach C?" — which single-shot memory_search can't chain. Read-only. low_confidence: true means no seed entity matched — fall back to memory_search.

Returns: {seeds, entities, edges, paths, texts, iterations}. entities/edges/texts are capped (currently 10/15/6) with a per-hop reservation, so a hub seed's own 1-hop ring can't crowd out the deeper hops the walk exists to reach; edges prefers links between surviving entities; each entity's facts is capped (currently 5). A fact carrying re_verify stands on a memory that has since been corrected — the value still stands, but check it before acting. A seed entity's constraint facts come first, marked pinned. Details: docs/guide/retrieval.md.

ParametersJSON Schema
NameRequiredDescriptionDefault
hopsNoMax graph hops. Clamped to 1..5.
queryYesNatural-language relational question; its top hits seed the graph walk.
top_kNoBounds only the SEED search (the initial hits that name the walk's start entities), not the result, which is capped separately; up to 3 ``texts`` slots go to seed hits.
verboseNoFull fact/edge provenance and untruncated texts. Default facts are ``{attribute, value}``, edges ``{src, relation, dst}``, texts truncated to a preview.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.6/5.0
Behavior5/5

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

With no annotations, the description carries full responsibility. It discloses read-only status, the low_confidence failure signal, result caps with per-hop reservation rationale, edge preference behavior, the re_verify flag meaning, and pinned constraint facts. This goes far beyond what the schema conveys.

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

Conciseness4/5

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

The description is front-loaded with purpose and routing, then layers behavioral detail. It is dense but each sentence adds meaningful information; the only slight demerit is that the cap details could arguably live in the output schema or docs, though their inclusion does help an agent interpret results safely.

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 retrieval tool with no annotations and a nontrivial output shape, the description covers when to use, when not to, failure semantics, result structure, caps, and data-quality caveats. It also points to detailed docs for deeper reading. 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 the baseline is 3. The tool description adds context about result caps that indirectly clarify top_k's role, but the schema already explains that top_k bounds only the seed search. The description doesn't need to compensate further.

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

Purpose5/5

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

The description opens with a precise verb+resource pairing: multi-hop retrieval over the knowledge graph for relational questions. It gives concrete example questions and explicitly contrasts itself with memory_search, making the tool's identity unmistakable even among 30+ 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?

It states exactly when to use this tool (relational questions requiring link-following, which single-shot memory_search can't chain) and provides an explicit fallback rule: 'low_confidence: true' means no seed entity matched — fall back to memory_search. This is model guidance for tool selection.

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

memory_recentA

List the N most recently stored memories, newest first — timestamp order, not relevance. Useful for "what did I just store?" and for catching up at the start of a session. The sources/episodes/ tags filters AND-combine.

ParametersJSON Schema
NameRequiredDescriptionDefault
nNoHow many entries to return.
tagsNoKeep only entries carrying one of these tags.
sourcesNoKeep only entries with one of these source tags.
verboseNoFull per-entry metadata; default entries are compact.
episodesNoKeep only entries stamped with one of these episode ids.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.5/5.0
Behavior4/5

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

With no annotations, the description carries the behavioral disclosure burden. It reveals key behaviors: newest-first ordering, timestamp-based rather than relevance-based ordering, and AND-combination of filters. It does not describe return-value details, but an output schema exists to cover that.

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 tightly written sentences with no filler: behavior first, use cases second, filter semantics last. Every sentence contributes information an agent needs.

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 an optional-parameter list tool, this is complete: it gives use cases, ordering semantics, and filter combination behavior. All parameters are self-documented in the schema, and an output schema exists for return-value details.

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 the baseline is 3. The description adds value beyond the schema by clarifying that sources, episodes, and tags AND-combine, and by establishing the ordering semantics that affect how the n parameter is interpreted.

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

Purpose5/5

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

The description clearly states a specific verb and resource: 'List the N most recently stored memories, newest first.' It also distinguishes itself from relevance-based search by explicitly saying 'timestamp order, not relevance,' which separates it from sibling tools like memory_search.

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 concrete use cases: 'what did I just store?' and catching up at the start of a session. It does not explicitly name an alternative tool for relevance search, but 'not relevance' implies the contrast, so the guidance is clear but not fully explicit.

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

memory_reinforceA

Strengthen one memory after reading it via memory_get and finding it genuinely useful — a deliberate "this mattered" signal that helps it resist forgetting. Read first, then reinforce.

ParametersJSON Schema
NameRequiredDescriptionDefault
entry_idYesThe id of the memory to strengthen.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.9/5.0
Behavior3/5

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

No annotations are provided, so the description carries the full burden. It explains the behavior and effect (strengthening, resisting forgetting) and the required sequence. However, it does not disclose error behavior, idempotency, or whether repeated reinforcement has cumulative effects, which leaves some uncertainty.

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

Conciseness4/5

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

The description is two sentences, front-loaded with the core purpose and no unnecessary fluff. The closing 'Read first, then reinforce' slightly restates an earlier point, but it emphasizes the important ordering rule and keeps the whole description tight.

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-parameter tool with an output schema present, the description provides the essential purpose, the precondition, and the behavioral effect. It could mention edge cases like invalid entry_id or repeated calls, but nothing critical is missing for an agent deciding whether and how to use it.

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%: the single parameter entry_id is already described as 'The id of the memory to strengthen.' The description adds the hint that the id likely comes from memory_get, but this is minor and the schema does the heavy lifting, 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?

The description clearly states the specific action ('Strengthen one memory'), the precondition ('after reading it via memory_get'), and the intent ('this mattered' signal that helps resist forgetting). This differentiates it from siblings like memory_get, memory_search, memory_store, and memory_forget.

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 explicitly says when to use the tool: after reading the memory via memory_get and finding it genuinely useful. The instruction 'Read first, then reinforce' provides a clear ordering rule. It doesn't spell out exclusions, but the precondition gives strong guidance.

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

memory_relation_defineA

Add a relation to the closed graph vocabulary — a deliberate, rare act. Prefer the builtins; define one only when a recurring connection genuinely fits none of them.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYesThe new relation name, hyphenated like the builtins.
dst_typeNoSoft entity-kind expectation for the object; a mismatch warns, never rejects.
src_typeNoSoft entity-kind expectation for the subject; a mismatch warns, never rejects.
inverse_ofNoPair with an existing relation, as ``runs-on`` is the inverse of ``hosts``.
transitiveNoTrue closes the relation transitively, so chained edges arrive pre-derived.
descriptionYesWhat the relation means, for later readers.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.7/5.0
Behavior3/5

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

With no annotations, the description carries the burden of behavioral disclosure. It does convey that this is a 'deliberate, rare act' within a 'closed' vocabulary, implying persistence and caution. However, it does not state whether the operation is reversible, what system-wide effects it has, or whether it affects existing graph relations. The warning semantics in the schema are useful but separate from the description.

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?

The description is two sentences with no filler. The first sentence states the action and its gravity; the second sentence gives the usage rule. It is front-loaded and every phrase earns its place.

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?

The description gives a strong rationale and selection criterion but omits side-effect details such as reversibility, effect on existing graph queries, or relation to sibling tools like memory_graph_relate. The output schema covers return values, so that absence is acceptable, but broader operational context is still somewhat thin.

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 each parameter, including optional soft type expectations and inverse_of, is already well described in the input schema. The description does not add parameter-level meaning beyond what the schema provides, so the baseline score of 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 action: 'Add a relation to the closed graph vocabulary' and clarifies that this means defining a new relation type, not creating an edge. It is distinguishable from sibling tools like memory_graph_relate, though it does not explicitly name them. The 'define one' phrasing reinforces the vocabulary-level purpose.

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 a clear decision rule: 'Prefer the builtins; define one only when a recurring connection genuinely fits none of them.' This tells the agent when to use the tool and when to avoid it. However, the alternative is referred to as 'builtins' rather than naming a specific sibling tool or concrete exclusionary condition.

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

memory_session_titleA

Name THIS session's auto-opened episode (default titles are generic). Call once at the start of work so session recaps read meaningfully. Idempotent; call again to rename.

ParametersJSON Schema
NameRequiredDescriptionDefault
titleYesWhat this session is about, e.g. "Pseudolife-MCP" or "auth-refactor".
episodeNoYour session handle — names that session's root directly (the identity a hook-registered client has).

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.4/5.0
Behavior4/5

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

With no annotations, the description carries the full burden, and it does so by disclosing idempotency, renamability, and the effect on session recaps. It could add more detail about whether a custom title fully replaces the prior one or how the episode handle is resolved, but the core behavior is clear.

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, all informative, with no fluff. The action and timing are front-loaded, and the idempotency is stated compactly without 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?

Complete for a simple setter: it covers when to call, repeat-call behavior, and why it matters. The optional episode parameter and output schema fill remaining context, so nothing critical 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 explains title and episode well; the description only adds usage context, not param-level detail. Baseline 3 is appropriate because 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?

The description uses a specific imperative ('Name THIS session's auto-opened episode'), identifies the object being modified, and contrasts with generic defaults. It clearly differentiates from siblings like memory_episode_summary or memory_episode_start by targeting the session title specifically.

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 says to call once at the start of work and that calling again renames, giving both timing and repeat behavior. It also explains why the call matters ('so session recaps read meaningfully'), which helps an agent decide when the tool is relevant.

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

memory_set_addA

Add/confirm a member of a set-valued slot (many concurrent values, not one NOW value). A scalar there converts to a set on first call — one-way — except number-led scalars ("32", "$1,500"), which are protected: the add parks as a contender (action="contested", settle via memory_fact_resolve). Read with memory_fact_get.

Returns: {action, entity, attribute, member, members_count}.

ParametersJSON Schema
NameRequiredDescriptionDefault
entityYesThe slot's subject.
memberYesThe member to add or re-confirm.
attributeYesThe slot's attribute.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.9/5.0
Behavior5/5

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

No annotations are provided, so the description carries the safety and side-effect burden. It discloses the one-way scalar-to-set conversion, the protection of number-led scalars, and the 'contested' outcome with resolution path. It also states the exact 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.

Conciseness5/5

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

Four compact sentences with no filler; the purpose is front-loaded and each sentence carries distinct information: operation, conversion caveat, read route, and return shape.

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 an output schema present, the description does not need to explain return values, and it still gives the return shape. It covers when to use, edge cases, resolution steps, and a read alternative. There is no missing information an agent needs to invoke the tool safely.

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 input schema already describes all three parameters with 100% coverage, so the baseline applies. The description adds meaningful context beyond the schema by explaining the set-slot concept, conversion behavior, and what happens to protected scalar members. It does not add much per-field format detail, but it clarifies how `member` may be interpreted.

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 operation: 'Add/confirm a member of a set-valued slot', and explicitly contrasts with scalar 'NOW value'. This distinguishes the tool from related memory tools such as memory_store and memory_set_remove. The edge-case behavior for number-led scalars adds clarity without ambiguity.

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?

Tells agents when it applies: set-valued slots with 'many concurrent values', and says it is not for 'one NOW value'. It names alternatives explicitly: read via memory_fact_get and settle contested adds via memory_fact_resolve. This is enough to route an agent to the correct sibling.

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

memory_set_removeA

Retract one current set member (audit row kept). Read with memory_fact_get.

Returns: {action, entity, attribute, member, members_count}.

ParametersJSON Schema
NameRequiredDescriptionDefault
entityYesThe slot's subject.
memberYesThe current member to retract.
attributeYesThe slot's attribute.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4/5.0
Behavior3/5

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

No annotations are present, so the description carries the full burden. It usefully discloses that an audit row is kept and that the return includes members_count, but it does not cover behavior when the member is absent, reversibility, or other edge cases.

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?

The description is compact and front-loaded: purpose, audit behavior, read-after hint, and return shape all appear in a few short lines with 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 simple three-parameter mutation with full schema coverage and a stated return shape, the description is nearly sufficient. A note on missing-member behavior or an example would make it fully complete, but nothing essential is missing for correct invocation.

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 each parameter already has a clear description such as 'The current member to retract' and 'The slot's attribute'. The tool description adds little parameter-specific meaning 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 opens with an active verb and resource: 'Retract one current set member', which precisely states what the tool does. It distinguishes itself from siblings like memory_set_add and memory_fact_set, and the parenthetical 'audit row kept' adds an important clarifying detail.

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 intended use is clear: removing an existing member from a set. The instruction 'Read with memory_fact_get' names the natural follow-up tool, but it does not explicitly state when not to use this tool or directly contrast it with memory_set_add.

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

memory_statsA

Memory-bank vital signs: store occupancy vs capacity, hit rates, true-drop count, and totals. Use to gauge how much has been remembered or to diagnose why retrieval feels off.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.2/5.0
Behavior3/5

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

With no annotations, the description must carry the safety/behavior burden. It implies a pure read operation by describing 'vital signs' and statistics, but it never explicitly states that the tool does not modify memory. The listed metrics do add useful behavioral context about what the call reports.

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?

The description is compact and well-structured: a front-loaded summary label, the specific metrics, then two concrete use cases. Every sentence earns its place and there is no redundant 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 no-parameter, output-schema-backed diagnostic stat list, the description covers the main invocation purposes and the categories of returned information. Additional details like time window or persistence would be nice, but the output schema can supply those where needed.

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 has zero parameters, so the input schema leaves nothing to explain. The baseline for no parameters is 4, and the description appropriately emphasizes what the response/statistics reveal rather than parameters that do not exist.

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

Purpose5/5

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

The description clearly defines the tool as a memory-bank statistics reader: it lists the exact metrics returned (occupancy vs capacity, hit rates, true-drop count, totals). This distinguishes it from content-focused siblings like memory_search or memory_get and states the diagnostic role rather than simply restating the name.

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 explicit use cases: 'gauge how much has been remembered' and 'diagnose why retrieval feels off.' It does not name alternative tools or say when not to use it, but the context is clear enough for an agent to select this tool over the sibling lookup/management tools.

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

memory_storeA

Store one durable fact, decision, or observation. Use proactively for anything worth keeping — one claim per call, and decide which kind it is: PERSIST what stays true and will be wanted back; leave task-scoped detail in CONTEXT ONLY; RE-VERIFY a fast-changing value at its source, parking it with memory_fact_set(..., freshness_class="volatile") rather than persisting a stale one; ASK when the claim is ambiguous instead of persisting the guess. Near-duplicates are dropped, not erred (stored=False, reason="below_surprise_threshold"). For canonical NOW use memory_fact_set.

Returns: {stored, surprise, reason, cortex_promoted}.

ParametersJSON Schema
NameRequiredDescriptionDefault
tagsNoOptional labels, e.g. ["decision", "blocker"].
textYesThe claim to remember.
originNoWho asserted the claim.
sourceNoStable per-project/topic tag for later filtering.agent
episodeNoEpisode handle for attribution.
authorityNoSpeech act: "directive" (an instruction to you) / "quoted" (a doc or third party said it) / "observation"; "auto" infers.auto
distortion_toleranceNo"constraint" = must survive verbatim, pinned in recall; "auto" infers only that.auto

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.7/5.0
Behavior5/5

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

With no annotations provided, the description carries the full burden of behavioral disclosure. It explains that near-duplicates are dropped rather than errored, with stored=False and reason="below_surprise_threshold", and it lists the return shape. This is unusually transparent for a storage tool.

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

Conciseness5/5

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

The description is dense but every sentence earns its place: core action, usage policy, decision rules, edge behavior, and canonical alternative. The structure front-lodes the action and then layers policy and behavior logically.

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

Completeness5/5

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

Given that an output schema exists and all parameters are already documented, the description covers the remaining context an agent needs: when to use it, how to classify claims, what happens to near-duplicates, and which sibling to use for canonical facts. Nothing critical 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 baseline is 3. The description does not add much per-parameter detail beyond the schema, though it does clarify the intended semantic of 'text' as a single claim and mentions freshness_class for memory_fact_set. That is useful but not parameter-specific enough to push higher.

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

Purpose5/5

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

The description opens with a specific verb and resource: "Store one durable fact, decision, or observation." It clearly differentiates itself from the sibling memory_fact_set by saying "For canonical NOW use memory_fact_set", so an agent can distinguish this tool without needing to open schemas.

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

Usage Guidelines5/5

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

The description gives explicit usage policy: use proactively for anything worth keeping, one claim per call, and a clear decision framework (PERSIST vs CONTEXT ONLY vs RE-VERIFY vs ASK). It also names the alternative memory_fact_set for volatile values and for canonical NOW, which is strong when-to-use and when-not-to-use guidance.

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

memory_supersedeA

Mark a stored memory obsolete and record its replacement. The old entry is kept but flagged superseded, so retrieval ranks the correction higher and shows both together.

Returns: {superseded_count, superseded_texts, new_memory_stored, derived_flagged} — the last being the canonical facts the dream built on the memories just corrected. They are FLAGGED, never rewritten; check each and re-assert the ones that moved. Each row carries has_current_value: false means the slot holds no current fact any more — blast radius worth seeing, but nothing to go re-check. The list is capped, live slots first; derived_flagged_truncated / derived_flagged_total say when a correction reached further than the cap.

ParametersJSON Schema
NameRequiredDescriptionDefault
new_textYesThe replacement claim; stored fresh.
old_textYesThe memory now obsolete. Matched exact-text first, then by nearest embedding — a close paraphrase works.

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.5/5.0
Behavior5/5

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

With no annotations provided, the description carries the full disclosure burden and does so thoroughly. It reveals that the old entry is kept, not deleted; that derived facts are flagged and never rewritten; that rows carry has_current_value; and that results are capped with truncation indicators.

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?

The description is front-loaded with the core action, then provides dense but purposeful detail about return semantics. Every sentence adds useful information about behavior, flagging, or truncation; there is 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?

Given the tool's complexity, the description is remarkably complete: it covers matching behavior via the schema, old-entry retention, derived-flag semantics, has_current_value meaning, and truncation reporting. An agent has enough context to invoke this correctly and interpret its result.

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 parameters old_text and new_text are already fully documented in the schema. The tool description itself adds no parameter-specific 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.

Purpose5/5

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

The description opens with a specific verb and resource: 'Mark a stored memory obsolete and record its replacement.' It clearly distinguishes supersede from siblings like memory_forget or memory_store by explaining the old entry is kept but flagged, and retrieval ranks the correction higher.

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 makes the usage context clear: use this when an existing memory is obsolete and a replacement should be recorded, with the old entry preserved for context. It does not explicitly name alternatives or when-not-to-use conditions, 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.

memory_toolsetA

Adjust YOUR visible toolset, one tier at a time (minimal → core → full; scoped to your credential/writer identity, free, instant). Core adds graph/recall, world facts, lessons, documents; full adds supersede/forget/history, dream and graph-review admin. status reports the ladder. Expand first: clients reject hidden-tool calls.

ParametersJSON Schema
NameRequiredDescriptionDefault
actionYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.7/5.0
Behavior5/5

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

No annotations exist, so the description carries the full behavioral burden. It discloses identity scoping ('scoped to your credential/writer identity'), cost and latency ('free, instant'), and the operational consequence of hidden tools ('clients reject hidden-tool calls'). It also specifies exactly which capability groups each tier unlocks.

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 dense sentences front-load the purpose and then add only high-value details: tier contents, status behavior, and expansion warning. There is no filler or redundant restatement of the schema.

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 one-action tool with an output schema, this description is complete. It defines the tier model, the three action semantics, identity scoping, and the operational warning about hidden-tool calls. An agent can decide to expand, collapse, or check status without needing further documentation.

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 schema has one enum parameter with 0% description coverage, so the description compensates by explaining 'expand' (move up the ladder) and 'status' ('reports the ladder'). 'Collapse' is left to inference from 'one tier at a time' and the minimal→core→full ordering, but the word and direction make it sufficiently clear.

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 the exact verb and resource: 'Adjust YOUR visible toolset, one tier at a time.' It enumerates tier contents and actions, making clear this is a toolset-management tool, not a memory-content operation like any sibling memory_* or document_* tool. The purpose is unambiguous and distinct.

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?

Provides an explicit precondition: 'Expand first: clients reject hidden-tool calls,' which tells the agent when to use this tool. It also explains that 'status reports the ladder' as a diagnostic use. It doesn't explicitly state when to collapse or name alternative tools, but no sibling tool is a substitute, so the context is clear.

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

memory_world_setA

Assert a canonical WORLD fact — sourced EXTERNAL knowledge (versions, prices, who-holds-a-role, research findings), kept separate from user/project facts. Route verified web/docs findings here, with the citation. A newer source supersedes an older value at the same slot.

Returns: {action: inserted|confirmed|superseded|rejected, ...record}.

ParametersJSON Schema
NameRequiredDescriptionDefault
valueYesThe externally-sourced value.
entityYesThe slot's subject.
attributeYesThe slot's attribute.
confidenceNoSource confidence, 0..1.
source_urlNohttp(s) citation URL; any other scheme is rejected.
content_hashNoHash of the fetched source, for change detection.
retrieved_atNoEpoch seconds the source was fetched.
source_quoteNoThe 1-2 sentences the claim was extracted from.
freshness_classNoTrust decay applied at read time: ``evergreen`` never decays, ``slow`` is months, ``volatile`` is weeks.volatile

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.4/5.0
Behavior4/5

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

With no annotations provided, the description carries the full behavioral burden. It discloses the critical side-effect that 'a newer source supersedes an older value at the same slot' and reveals the action vocabulary returned (inserted, confirmed, superseded, rejected). This is meaningful write-semantics disclosure beyond the schema, though it does not cover every edge case such as rejection triggers.

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?

The description is compact, front-loaded with the core purpose, and each sentence earns its place: what the tool is for, when to use it, what behavior to expect, and what it returns. There is no filler or redundant restatement of schema details.

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 tool with no annotations, the description provides the essential operating model: external world facts, separation from user facts, citation requirement, supersession behavior, and return shape. The output schema covers return details and the input schema covers parameter descriptions, so the remaining gap is mainly the lack of explicit alternative tool routing.

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 semantic glue: 'with the citation' reinforces the role of source_url/source_quote, and the supersede rule gives meaning to retrieved_at and freshness_class. It doesn't restate individual field descriptions, which is appropriate given the schema already documents them.

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 and resource: 'Assert a canonical WORLD fact' sourced from EXTERNAL knowledge. It also clearly scopes the tool to external/world facts as opposed to user/project facts, which differentiates it from sibling memory tools. The listing of example knowledge types (versions, prices, role-holders, research findings) makes the purpose concrete.

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 usage context: route verified web/docs findings here, with a citation, for externally-sourced knowledge. It implicitly excludes user/project facts by saying this is 'kept separate' from them, but it does not explicitly name sibling alternatives or state a when-not-to-use rule.

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. 33 tool updatesv0.15.0
    • Changeddocument_ingest2 fields changed
      • addedInput schema / properties / path / description
        Added value: +"Path to a .txt / .md / .pdf file, resolved on the SERVER's filesystem — with the Docker daemon, a path visible inside the container (e.g. a mounted volume), not a host path."
      • addedInput schema / properties / source / description
        Added value: +"Source tag for the chunks; defaults to the filename."
    • Changeddocument_search2 fields changed
      • addedInput schema / properties / query / description
        Added value: +"Natural-language description of the passage wanted."
      • addedInput schema / properties / top_k / description
        Added value: +"Max chunks returned."
    • Changedmemory_alias2 fields changed
      • addedInput schema / properties / alias / description
        Added value: +"The alternative name."
      • addedInput schema / properties / entity / description
        Added value: +"The canonical entity to bind onto."
    • Changedmemory_consolidate4 fields changed
      • addedInput schema / properties / new_text / description
        Added value: +"The canonical note that replaces them."
      • addedInput schema / properties / replaces / description
        Added value: +"The memories being folded in; each is matched by exact text or close paraphrase."
      • addedInput schema / properties / source / description
        Added value: +"Source tag for the new note."
      • addedInput schema / properties / tags / description
        Added value: +"Labels for the new note."
    • Changedmemory_consolidation_candidates8 fields changed
      • addedInput schema / properties / episode / description
        Added value: +"Session-driven anchor: cluster within this episode id."
      • addedInput schema / properties / max_clusters / description
        Added value: +"Max clusters returned."
      • addedInput schema / properties / min_cluster_size / description
        Added value: +"Drop clusters with fewer members than this."
      • addedInput schema / properties / min_cohesion / description
        Added value: +"Minimum intra-cluster cosine — raise it to flag only near-duplicates."
      • addedInput schema / properties / query / description
        Added value: +"Topic-driven anchor: cluster memories near this description."
      • addedInput schema / properties / sources / description
        Added value: +"Consider only entries with one of these source tags."
      • addedInput schema / properties / tags / description
        Added value: +"Consider only entries carrying one of these tags."
      • addedInput schema / properties / top_k / description
        Added value: +"How many candidate entries to cluster over."
    • Changedmemory_dream5 fields changed
      • addedInput schema / properties / apply / description
        Added value: +"deep: True writes the consolidation (graph tables are snapshotted first); the default is a dry run."
      • addedInput schema / properties / cursor / description
        Added value: +"commit: the newest pulled timestamp. Required for that action."
      • addedInput schema / properties / limit / description
        Added value: +"pull/run: how many memories to process (pull defaults to 40). runs: how many passes to list (defaults to 10)."
      • addedInput schema / properties / run_id / description
        Added value: +"rollback: which pass to revert; defaults to the newest committed pass."
      • addedInput schema / properties / snippets / description
        Added value: +"deep: False omits the evidence snippets."
    • Changedmemory_episode_end1 field changed
      • addedInput schema / properties / episode
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Your session handle — pops only within your own session's subtree; the session root is never closed.",
        +  "title": "Episode"
        +}
    • Changedmemory_episode_start3 fields changed
      • addedInput schema / properties / episode
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Your session handle (from the session-start briefing) — anchors the sub-episode to YOUR session when several run concurrently.",
        +  "title": "Episode"
        +}
      • addedInput schema / properties / hint / description
        Added value: +"Optional note on what the task is about."
      • addedInput schema / properties / title / description
        Added value: +"Short name for the task, used in later recaps."
    • Changedmemory_episode_summary1 field changed
      • addedInput schema / properties / id / description
        Added value: +"An episode id, as it appears on search/recent results."
    • Changedmemory_fact_get2 fields changed
      • addedInput schema / properties / attribute / description
        Added value: +"The slot's attribute."
      • addedInput schema / properties / entity / description
        Added value: +"The slot's subject; the (entity, attribute) match is case- and separator-insensitive."
    • Changedmemory_fact_resolve3 fields changed
      • addedInput schema / properties / accept / description
        Added value: +"True adopts the parked contender as the new current value (the old value is kept as history); False discards the contender and keeps the current value."
      • addedInput schema / properties / attribute / description
        Added value: +"The contested slot's attribute."
      • addedInput schema / properties / entity / description
        Added value: +"The contested slot's subject."
    • Changedmemory_fact_set9 fields changed
      • addedInput schema / properties / attribute / description
        Added value: +"The slot's attribute."
      • addedInput schema / properties / authority
        Added value: +{
        +  "default": "auto",
        +  "description": "Speech act of the source: \"directive\" / \"quoted\" (doc or third party) / \"observation\"; \"auto\" infers.",
        +  "enum": [
        +    "auto",
        +    "directive",
        +    "observation",
        +    "quoted"
        +  ],
        +  "title": "Authority",
        +  "type": "string"
        +}
      • addedInput schema / properties / confidence / description
        Added value: +"How sure you are, 0..1."
      • addedInput schema / properties / distortion_tolerance
        Added value: +{
        +  "default": "auto",
        +  "description": "\"constraint\" = verbatim, pinned in recall; \"auto\" infers only that.",
        +  "enum": [
        +    "auto",
        +    "constraint",
        +    "procedural",
        +    "belief",
        +    "preference",
        +    "episodic"
        +  ],
        +  "title": "Distortion Tolerance",
        +  "type": "string"
        +}
      • addedInput schema / properties / entity / description
        Added value: +"The slot's subject; the (entity, attribute) match is case- and separator-insensitive."
      • addedInput schema / properties / episode / description
        Added value: +"Episode handle for attribution."
      • addedInput schema / properties / freshness_class / description
        Added value: +"How fast the value rots. \"auto\" infers the decay rate from the entity kind."
      • addedInput schema / properties / origin / description
        Added value: +"Who asserted it: \"user\" = the human told you; otherwise \"action\"/\"agent\". Omitted records \"agent\"."
      • addedInput schema / properties / value / description
        Added value: +"The value that is canonical NOW."
    • Changedmemory_forget8 fields changed
      • addedInput schema / properties / attribute / description
        Added value: +"fact/world scope: one slot's attribute; omit to purge the whole entity. lesson scope: the aspect."
      • addedInput schema / properties / entity / description
        Added value: +"fact/world scope: the slot's subject. lesson scope: the task."
      • addedInput schema / properties / episode / description
        Added value: +"memory scope: delete entries stamped with this episode id."
      • addedInput schema / properties / scope / description
        Added value: +"Which store to delete from."
      • addedInput schema / properties / source / description
        Added value: +"memory scope: delete entries with this source tag."
      • addedInput schema / properties / substring / description
        Added value: +"memory scope: delete entries whose text contains this."
      • addedInput schema / properties / tag / description
        Added value: +"memory scope: delete entries carrying this tag."
      • addedInput schema / properties / text / description
        Added value: +"memory scope: delete entries whose text matches this exactly."
    • Changedmemory_get1 field changed
      • addedInput schema / properties / entry_id / description
        Added value: +"A memory id, as returned by search results or by a fact's ``source_entries``."
    • Changedmemory_graph5 fields changed
      • addedInput schema / properties / depth / description
        Added value: +"Hops from the root. Max 3."
      • addedInput schema / properties / entity / description
        Added value: +"The root entity to read out from."
      • addedInput schema / properties / include_facts / description
        Added value: +"False omits each node's canonical facts."
      • addedInput schema / properties / relation_filter / description
        Added value: +"Keep only edges whose relation contains this substring."
      • addedInput schema / properties / to / description
        Added value: +"Also return the shortest path from ``entity`` to this entity under ``paths``; its nodes are folded into the neighborhood."
    • Changedmemory_graph_relate7 fields changed
      • addedInput schema / properties / confidence / description
        Added value: +"How sure you are, 0..1."
      • addedInput schema / properties / dst / description
        Added value: +"The object entity."
      • addedInput schema / properties / dst_type / description
        Added value: +"Entity kind for ``dst``: set when the node is created, or filled in on an existing node that has none."
      • addedInput schema / properties / origin / description
        Added value: +"Who asserted the edge."
      • addedInput schema / properties / relation / description
        Added value: +"From the closed registry: ``depends-on``, ``part-of``, ``runs-on``, ``hosts``, ``uses``, ``configures``, ``stores-data-in``, ``related-to``. Separator variants normalise; an unknown name is rejected WITH the closest matches."
      • addedInput schema / properties / src / description
        Added value: +"The subject entity."
      • addedInput schema / properties / src_type / description
        Added value: +"Entity kind for ``src``: set when the node is created, or filled in on an existing node that has none."
    • Changedmemory_graph_review9 fields changed
      • changedInput schema / properties / action / enum
        Previous value: -[
        -  "list",
        -  "propose",
        -  "relate",
        -  "dismiss_pair",
        -  "dismiss_slot_pair",
        -  "accept_link",
        -  "reject_link",
        -  "accept_merge",
        -  "accept_junk",
        -  "reject_entity"
        -]New value: +[
        +  "list",
        +  "propose",
        +  "relate",
        +  "dismiss_pair",
        +  "dismiss_slot_pair",
        +  "restore_slot",
        +  "accept_link",
        +  "reject_link",
        +  "accept_merge",
        +  "accept_junk",
        +  "reject_entity"
        +]
      • addedInput schema / properties / dst / description
        Added value: +"relate/dismiss_pair: the second entity. dismiss_slot_pair: an \"entity|attribute\" key from the deep response."
      • addedInput schema / properties / proposal_id / description
        Added value: +"Id actions: the one proposal to settle."
      • addedInput schema / properties / proposal_ids / description
        Added value: +"Id actions: settle many proposals in one call, instead of ``proposal_id``."
      • addedInput schema / properties / proposals / description
        Added value: +"propose: ``[{src, relation, dst, similarity?, rationale?}]``."
      • addedInput schema / properties / relation / description
        Added value: +"relate: the edge relation to write, from the graph vocabulary."
      • addedInput schema / properties / scope / description
        Added value: +"list: keep only findings of this kind."
      • addedInput schema / properties / src / description
        Added value: +"relate/dismiss_pair: the first entity. dismiss_slot_pair: an \"entity|attribute\" key from the deep response; restore_slot: retired key or entity."
      • addedInput schema / properties / store / description
        Added value: +"dismiss_slot_pair / restore_slot: which store the key belongs to — \"lesson\" or \"world\"."
    • Changedmemory_graph_unrelate3 fields changed
      • addedInput schema / properties / dst / description
        Added value: +"The edge's object entity."
      • addedInput schema / properties / relation / description
        Added value: +"The edge's relation."
      • addedInput schema / properties / src / description
        Added value: +"The edge's subject entity."
    • Changedmemory_history3 fields changed
      • addedInput schema / properties / as_of / description
        Added value: +"Slot mode only: ISO-8601 or epoch seconds; returns only versions written by then."
      • addedInput schema / properties / attribute / description
        Added value: +"The fact slot to read; omit for chain mode."
      • addedInput schema / properties / entity / description
        Added value: +"The subject whose past to read."
    • Changedmemory_lesson_search3 fields changed
      • addedInput schema / properties / query / description
        Added value: +"The task at hand, described the way it would have been logged."
      • addedInput schema / properties / top_k / description
        Added value: +"Max entries returned."
      • addedInput schema / properties / verbose / description
        Added value: +"Full provenance metadata; default entries are compact."
    • Changedmemory_outcome6 fields changed
      • addedInput schema / properties / about / description
        Added value: +"The tool or approach concerned; aids traversal."
      • addedInput schema / properties / detail / description
        Added value: +"What worked, or what the dead-end was."
      • addedInput schema / properties / episode / description
        Added value: +"Episode handle for attribution."
      • addedInput schema / properties / outcome / description
        Added value: +"What happened."
      • addedInput schema / properties / polarity / description
        Added value: +"\"+\" do-this or \"-\" avoid; usually omit — it is inferred from the outcome."
      • addedInput schema / properties / task / description
        Added value: +"Kind of task, in stable wording (\"deploy engine to host\") so signals for the same work group."
    • Changedmemory_recall4 fields changed
      • addedInput schema / properties / hops / description
        Added value: +"Max graph hops. Clamped to 1..5."
      • addedInput schema / properties / query / description
        Added value: +"Natural-language relational question; its top hits seed the graph walk."
      • addedInput schema / properties / top_k / description
        Added value: +"Bounds only the SEED search (the initial hits that name the walk's start entities), not the result, which is capped separately; up to 3 ``texts`` slots go to seed hits."
      • addedInput schema / properties / verbose / description
        Added value: +"Full fact/edge provenance and untruncated texts. Default facts are ``{attribute, value}``, edges ``{src, relation, dst}``, texts truncated to a preview."
    • Changedmemory_recent5 fields changed
      • addedInput schema / properties / episodes / description
        Added value: +"Keep only entries stamped with one of these episode ids."
      • addedInput schema / properties / n / description
        Added value: +"How many entries to return."
      • addedInput schema / properties / sources / description
        Added value: +"Keep only entries with one of these source tags."
      • addedInput schema / properties / tags / description
        Added value: +"Keep only entries carrying one of these tags."
      • addedInput schema / properties / verbose / description
        Added value: +"Full per-entry metadata; default entries are compact."
    • Changedmemory_reinforce1 field changed
      • addedInput schema / properties / entry_id / description
        Added value: +"The id of the memory to strengthen."
    • Changedmemory_relation_define6 fields changed
      • addedInput schema / properties / description / description
        Added value: +"What the relation means, for later readers."
      • addedInput schema / properties / dst_type / description
        Added value: +"Soft entity-kind expectation for the object; a mismatch warns, never rejects."
      • addedInput schema / properties / inverse_of / description
        Added value: +"Pair with an existing relation, as ``runs-on`` is the inverse of ``hosts``."
      • addedInput schema / properties / name / description
        Added value: +"The new relation name, hyphenated like the builtins."
      • addedInput schema / properties / src_type / description
        Added value: +"Soft entity-kind expectation for the subject; a mismatch warns, never rejects."
      • addedInput schema / properties / transitive / description
        Added value: +"True closes the relation transitively, so chained edges arrive pre-derived."
    • Changedmemory_search12 fields changed
      • addedInput schema / properties / bands / description
        Added value: +"Keep only entries held by one of these bands."
      • addedInput schema / properties / bm25 / description
        Added value: +"Tri-state override for keyword scoring, which aids exact-term queries; None follows config."
      • addedInput schema / properties / disable_recency_boost / description
        Added value: +"True to score without the recency bias."
      • addedInput schema / properties / episodes / description
        Added value: +"Keep only entries stamped with one of these episode ids."
      • addedInput schema / properties / explain / description
        Added value: +"Attach a ranking ``trace``; implies verbose."
      • addedInput schema / properties / min_score / description
        Added value: +"Override the 0.25 relevance floor."
      • addedInput schema / properties / query / description
        Added value: +"Natural-language description; specific beats vague."
      • addedInput schema / properties / rerank / description
        Added value: +"Tri-state override for cross-encoder reranking (~200ms); None follows config."
      • addedInput schema / properties / sources / description
        Added value: +"Keep only entries with one of these source tags."
      • addedInput schema / properties / tags / description
        Added value: +"Keep only entries carrying one of these tags."
      • addedInput schema / properties / top_k / description
        Added value: +"Max entries returned."
      • addedInput schema / properties / verbose / description
        Added value: +"Full per-entry metadata; the default is compact ``{id, text, source, tags, score}`` plus supersession when set."
    • Changedmemory_session_title2 fields changed
      • addedInput schema / properties / episode
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "description": "Your session handle — names that session's root directly (the identity a hook-registered client has).",
        +  "title": "Episode"
        +}
      • addedInput schema / properties / title / description
        Added value: +"What this session is about, e.g. \"Pseudolife-MCP\" or \"auth-refactor\"."
    • Changedmemory_set_add3 fields changed
      • addedInput schema / properties / attribute / description
        Added value: +"The slot's attribute."
      • addedInput schema / properties / entity / description
        Added value: +"The slot's subject."
      • addedInput schema / properties / member / description
        Added value: +"The member to add or re-confirm."
    • Changedmemory_set_remove3 fields changed
      • addedInput schema / properties / attribute / description
        Added value: +"The slot's attribute."
      • addedInput schema / properties / entity / description
        Added value: +"The slot's subject."
      • addedInput schema / properties / member / description
        Added value: +"The current member to retract."
    • Changedmemory_store7 fields changed
      • addedInput schema / properties / authority
        Added value: +{
        +  "default": "auto",
        +  "description": "Speech act: \"directive\" (an instruction to you) / \"quoted\" (a doc or third party said it) / \"observation\"; \"auto\" infers.",
        +  "enum": [
        +    "auto",
        +    "directive",
        +    "observation",
        +    "quoted"
        +  ],
        +  "title": "Authority",
        +  "type": "string"
        +}
      • addedInput schema / properties / distortion_tolerance
        Added value: +{
        +  "default": "auto",
        +  "description": "\"constraint\" = must survive verbatim, pinned in recall; \"auto\" infers only that.",
        +  "enum": [
        +    "auto",
        +    "constraint",
        +    "procedural",
        +    "belief",
        +    "preference",
        +    "episodic"
        +  ],
        +  "title": "Distortion Tolerance",
        +  "type": "string"
        +}
      • addedInput schema / properties / episode / description
        Added value: +"Episode handle for attribution."
      • addedInput schema / properties / origin / description
        Added value: +"Who asserted the claim."
      • addedInput schema / properties / source / description
        Added value: +"Stable per-project/topic tag for later filtering."
      • addedInput schema / properties / tags / description
        Added value: +"Optional labels, e.g. [\"decision\", \"blocker\"]."
      • addedInput schema / properties / text / description
        Added value: +"The claim to remember."
    • Changedmemory_supersede2 fields changed
      • addedInput schema / properties / new_text / description
        Added value: +"The replacement claim; stored fresh."
      • addedInput schema / properties / old_text / description
        Added value: +"The memory now obsolete. Matched exact-text first, then by nearest embedding — a close paraphrase works."
    • Changedmemory_world_search3 fields changed
      • addedInput schema / properties / query / description
        Added value: +"Natural-language description of the external fact needed."
      • addedInput schema / properties / top_k / description
        Added value: +"Max entries returned."
      • addedInput schema / properties / verbose / description
        Added value: +"Full provenance metadata; default entries are compact."
    • Changedmemory_world_set9 fields changed
      • addedInput schema / properties / attribute / description
        Added value: +"The slot's attribute."
      • addedInput schema / properties / confidence / description
        Added value: +"Source confidence, 0..1."
      • addedInput schema / properties / content_hash / description
        Added value: +"Hash of the fetched source, for change detection."
      • addedInput schema / properties / entity / description
        Added value: +"The slot's subject."
      • addedInput schema / properties / freshness_class / description
        Added value: +"Trust decay applied at read time: ``evergreen`` never decays, ``slow`` is months, ``volatile`` is weeks."
      • addedInput schema / properties / retrieved_at / description
        Added value: +"Epoch seconds the source was fetched."
      • addedInput schema / properties / source_quote / description
        Added value: +"The 1-2 sentences the claim was extracted from."
      • addedInput schema / properties / source_url / description
        Added value: +"http(s) citation URL; any other scheme is rejected."
      • addedInput schema / properties / value / description
        Added value: +"The externally-sourced value."
  2. 3 tool updatesv0.14.0
    • Changedmemory_dream2 fields changed
      • changedInput schema / properties / action / enum
        Previous value: -[
        -  "status",
        -  "pull",
        -  "commit",
        -  "run",
        -  "deep"
        -]New value: +[
        +  "status",
        +  "pull",
        +  "commit",
        +  "run",
        +  "deep",
        +  "runs",
        +  "rollback"
        +]
      • addedInput schema / properties / run_id
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "integer"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Run Id"
        +}
    • Changedmemory_graph_review3 fields changed
      • changedInput schema / properties / action / enum
        Previous value: -[
        -  "list",
        -  "propose",
        -  "dismiss_pair",
        -  "dismiss_slot_pair",
        -  "accept_link",
        -  "reject_link",
        -  "accept_merge",
        -  "accept_junk",
        -  "reject_entity"
        -]New value: +[
        +  "list",
        +  "propose",
        +  "relate",
        +  "dismiss_pair",
        +  "dismiss_slot_pair",
        +  "accept_link",
        +  "reject_link",
        +  "accept_merge",
        +  "accept_junk",
        +  "reject_entity"
        +]
      • addedInput schema / properties / proposal_ids
        Added value: +{
        +  "anyOf": [
        +    {
        +      "items": {
        +        "type": "integer"
        +      },
        +      "type": "array"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Proposal Ids"
        +}
      • addedInput schema / properties / relation
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "Relation"
        +}
    • Changedmemory_history1 field changed
      • addedInput schema / properties / as_of
        Added value: +{
        +  "anyOf": [
        +    {
        +      "type": "string"
        +    },
        +    {
        +      "type": "number"
        +    },
        +    {
        +      "type": "null"
        +    }
        +  ],
        +  "default": null,
        +  "title": "As Of"
        +}
  3. 35 tool updatesv0.11.0
    • First observeddocument_ingest
    • First observeddocument_search
    • First observedmemory_alias
    • First observedmemory_consolidate
    • First observedmemory_consolidation_candidates
    • First observedmemory_dream
    • First observedmemory_episode_end
    • First observedmemory_episode_start
    • First observedmemory_episode_summary
    • First observedmemory_fact_get
    • First observedmemory_fact_resolve
    • First observedmemory_fact_set
    • First observedmemory_forget
    • First observedmemory_get
    • First observedmemory_graph
    • First observedmemory_graph_relate
    • First observedmemory_graph_review
    • First observedmemory_graph_unrelate
    • First observedmemory_history
    • First observedmemory_lesson_search
    • First observedmemory_outcome
    • First observedmemory_recall
    • First observedmemory_recent
    • First observedmemory_reinforce
    • First observedmemory_relation_define
    • First observedmemory_search
    • First observedmemory_session_title
    • First observedmemory_set_add
    • First observedmemory_set_remove
    • First observedmemory_stats
    • First observedmemory_store
    • First observedmemory_supersede
    • First observedmemory_toolset
    • First observedmemory_world_search
    • First observedmemory_world_set

TDQS

A3.9/5.0

Scored across 35 tools

Disambiguation5/5

Every tool targets a distinct store, lifecycle action, or retrieval mode, and the descriptions aggressively cross-reference the right tool for each case (e.g. memory_store points to memory_fact_set for canonical facts; memory_recall falls back to memory_search). Even the many search and consolidation tools are clearly separated by store type or workflow stage.

Naming Consistency4/5

The memory_ prefix is used almost everywhere and the snake_case naming is predictable, with clear subfamilies like memory_fact_*, memory_world_*, memory_episode_*, and memory_graph_*. The main deviation is that action position varies (memory_search vs memory_fact_get) and the document_* tools break the memory_ prefix, but this is still easy to navigate.

Tool Count2/5

35 tools is above the 25+ threshold and feels heavy even for a broad memory server. Many consolidation, review, and graph-admin tools could be grouped or hidden behind sub-actions, so the surface is larger than an agent likely needs for day-to-day memory work.

Completeness4/5

The domain is covered remarkably thoroughly: memories, canonical facts, world facts, lessons, episodes, graph relations, consolidation, and documents all have create/read/update/delete or equivalent lifecycle operations. Minor gaps remain, such as no document delete/update and no obvious episode-list tool, but these are workable rather than blocking.

Maintenance

ActivityActive
ResponsivenessWithin a week

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Provides long-term memory capabilities for Claude through persistent storage and full-text search of context across conversations. Enables storing, searching, and managing memories organized by categories like facts, preferences, projects, and goals.
    5 npm
    1
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Provides persistent cross-session memory for Claude Code, enabling it to remember user preferences, decisions, and project context across new sessions.
    Apache 2.0
  • A
    license
    Not graded
    quality
    C
    maintenance
    Persistent memory management for Claude Code, allowing agents to store and retrieve user preferences, environment notes, and skills across sessions.
    0
    5
    MIT
  • F
    license
    C
    quality
    D
    maintenance
    Provides long-term memory and lossless context management for Claude Code, enabling automatic context compression, cross-session memory sharing, and semantic search across all history.
    10
    -