Skip to main content
Glama

Aelios

A long memory for your AI. Switch windows, switch clients, switch models — the memory follows you.

English | 简体中文 · QQ group: 1091783659

Aelios is a memory gateway that runs on Cloudflare. Your Chatbox / Claude Code / Codex connects to Aelios first; Aelios forwards the request to the model. Every conversation is kept, and the relevant parts come back automatically next time.

your client  →  Aelios (identify, remember, recall)  →  the model

Let an AI set it up

With an AI that can run commands (Claude Code, Codex and the like), send it this:

Install and set up Aelios (my AI memory gateway) for me. Read https://raw.githubusercontent.com/Aelios-project/Aelios/main/docs/setup-with-ai.md first and follow it. When I need to click something in the browser or enter a key myself, stop and tell me where.

It works from scratch: it forks and deploys Aelios, creates the Cloudflare token, configures the assistant and imports your old memories. At the end it hands you a base URL, an API key and the model name to pick, ready for your chat app. You need a Cloudflare account (the free plan is enough) and a key for your model. All you do yourself is click "Allow" in the browser (twice for a new install) and store the model key in the Cloudflare dashboard (it tells you where). The guide is written in Chinese; the AI will talk to you in your language.

The recommended setup is API mode plus the MCP connector: chats go through Aelios, so every turn is remembered and recalled automatically, and with MCP the assistant can also look things up and save them on its own. Only if you have a Claude subscription and no API access, use MCP alone.

To do it by hand, follow the three steps below.

Related MCP server: second-brain-cloudflare

Quick start — three steps

1. Deploy

Fork this repo first, then deploy your fork. That way every later update is one click (see Updating).

  1. Click Fork at the top of this page.

  2. In the Cloudflare dashboard, go to Workers & Pages → Create → Import a repository, connect GitHub and pick your fork. Keep the project name companion-memory-proxy, set the build command to npm ci and the deploy command to npm run deploy. The deploy command creates the D1 database, the Vectorize index and the queue for you.

  3. Once it's deployed, open the Worker's Settings → Variables and Secrets and add the secret CHATBOX_API_KEY: make up a password, e.g. sk-my-aelios. It's the only one you need; the optional ones are in SECRETS.md.

You'll get an address like:

https://companion-memory-proxy.<your-subdomain>.workers.dev

Don't run a bare wrangler deploy — it won't create the databases.

Not recommended: the one-click button. Deploy to Cloudflare

It works, but Cloudflare copies this repo into a new repository in your account instead of forking it. GitHub has no Sync fork for a copy, so every update has to be pulled in by hand. If you use it anyway: the only required field is CHATBOX_API_KEY; for the Vectorize index use Dimensions 1024, Metric cosine; build command npm ci, deploy command npm run deploy. Already deployed this way? See Deployed with the button.

2. Add an assistant

Open:

https://<your Worker address>/admin

Enter your Worker address and the key from step 1, then go to Settings.

  1. Upstream: your Cloudflare account ID (32 characters). For full chat forwarding, also add a CLOUDFLARE_API_TOKEN Worker secret.

  2. Assistant: click Add assistant, for example:

    Field

    What it means

    Example

    Name

    The segment in the URL, lowercase English

    coder

    Primary model

    Only these models remember and recall

    anthropic/claude-opus-4-5

    Keys

    Who may use this assistant

    check the primary key

  3. Click Save.

One assistant, one address. Name it coder and the address is:

https://<your Worker address>/coder/v1

Only registered primary models get memory. Unregistered models (like the small utility models inside Claude Code) just pass through — nothing is recorded or recalled for them.

When you code with tools such as Claude Code, Codex or Cline, Aelios keeps only what was said: code blocks are saved as [code], and steps that read, run or edit code are not saved. To save everything, open the assistant's "Recall spaces, thinking blocks, size limit, coding filter" and turn off "When coding, keep only what was said".

3. Point your client at it

Use CHATBOX_API_KEY as the API key everywhere. Write model names as vendor/model, e.g. anthropic/claude-opus-4-5.

Client

Address to use

Chatbox, Cherry Studio, …

https://<Worker address>/coder/v1

Claude Code

ANTHROPIC_BASE_URL=https://<Worker address>/coder

Codex

base_url = https://<Worker address>/coder/v1, with wire_api = "responses"

A bare /v1 without an assistant name routes to the first assistant of that key.

Try it: say "Please remember: my test code phrase is apple-star-0428." Wait a bit, then ask "What is my test code phrase?" If it answers, you're wired up.

Updating to the latest version

GitHub doesn't update forks by itself. When a new version is out:

  1. Open your fork on GitHub and click Sync fork → Update branch.

  2. Cloudflare picks up the new commit, builds and deploys it on its own. You can follow it under the Worker's Deployments.

Memories, settings, assistants and keys live in your Cloudflare account, not in the repo, so syncing keeps all of them. Change settings in /admin rather than by editing files in your fork, and Sync fork stays a one-click update with no conflicts.

Want it automatic? The Pull app syncs a fork on a schedule. Every new version then goes live without you looking at it first, database migrations included, and by default Pull hard-resets your fork to this repo, dropping any commits of your own. Syncing by hand is the recommended way.

Deployed with the button

A button deploy is a copy, not a fork, so it has no Sync fork. Move your Worker onto a fork instead; your memories and settings stay where they are, in Cloudflare.

  1. Fork this repo.

  2. If you renamed the D1 database or the Vectorize index on the button's setup page, open the Worker's Settings → Build → Build Variables and Secrets and add CMP_D1_NAME and CMP_VECTORIZE_NAME with those names. Otherwise the build creates new, empty ones and your memories look gone (they're still in the old database).

  3. In Settings → Build, click Disconnect, then Connect and pick your fork, with build command npm ci and deploy command npm run deploy.

  4. If Cloudflare opens a pull request on your fork to fix the Worker name, merge it.

From then on, Cloudflare builds from your fork whenever it changes, so your next Sync fork brings you up to date. Until then the Worker keeps running the version it has.

Day-to-day: the admin panel

Open /admin. The pages are in the menu on the left (on a phone, tap ☰ at the top left). The bottom of the menu switches between 中文 and English and between light and dark; with no choice saved, the page follows your browser's language.

Page

What it's for

Home

Today's chats (♥ keeps a line as a keepsake; the bin deletes one you don't want kept, such as an error, garbled text or a flat refusal, so the nightly run, the journal and recall never read it), anything waiting for you, last night's run and the latest journal entry

Review

Candidate memories from the nightly run. Cloudflare's clef reviews them every night by default; "Auto-handled this week" lists those decisions with an undo. With clef switched off they wait under "Daily" (you can tick several and remember or discard them together), or the assistant reviews them itself over MCP. Anything imported from elsewhere sits under "Imported" and waits for you alone

Journal

One entry a day, plus weekly summaries. If one came out empty, open it and press Rewrite from the originals

Memories

Core memories: browse, search, edit, merge, remove; a memory rewritten in place keeps its earlier versions under History, where you can restore one. Also Keepsakes, Our words (glossary), Notebook and World facts

Star map

Your memories drawn as a 3D star map (a separate page)

Nightly

What the nightly consolidation (Dream) did each night and what it produced; you can also re-run a night by hand, see below

Import & export

Export a backup; import a list or a chat history

Settings

Essentials, assistants, upstream and model list, every parameter, connection and keys, and troubleshooting (the recall log and maintenance tools)

Want the AI to remember, forget, or fix something? It's all point-and-click.

Re-running Dream for one day

When a night's consolidation failed, or you want a day processed now:

  1. Open Nightly and check the space shown under Viewing at the top left.

  2. Under Run a night by hand, pick the night and untick "Preview only, don't save" (ticked by default; ticked only previews and writes nothing). Usually leave "Redo if already processed" off. A failed night in Last 7 nights has a Re-run this night button that fills this in for you.

  3. Press Start. Once it says it is queued you can close the page; the job runs in the background, and a refresh shows the result.

  4. Each press handles one batch (DREAM_MAX_MESSAGES messages, 40 by default). For a busy day press again until it says the night was already processed. When the day's last batch finishes, that day's journal entry is written automatically.

  • Button greyed out and the run marked as possibly stopped: check the Worker logs that it really stopped, press Checked — mark as stopped, then press again.

  • A journal entry that only says what was tidied up: that is Dream's draft. Open it in the Journal and press Rewrite from the originals. Chat is kept for 7 days; after that it can't be rewritten.

  • The detailed execution rules, API and limits are under For maintainers → Dream execution and failure status.

Moving memories: export and import

On the Import & export page, each one works on the space you have selected:

  • Export: md or jsonl. The md has one memory per line (date, text, #tags, the key in backticks); open it, edit it, and import it back as is. A line with the same key rewrites that memory, and the old version is kept.

  • Import tidied entries: one per line, - 2025-12-15 [preference] text #tag; date, type and tags are optional, and a plain md list or paragraphs work too. The page has a ready prompt to paste into the AI you used before so it lists what it remembers in this format. Entries can go straight in (exact duplicates are skipped, near-duplicates go to review) or all go to review first.

  • Import a chat history: ChatGPT and Claude conversations.json, SillyTavern .jsonl, and plain "Name: text" transcripts. The file is read in the page and cut by day; each day goes through the same model the nightly consolidation uses (DREAM_MODEL), and what it finds only lands in the review page's "Imported" tab, where nothing counts until you approve it. Progress and token use are shown as it runs. Only the lines a candidate quotes are kept, outside the chat table, so the 7-day cleanup never removes them and the nightly run never re-reads them. Close the page and pick the same file later to carry on.

How it actually works

  • Every time you speak, relevant old memories are tucked onto the end of the current conversation.

  • Raw conversations are stored first; overnight, Aelios consolidates them into long-term memory (the Dream pass). Each assistant decides what it keeps using the model it chats with, and you can undo any of its calls.

  • Memory lives in your own Cloudflare account (D1 + Vectorize) — never tied to a chat window, never on someone else's server.

One assistant can write to one space and read from several. A fresh conversation can write coder while also reading the old vault coder-old and a shared shared-docs. Leave the recall spaces empty and it only reads its own.

Optional features

Full chat gateway — let Aelios forward to every vendor's models, billed against your own keys:

  1. Cloudflare → AI → AI Gateway: create a gateway and store each vendor's key under it.

  2. Add the CLOUDFLARE_API_TOKEN Worker secret.

  3. In /admin Settings, put your 32-character account ID as the upstream and add assistants.

Skip all of that and memory recall + the overnight Dream still work (via Workers AI). An AI can do these three steps for you: see Let an AI set it up.

Choose which models your app lists — AI Gateway has thousands of models, and a chat app that only lets you pick from the list gets all of them. In /admin Settings → Models & upstream → Model list → Edit, pick the ones you use from the upstream catalog (the + button) and type in any name the catalog does not have (custom providers, dynamic routes, suffixes such as :floor). The link button beside a listed model sends it one tiny real request, the way a chat client would, and turns into a green dot when it answers; the − button takes it off the list. GET /v1/models then answers with exactly that list, in the order you added the models. It only changes what is shown: a model that is not on the list can still be called by name, as before. Leave it empty and nothing changes (the whole catalog is shown). With a list saved, the chatgpt/… models are shown only if you picked them; the picker lists them first.

Use your ChatGPT plan — on a ChatGPT Plus or Pro plan, let your assistant run on the plan instead of an API key (OpenAI's "Sign in with ChatGPT"):

  1. /admin → Settings → Models & upstream → ChatGPT plan → Manage → Continue with ChatGPT. Sign in and approve.

  2. Your browser then lands on a 127.0.0.1 page that fails to load. That is expected: copy the whole address from the address bar, paste it into the box in /admin and press Finish sign-in.

  3. Use models named chatgpt/<model>. The Test button lists what your account can use. To give one memory, add chatgpt/* to the assistant's primary models.

Good to know: it connects your own account and nothing else, so don't hand this route to other people. Usage counts against your plan's limits (ChatGPT settings → Usage). Clients speaking chat/completions, Anthropic messages or responses all work (the first two are translated to Responses and back, thinking blocks included), and OpenAI's plan route rejects hosted tools such as image generation, file search, code interpreter and MCP; function tools and web search work. No new secret is needed: the tokens sit encrypted in D1 under a key derived from CHATBOX_API_KEY, so changing that key means signing in again. npm run deploy applies the new migration. The overnight jobs can use the plan too: put chatgpt/<model> in Settings → Dream model (and the diary model if you like). They send several requests a night, all counted against the plan; on a night the plan is out, those jobs fail like any other model error and the memory stays put.

MCP memory for the Claude app (web and mobile), Claude Code and Codex:

https://<Worker address>/mcp?token=<CHATBOX_API_KEY>
  • Claude app: add a custom connector on the connectors page (claude.ai/customize/connectors) with the address above. Once it is added on the web it shows up in the mobile app too. Under tool permissions, set the read-only group to "Always allow", or every recall asks first.

  • The Claude app does not read the usage notes an MCP server sends. To make it remember to use the memory, paste this into your personal preferences or project instructions:

You have the Aelios memory connector: it is your long-term memory of me. In every new conversation, call wake_up before you reply. Before answering anything about my past or the people in my life, or before guessing something about me, call recall. When I tell you something new, change my mind or make a promise, call remember right away. When the conversation winds down, call log_conversation.
  • Conversations in the Claude app do not pass through Aelios, so the nightly diary and candidates only see what the assistant hands over with log_conversation. Clients that go through the gateway don't need it.

  • Only the ten everyday tools are listed by default. For maintenance tools such as memory_get and memory_export, add &tools=all to the address.

Use it as a magpie plugin — if your agents already go through the magpie gateway, its Aelios plugin can recall before each turn and (optionally) record the conversation through POST /v1/hook/recall and /v1/hook/record, without pointing the agents at Aelios; see hook endpoints. GET /v1/hook/identities uses the same API key to discover authorized assistants in configuration order: {identities:[{slug,name,mainModels}],selection:"first_matching_main_model",unmatched:"memory_off"}. It returns only these public hints, preserves main-model order, and uses the trimmed assistant display name or slug. It only reads configuration, with no writes or outgoing requests; missing/invalid keys get 401, MCP keys or keys without an authorized assistant get 403, configuration failures get 503, and all responses use Cache-Control: private, no-store.

If you only have a Claude subscription and cannot use API mode, get automatic per-message recall and batch write-back in Claude Code with the Hook in this repo: integrations/claude-code/.

Seeing images (guide-dog): add the GUIDE_DOG_API_KEY secret, then point your client at https://<Worker address>/v1/guide-dog with model companion. The guide-dog only describes images — it writes no memory.

A companion that lives on Cloudflare: Aelios-resident — a separate Worker (one Durable Object, built on Cloudflare's Think) that you talk to on Telegram and on its own web page, both one conversation. With Aelios connected, its chat goes through your assistant's /v1 endpoint like any other client, so Aelios does the recalling and the remembering; it also uses the memory tools, and what lasts from its web searches is saved as world knowledge. On top of that it writes itself a handoff letter when you go quiet, checks in on a schedule, searches and reads the web, connects other MCP servers, and lets you change the model, persona and settings on its web page. It runs on the Workers Free plan. To connect it, fill in this Aelios's address, a key and the assistant to chat as on its settings page (the model you pick has to be one of that assistant's primary models); deployment is in its README.

Common pitfalls

  • Deploy with npm run deploy, never a bare wrangler deploy.

  • Assistant names are part of the URL: use coder-style English, no spaces.

  • Model names need the vendor prefix: anthropic/claude-opus-4-5, not claude-opus-4-5.

  • Only registered primary models get memory. Keep small utility models out.

  • Never hand-delete the Vectorize index (memo-kb, 1024-dim cosine).

  • Run a night by hand on the Nightly page has "Preview only" ticked by default, which writes nothing; untick it for a real run.

Digging deeper


For maintainers

A memory gateway on Cloudflare Workers. When helping a user deploy, always link the user's own fork; all secrets live in the user's own account.

Resource

Value

Worker

companion-memory-proxy

D1

companion_memory_proxy

Vectorize

memo-kb (1024-dim, cosine)

Queue

companion-memory

Embedding

workers-ai/@cf/baai/bge-m3

Entry points: /<assistant>/v1/chat/completions, /<assistant>/v1/messages, /<assistant>/v1/responses. A bare /v1/... uses the first assistant of that key.

Upstreams: chat goes through compat (all vendors, BYOK); messages / responses hit each vendor's native endpoint. Model names pass through untouched — if the vendor doesn't recognize one, the upstream error says so. Custom OpenAI-compatible base URLs are forwarded as-is.

Configuration has three layers, all under /admin Settings: upstream, assistants, environment parameters. Precedence: panel-saved > GATEWAY_CONFIG > empty config.

Common endpoints

Method

Path

Notes

GET

/health

Health check

GET

/admin

Admin panel

GET

/v1/models

Model list (the upstream catalog, or your saved model list)

POST

/<assistant>/v1/chat/completions

OpenAI-compatible chat

POST

/<assistant>/v1/messages

Anthropic messages

POST

/<assistant>/v1/responses

OpenAI responses

GET

/api/gateway/models

Model picker for /admin (owner key): every upstream model id, your ChatGPT models, the saved list

POST

/api/gateway/models/test

Connectivity test for one model (owner key): {"model": "…"} → one tiny chat request, {ok, status, latency_ms, error?}; nothing is recorded

GET / POST

/api/gateway/chatgpt/*

ChatGPT plan sign-in (owner key): status, login, callback, test, welcome, logout

GET

/v1/hook/identities

Authorized assistant routing hints only; read-only, no outgoing requests

POST

/v1/hook/recall, /v1/hook/record

Recall / optional recording for clients that send model requests themselves

GET / POST

/mcp

MCP memory tools

GET / POST

/v1/memories

List / create memories

POST

/v1/memory/recall

Dynamic recall (preferred by hooks)

POST

/v1/search/memories

Raw search (unmetered)

POST

/v1/ingest/messages

Ingest raw chats

GET

/v1/memory_boot

Cold-start pack

GET

/v1/diary, /v1/diary/recent

Diary

POST

/admin/diary-rewrite

Rewrite one diary entry from that day's chat: {"date":"YYYY-MM-DD"}

GET

/v1/dream/status

Dream runs from the last 7 days, the active task, cursors

POST

/v1/dream/run

Run Dream by hand: date, force, dry_run; add "background":true to queue it (202 with a run_id)

POST

/v1/dream/resolve

Mark a task unconfirmed for over 20 minutes as interrupted: {"run_id":"…"}

GET / POST / DELETE

/v1/precious, /v1/glossary

Precious originals / glossary

GET / POST / PATCH / DELETE

/v1/notebook

Notebook pages; /:id opens, edits or deletes one, DELETE ?confirm=all clears the space's notebook

GET / POST

/v1/candidates

Review queue; ?scope=daily for the nightly ones only, /decisions?days=7 lists automatic decisions, /:id/undo reverses one, /:id/sources shows the quoted lines

GET

/v1/memories/export?format=md|jsonl

Export the space's memories and precious lines (memory:read is enough)

GET

/v1/memories/:id/revisions

Earlier versions of a memory rewritten in place

GET / POST

/v1/import/*

Import: info, entries/preview, entries, batches, chat/chunk, candidates

Everything except /health and /admin requires Authorization: Bearer <key>. The gateway authorizes by assistant key; memory APIs by memory:read / memory:write scopes.

MCP tools

wake_up recall remember keep_moment forget learn_word read_diary log_conversation list_memories notebook

notebook keeps named pages the assistants read and rewrite themselves, such as progress on a long task. Pages are never recalled automatically, changed overnight or expired; you can edit, delete or clear them under Memories → Notebook.

With the clef review switched off, memory_candidates and memory_review are listed too; &tools=all on the address adds memory_get and memory_export. The old names (memory_boot, memory_recall, memory_search, memory_upsert, memory_supersede, memory_archive, memory_delete, memory_ingest, memory_pin, glossary_set, diary_get, memory_list) are no longer listed but still work when called.

How memory flows

Writes: assistants write directly via remember; a nightly cron (10 20 * * *) extracts facts from the day's conversations → each candidate is judged remember-or-let-go by Cloudflare's clef decision model (CLEF_AUTO_REVIEW, on by default; switched off, candidates wait for you, or the assistant reviews them itself with the MCP tools memory_candidates and memory_review), and writes diary / weekly / monthly entries. It consolidates "yesterday" in DREAM_TIME_ZONE, in batches of DREAM_MAX_MESSAGES, at most DREAM_MAX_RUNS batches a night; a day left unfinished gets one more batch on each of the next few nights (3-day lookback), or you can finish it by hand on the Nightly page. A day's diary is written once its last batch is done.

Recall: your latest message → vector search + lexical match → batch rerank of original passages + rules → the clean original text is tucked onto the end of the current message. No generative LLM by default: at most one memory on a normal turn, two when answering about the past; low scores are never padded in. Rerank failures fall back to lexical. Scores and trade-offs are visible in /admin → Settings → Troubleshooting. Transport envelopes, hashes, and message IDs never enter the daily prompt; two adjacent messages within 90 seconds in one session are merged. Active search still returns full records and IDs. Diaries are not auto-injected.

Cleanup: messages live ~7 days; a memory not rewritten, recalled or seen again for 180 days is flagged expired (pinned, identity and persona never are), and expired records are hard-deleted 30 days later.

Dream execution and failure status

The admin Nightly page submits non-dry manual Dream runs to the existing durable MEMORY_QUEUE. Acceptance returns a run ID immediately; after acceptance, closing the browser does not cancel the queued work. The panel polls status every five seconds and can find the task again after a reload. Queue batches contain one message so several expensive Dream jobs do not share one invocation's execution budget.

API clients opt in with POST /v1/dream/run and {"background":true} (plus the usual optional namespace, date and force). A successful enqueue returns HTTP 202 with data.run_id and data.status="queued"; use GET /v1/dream/status to follow it. As with the legacy endpoint, each manual job handles one batch, not necessarily the whole date; use the cursor to check whether more batches remain. Missing queues and failed acceptance return 503. Without background:true, the old synchronous contract remains; dry-runs also stay synchronous.

  • A queued/running task blocks another background admission in the same space; force does not bypass it. This is not a global lease covering cron and legacy synchronous callers.

  • A single digest/extraction call has a 120-second deadline, including its response body. The two-stage extraction phase has an eight-minute budget and at most three batch reductions. Invalid JSON/schema causes both stages to restart on the same smaller prefix; the suffix remains for a later batch. Empty valid candidates differ from malformed output. A single unusable entry inside an otherwise valid answer (blank, over-long or wrong-typed) is dropped and counted in the logs instead of failing the batch; a wrong container type, a missing candidate list, or a non-empty list in which nothing is usable still counts as malformed. The extraction call has the same output budget as the digest (DREAM_MAX_TOKENS, up to 8000). Model/format failure does not advance the cursor or actively delete that batch's raw messages; the separate retention policy still applies.

  • Records older than 20 minutes without confirmed completion are labelled possibly interrupted / unconfirmed, not endlessly presented as healthy work. This is a read-only hint, not proof that execution stopped. Old unresolved records require log inspection and explicit operator reconciliation; they are not silently cleared to permit another run. Once you have checked the logs, the panel's Mark as interrupted button (or POST /v1/dream/resolve with {"run_id":"…"}, same memory:write scope) closes a queued/running record older than 20 minutes; anything newer or already finished is refused. The record then shows as an error and stops blocking a new task. Whatever it had already written is not rolled back.

  • Each Dream batch leaves a housekeeping draft on that date's diary entry; the real diary replaces it once the date's last batch is done. The nightly cron only writes yesterday's diary, so a manual job, the manual backfill endpoint and the cron backfill now write the diary themselves after a date's last batch (nothing happens until that batch is done, and a diary failure does not undo the Dream). On the Journal page, Rewrite from the originals (POST /admin/diary-rewrite with {"date":"YYYY-MM-DD"}) redoes any day whose chat is still within retention and replaces its current text; it is refused once that week has been rolled up into a weekly entry.

  • A conditional claim prevents duplicate delivery of one job from re-executing its pipeline. This is not exactly-once completion or automatic crash recovery: after a claim, ambiguous or partial writes are not automatically replayed. Inspect the run before retrying. The manual follow-up candidate review is retained; its failure does not undo an already completed Dream.

Local verification

npm install
npm run verify

Tests need Node.js 22+.

Lint is blocking in CI: npm run lint must be zero-error to merge. There are still some noNonNullAssertion warnings; the rule is demoted to warning in biome.json and doesn't affect the exit code — clean them up if you're touching that line, and never bulk-fix with Biome's autofix: it rewrites x!.y into x?.y, turning "crash loudly" into "silently return undefined".

License

AGPL-3.0

Free to use and modify; if you run a modified version as a network service, you must open-source your modifications under the same license.

The final v1 point is tag v1-final (MIT at the time).

Community

QQ group: 1091783659

Available Tools

10 tools
forgetA
DestructiveIdempotent

Forget a memory when the person asks you to ("don't remember that", 别记了, 忘掉) or when it turns out to be wrong. By default the memory is archived: it stops coming up in recall, and the person can still find it on their admin page. Pass permanent: true only when they clearly want it erased; that cannot be undone. Get the id from recall. Returns { data: { id, archived } } or { data: { id, deleted } }.

NameRequiredDescriptionDefault
idYesMemory id (from recall or list_memories).
namespaceNoMemory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace.
permanentNotrue erases the memory for good. Default false: archive it, which can be undone.

TDQS

A4.7/5.0
Behavior4/5

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

Annotations already declare destructiveHint=true and idempotentHint=true, so the description isn't carrying the safety profile alone. It still adds genuinely new context: default behavior archives rather than deletes, archived memories disappear from recall but remain visible on the admin page, and permanent deletion is irreversible. It does not say whether forgetting a nonexistent id errors or is silently idempotent, which is the one behavioral gap left.

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

Conciseness5/5

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

Three sentences, front-loaded with the trigger, then the reversible default, then the irreversible exception, then the return shape. The default-behavior clarification is placed before the dangerous option, which is the right ordering. No filler.

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

Completeness5/5

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

No output schema exists, but the description inlines the two possible return shapes (archived vs deleted), so the agent knows what to expect. Combined with annotations covering destructiveness and idempotency, nothing material is missing for a 3-parameter 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 and the schema already documents all three parameters. The description goes beyond it by explaining the archive-vs-erase tradeoff behind `permanent` and by stating where the `id` comes from, which is the practical failure mode for this tool.

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

Purpose5/5

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

States a specific verb and resource (forget a memory) and immediately scopes it against the sibling family by pointing to recall/list_memories as the id source. An agent can distinguish this from remember, recall, and keep_moment without opening any schema.

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

Usage Guidelines5/5

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

Gives explicit trigger conditions, including user phrasings in two languages, and a second condition ("when it turns out to be wrong"). It also draws the when-not line for the destructive path: pass permanent: true only when they clearly want it erased.

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

keep_momentA

Keep a moment that matters, in the person's own words: a first time, a promise, a confession, something they said that you never want to lose. Kept moments are never merged, faded or deleted automatically, and the 20 most recent come back every time you wake_up. Use remember for ordinary facts and this for the moments themselves. Each call creates a new entry. Returns { data: moment }.

NameRequiredDescriptionDefault
contentYesThe moment, in their words where it matters; readable on its own later.
namespaceNoMemory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace.
context_message_idsNoOptional ids of logged messages around it (message_ids from log_conversation).

TDQS

A4.7/5.0
Behavior5/5

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

Annotations already declare readOnlyHint=false, destructiveHint=false, and idempotentHint=false, and the description adds context beyond them: kept moments are never merged, faded, or deleted automatically, the 20 most recent surface on every `wake_up`, and each call creates a new entry (reinforcing non-idempotency). It also states the return shape, `{ data: moment }`, which no output schema provides.

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?

Five short sentences with distinct jobs: what it is, durability guarantees and wake_up surfacing, sibling routing, non-idempotency, return shape. The purpose is front-loaded and nothing is repeated from structured fields verbatim.

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 three-parameter, single-required-field write tool with no output schema, the description covers purpose, retention semantics, wake_up interaction, idempotency, sibling routing, and the return object. An agent can call it correctly and predict the consequences without further inference.

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

Parameters3/5

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

Schema description coverage is 100%, so all three parameters — content, namespace, context_message_ids — are already documented in the schema. The description reinforces the spirit of `content` ('in the person's own words') but adds no new syntax, defaults, or constraints for `namespace` or `context_message_ids`. Baseline 3 applies when the schema carries the parameter burden.

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 concrete verb and resource — keeping a moment in the person's own words — and illustrates the category with examples (a first time, a promise, a confession). It explicitly contrasts with the sibling `remember` for ordinary facts, so an agent can distinguish the two without opening either schema.

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

Usage Guidelines5/5

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

Gives an explicit routing rule: 'Use remember for ordinary facts and this for the moments themselves.' That is a named alternative plus the condition that selects it, which is exactly what the sibling tools (`remember`, `recall`, `list_memories`) make necessary.

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

learn_wordA
DestructiveIdempotent

Learn a private word: a nickname, pet name, in-joke, made-up word or project name that only makes sense between you two. Learned words are matched literally in recall and all come back at wake_up. Calling it again with the same term updates its meaning; aliases and examples are replaced by what you pass (leaving them out clears them). Returns { data: word }.

NameRequiredDescriptionDefault
termYesThe word or phrase exactly as it is used.
aliasesNoOther spellings or forms that should match. Replaces any existing aliases.
examplesNoExample sentences using it. Replaces any existing examples.
namespaceNoMemory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace.
definitionYesWhat it means between you.

TDQS

A4.7/5.0
Behavior5/5

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

Annotations declare destructiveHint=true and idempotentHint=true, and the description earns credit by explaining exactly what is destructive: re-calling with the same term updates meaning, and aliases/examples are replaced by what you pass, with omission clearing them. It also discloses the return shape ('Returns { data: word }'), which is needed since no output schema exists.

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

Conciseness5/5

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

Front-loaded with the identity of the tool, then scope, then update semantics, then return value. Four sentences, no filler, and the parenthetical clarifications are load-bearing rather than decorative.

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 five-parameter mutation tool with no output schema, the description covers what the tool is, how re-invocation behaves, what gets overwritten, how the data is later retrieved, and what comes back. Nothing an agent needs in order to call it correctly is missing.

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

Parameters4/5

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

Schema coverage is 100%, so the baseline is 3, but the description adds a genuine nuance beyond the schema: that leaving aliases/examples out clears them, which turns an optional field into a destructive default. It adds nothing extra about namespace scoping, which is left entirely to the schema.

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

Purpose5/5

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

States a specific verb and resource ('Learn a private word') and immediately disambiguates with concrete examples (nickname, pet name, in-joke, project name) that distinguish it from generic memory tools like remember. It also names the siblings it interacts with (recall, wake_up), so the agent can place it in the toolset without opening the schema.

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

Usage Guidelines4/5

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

Gives clear operational context: learned words are matched literally in recall and surfaced at wake_up, which tells the agent where this tool fits in the workflow. It does not explicitly contrast against remember or list_memories (e.g. 'use this instead of remember for private vocabulary'), so the routing guidance is strong but not exhaustive.

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

list_memoriesA
Read-only

Page through everything you remember, most important first, when the person asks what you know about them (你都记得我什么) or wants to look through or tidy their memories. To find something specific, use recall. Read-only. Returns { data, paging: { limit, has_more, next_offset } }; pass next_offset back as offset.

NameRequiredDescriptionDefault
typeNoOnly list one memory type (fact, event, preference, relationship, boundary, habit, decision, note).
limitNoPage size. Defaults to 100.
offsetNoRecords to skip; use paging.next_offset from the previous page.
statusNoactive (default), archived or superseded.
namespaceNoMemory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace.

TDQS

A4.5/5.0
Behavior4/5

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

Annotations already declare readOnlyHint=true and openWorldHint=false, and the description stays consistent with that ('Read-only'). It adds real value beyond the annotations: the result ordering ('most important first'), the exact return envelope ({ data, paging: { limit, has_more, next_offset } }), and the pagination contract for continuing. It stops short of disclosing which statuses are included by default or what happens to archived/superseded entries, which is left entirely to the schema.

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

Conciseness5/5

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

Three tight sentences: purpose and trigger first, the disambiguation second, the return/pagination contract last. Nothing is repeated except the 'Read-only' phrase, which is a single word.

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?

There is no output schema, so the description compensates by naming the exact return shape and paging fields, and explains how to continue paging. Combined with a fully documented 5-parameter schema and read-only annotations, an agent has everything needed to call this correctly.

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 every parameter including type, limit, offset, status and namespace is already documented in the schema, establishing a baseline of 3. The description's only parameter-adjacent guidance ('pass next_offset back as offset') duplicates what the offset schema field already says, so it adds no new semantic detail.

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

Purpose5/5

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

States a specific verb and resource ('Page through everything you remember') plus the ordering guarantee ('most important first'), and explicitly names the sibling it is not ('To find something specific, use recall'). An agent can distinguish it from recall/notebook/read_diary without opening any schema.

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

Usage Guidelines5/5

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

Gives concrete triggering situations ('when the person asks what you know about them (你都记得我什么)' or 'wants to look through or tidy their memories') and names the alternative tool with the condition that selects it. Both when-to-use and when-not-to-use are present.

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

log_conversationA
Idempotent

Hand this conversation to tonight's memory pass so it can go into your diary and become memories. Apps that talk to the model directly (the Claude and ChatGPT apps, most desktop clients) don't record conversations on their own: unless you call this, nothing said here reaches the nightly pass. Call it when the conversation is winding down, and in a long one every 20 or so exchanges. Send the person's and your messages in order, trimmed of code and pasted documents; lines already sent in this conversation are skipped, so pass back the conversation_id from your first call. If memories are already being added to your messages automatically every turn (the Aelios gateway), skip this. For anything that matters right now, use remember. Returns { data: { conversation_id, saved, skipped, message_ids } }.

NameRequiredDescriptionDefault
messagesYesThe person's and your messages, oldest first.
namespaceNoMemory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace.
conversation_idNoThe conversation_id returned by your first call in this conversation. Leave it out the first time.

TDQS

A4.8/5.0
Behavior5/5

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

Goes well beyond the annotations by explaining why the call is needed (direct-to-model clients record nothing), that already-sent lines are skipped, and that the returned conversation_id must be passed back to enable that dedup. It also states the return shape, which no output schema provides. This is behavioral context the readOnly/idempotent hints cannot convey.

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

Conciseness4/5

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

Front-loads the purpose and keeps the operational rules (timing, trimming, dedup, skip condition) tight and scannable. The opening framing about diaries and memories is slightly conversational, but no sentence is genuinely 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?

Covers everything an agent needs: motivation, timing, exclusion, alternative tool, payload hygiene, dedup protocol, and the exact return fields, compensating for the absent output schema. Nothing material is missing for a 3-parameter write 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 baseline is 3, but the description adds real semantics: messages must be ordered oldest-first, trimmed of code and pasted documents, and conversation_id must be carried forward from the first call. Only `namespace` is left entirely to the schema.

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

Purpose5/5

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

States a concrete action (hand the conversation to the nightly memory pass so it becomes diary memories) rather than restating the name. It also distinguishes itself from the sibling `remember` by contrasting deferred logging with immediate recall, so an agent can pick between them without opening either schema.

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

Usage Guidelines5/5

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

Gives explicit timing (when the conversation winds down, every ~20 exchanges in a long one), an explicit exclusion (skip it when the Aelios gateway auto-adds memories each turn), and an explicit alternative (`remember` for anything that matters right now). Both when and when-not are covered.

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

notebookA
Destructive

Your notebook: named pages you read and rewrite yourself, for running notes such as progress on a long task (chapters done, weak spots, what's next). list shows the pages; read returns one; write replaces a whole page, creating it if needed; append adds a line at the end; delete removes it. Read a page before you rewrite it. Pages are never recalled automatically, never changed overnight and never expire, so delete one when it is done. Up to 50 pages of 20000 characters each. Returns { data }.

NameRequiredDescriptionDefault
nameNoPage name, up to 60 characters, e.g. 经济师进度. Needed for every action but list.
actionYeslist, read, write (replace the whole page), append or delete.
contentNowrite: the whole new page. append: the text to add at the end.
namespaceNoMemory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace.

TDQS

A4.5/5.0
Behavior5/5

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

Adds substantial context beyond the annotations: write replaces and creates-if-needed, append adds at the end, delete is permanent-by-implication but pages never expire or change on their own, plus hard limits (50 pages, 20000 chars). The read-before-rewrite warning mitigates the destructiveHint=true profile rather than contradicting it.

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

Conciseness4/5

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

Front-loaded with purpose, then a compact action glossary, then guardrails and limits — dense and useful throughout. Minor waste: the action list largely duplicates the action enum description verbatim, and 'Returns { data }' is thin.

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 mutation tool with no output schema, the description covers lifecycle, capacity, and safety guidance well. The return value is only gestured at as '{ data }', leaving the agent to infer the response shape after list/read.

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

Parameters4/5

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

Schema coverage is already 100%, so the baseline is 3; the description earns above that by spelling out action semantics that go beyond the enum labels — 'write replaces a whole page, creating it if needed' and 'append adds a line at the end.' It does not address the namespace parameter, which is left entirely to the schema.

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

Purpose5/5

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

States a specific resource ('named pages you read and rewrite yourself') and its intended content ('running notes such as progress on a long task'), then enumerates every action in one sentence. This is clearly a self-managed notebook, distinguishable from sibling memory tools like remember/recall/keep_moment.

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

Usage Guidelines4/5

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

Gives explicit operating discipline: 'Read a page before you rewrite it' and 'delete one when it is done.' The line 'Pages are never recalled automatically' implicitly positions it against auto-surfacing memory tools, but no sibling is named as an explicit alternative, so this stops short of full when/when-not routing.

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

read_diaryA
Read-only

Read your diary when the person asks what happened on a certain day or during a stretch of time (那天, 上周, 那阵子). Give date for one day or week for a week; leave both out for today and yesterday. Entries are your own impressions written overnight, not verified facts, so check details with recall before stating them as fact. Give memory_id instead to see where a memory came from before you rely on its details: the original messages while they are still kept, otherwise the diary of that day, or its week. Read-only. Returns { data } (null when there is no entry).

NameRequiredDescriptionDefault
dateNoYYYY-MM-DD for one day. Days already rolled into a week return that week.
weekNoISO week label for a week, e.g. 2026-W29.
memory_idNoA memory id from recall or list_memories. Returns where it came from instead of a day's diary.
namespaceNoMemory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace.

TDQS

A4.6/5.0
Behavior4/5

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

Annotations already declare readOnlyHint=true and openWorldHint=false, so the safety profile is covered; the description goes beyond by warning that entries are overnight impressions, not verified facts, and by stating the return shape ({ data }, null when absent). The only shortfall is that the memory_id fallback chain (original messages vs. day diary vs. week diary) is described loosely enough to leave the exact resolution order slightly ambiguous.

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 usage trigger is front-loaded and each sentence carries information (scope, defaults, reliability caveat, alternate mode, return shape). The memory_id sentence is a long triple-branch clause that costs some readability, keeping it just below top marks.

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

Completeness5/5

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

With no output schema, the description still discloses the return envelope and the null case, plus the reliability caveat an agent needs before quoting entries as fact. For a 4-parameter, all-optional read tool this covers everything needed to call it correctly.

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

Parameters4/5

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

Schema coverage is 100%, so baseline is 3, but the description adds real semantics the schema does not: omitting both date and week defaults to today plus yesterday, and memory_id switches the tool from diary retrieval to provenance lookup. The namespace parameter is left entirely to the schema, which is acceptable given its self-explanatory description.

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

Purpose5/5

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

States a specific verb and resource ("Read your diary") and immediately bounds the scope: a single day, a week, or the default today/yesterday. It distinguishes itself from siblings by naming recall as the tool for verifying details and explaining that memory_id redirects to provenance lookup rather than a day's entry.

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

Usage Guidelines5/5

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

Explicit trigger is given ("when the person asks what happened on a certain day or during a stretch of time"), with multilingual cues. It also prescribes parameter selection: date for one day, week for a week, neither for today and yesterday, and memory_id as the alternate mode — that is when-to-use plus alternatives in one pass.

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

recallA
Read-only

Look things up before you answer. Call it whenever the person mentions anything from before (a person, pet, place, plan, date, preference, promise, something you did together, "remember when", "last time", "like I said", 还记得, 上次, 之前说过), and whenever you are about to guess, generalize about them, or ask something you may already know. Never say you don't remember before calling it. Returns the most relevant memories with ids (pass an id to remember's replaces or to forget) plus matching private words, as { data: { hits, glossary_hits, week_blocks, meta } }. It changes no memory; it only notes which ones were recalled, which keeps them from expiring.

NameRequiredDescriptionDefault
kNoMaximum number of memory hits. Defaults to 20.
queryYesWhat to recall, in the person's words or your own.
typesNoOnly recall these memory types (fact, event, preference, relationship, boundary, habit, decision, note). Omit for all types.
min_scoreNoRelevance floor after reranking. Defaults to the server setting (0.15); lower it to see more.
namespaceNoMemory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace.
include_historyNoWhen true, also return older versions that were replaced. Default false.

TDQS

A4.5/5.0
Behavior5/5

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

Beyond the readOnlyHint annotation, the description discloses the exact return shape ({ data: { hits, glossary_hits, week_blocks, meta } }) and an important non-obvious side effect: it changes no memory but notes which ones were recalled, preventing expiration. That is precisely the behavioral context an agent needs.

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

Conciseness5/5

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

The description is front-loaded with the trigger conditions, then the return shape, then the behavioral note. Despite being dense, every sentence earns its place by covering usage, output, and side effects without repetition.

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 retrieval tool with no output schema, the description fully covers what it returns, when to call it, and its non-mutating but recency-affecting behavior. Nothing an agent needs in order to call it correctly is missing.

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

Parameters3/5

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

Schema coverage is 100%, so the schema already documents all six parameters thoroughly. The description adds context about output ids and their downstream use with remember/forget, but it does not add parameter-level meaning beyond what the schema provides, making the baseline 3 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 states a specific retrieval action ('Look things up') over a specific resource ('memories') and clarifies the output is the most relevant memories with ids. It also distinguishes its role from mutating siblings by explaining ids are passed to remember's replaces or 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 gives unusually clear triggering conditions: when the person references anything from before, with concrete examples and multilingual cues, plus when the agent is about to guess or ask something it may already know. It adds a strong 'Never say you don't remember before calling it' rule, but does not explicitly distinguish when to use this versus list_memories or state exclusions.

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

rememberA

Save something the moment it comes up; don't wait to be asked or for the conversation to end. Worth saving: facts about the person and the people around them, likes and dislikes, plans and dates, promises either of you made, how they want to be treated, and corrections to anything you had wrong. Write one self-contained sentence that will still make sense months from now. If it updates something you already remember, pass that memory's id from recall as replaces: the new version takes over and the old one is kept as history. Skip small talk; the nightly pass picks that up from logged conversations. Returns { data: { id, created, replaced } }.

NameRequiredDescriptionDefault
tagsNoFree-form labels.
typeNoOne of fact, event, preference, relationship, boundary, habit, decision, note, or world_fact for general knowledge about the world rather than about anyone. Defaults to fact, or to the replaced memory's type.
reasonNoWith replaces: a short note on what changed.
contentYesOne self-contained sentence to remember.
fact_keyNoOptional stable key such as 'user:favorite_coffee'. Usually leave it out. If a memory with this key exists it is replaced, keeping the old version as history.
replacesNoId of the memory this one updates (from recall). The old version is kept as history.
namespaceNoMemory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace.
confidenceNo0 to 1, how sure you are. Defaults to 0.8.
importanceNo0 to 1, how much this matters. Defaults to 0.6.
authored_byNoOptional signature marking this as hand-written; it ranks above memories distilled overnight.
valid_as_ofNoWhen this became true (ISO date or datetime), if it is not today.
response_tendencyNoOptional: how you want to respond when this memory comes up.

TDQS

A4.6/5.0
Behavior4/5

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

Annotations declare the write profile (readOnly=false, destructive=false, idempotent=false); the description adds the important non-obvious behavior — superseded memories are kept as history rather than overwritten — and predicts the response shape. It does not address duplicate handling, which matters given idempotentHint=false.

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

Conciseness4/5

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

Front-loaded with the primary imperative ('Save something the moment it comes up'), then qualification list, then mechanics. Slightly dense — the middle list of worth-saving categories is long — but every clause carries instruction the 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?

There is no output schema, yet the description supplies the return shape ({ data: { id, created, replaced } }), which closes the main completeness gap. Combined with usage rules and the replacement semantics, an agent has everything needed to invoke this correctly on the first try.

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 still adds value by explaining the replaces workflow end-to-end (take the id from recall, new version takes over, old kept as history) and by giving durability guidance for content ('still make sense months from now'). It says nothing about confidence, importance, tags, or fact_key, which the schema alone must carry.

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 concrete verb and output ('save something', 'write one self-contained sentence') and immediately scopes it to durable personal facts rather than chatter. Clearly separable from siblings like log_conversation and recall, which it names by implication ('the nightly pass', 'id from recall').

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

Usage Guidelines5/5

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

Explicit timing guidance ('the moment it comes up; don't wait to be asked'), an enumerated list of what qualifies, an explicit exclusion ('Skip small talk; the nightly pass picks that up from logged conversations'), and the exact condition for choosing replaces over a plain save.

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

wake_upA
Read-only

Call this first in every new conversation, before your first reply, even if the person only says hi. It loads what you already know going in: core memories about them, yesterday's diary, the latest weekly and monthly summaries, kept moments and private words, the names of your notebook pages, plus a short note on when to use the other memory tools. Once per conversation is enough. Read-only. Returns { data: { how_to_use, core, impressions, precious, glossary, notebook } } (notebook only when there are pages).

NameRequiredDescriptionDefault
namespaceNoMemory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace.

TDQS

A4.4/5.0
Behavior4/5

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

Annotations already declare readOnlyHint=true and openWorldHint=false, and the description reinforces 'Read-only' while adding real value: the exact contents loaded and a once-per-conversation constraint. It does not describe size/verbosity of the payload (e.g., whether summaries are truncated), so it stops short of full behavioral disclosure.

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

Conciseness4/5

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

Front-loaded with the imperative call-order instruction and frequency cap, then the payload contents. The final return-shape sentence is long but functional; only minor trimming would be possible without losing information.

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

Completeness5/5

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

With no output schema, the description compensates by enumerating the returned data keys (how_to_use, core, impressions, precious, glossary, notebook) and conditionally describing notebook. Combined with annotations and full schema coverage, an agent has everything needed to call it correctly.

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

Parameters3/5

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

Schema description coverage is 100% and the single namespace parameter is fully documented in the schema, so the baseline of 3 applies. The description never mentions namespace or the fixed-namespace override, adding nothing beyond the schema.

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

Purpose5/5

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

States a concrete verb (call first) and resource (the memory context: core memories, diary, summaries, notebook pages) so an agent knows exactly what it retrieves. It also distinguishes itself from siblings by promising a note on when to use the other memory tools, a role no sibling name implies.

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

Usage Guidelines5/5

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

Explicit ordering guidance: 'Call this first in every new conversation, before your first reply, even if the person only says hi,' plus the frequency constraint 'Once per conversation is enough.' That removes the main ambiguity (whether to call when the user's message looks trivial) and names the alternative path via the how_to_use note.

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. 24 tool updatesv2.1.0
    • Removeddiary_get
    • Addedforget
    • Removedglossary_set
    • Addedkeep_moment
    • Addedlearn_word
    • Addedlist_memories
    • Addedlog_conversation
    • Removedmemory_archive
    • Removedmemory_boot
    • Removedmemory_delete
    • Removedmemory_export
    • Removedmemory_get
    • Removedmemory_ingest
    • Removedmemory_list
    • Removedmemory_pin
    • Removedmemory_recall
    • Removedmemory_search
    • Removedmemory_supersede
    • Removedmemory_upsert
    • Addednotebook
    • Addedread_diary
    • Addedrecall
    • Addedremember
    • Addedwake_up
  2. 14 tool updatesv0.1.2
    • Changeddiary_get1 field changed
      • addedInput schema / properties / namespace / description
        Added value: +"Memory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace."
    • Changedglossary_set5 fields changed
      • addedInput schema / properties / aliases / description
        Added value: +"Other spellings or names that should match this term. Replaces any existing aliases."
      • addedInput schema / properties / definition / description
        Added value: +"What the term means."
      • addedInput schema / properties / examples / description
        Added value: +"Example sentences using the term. Replaces any existing examples."
      • addedInput schema / properties / namespace / description
        Added value: +"Memory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace."
      • addedInput schema / properties / term / description
        Added value: +"The word or phrase exactly as it is used."
    • Changedmemory_archive2 fields changed
      • addedInput schema / properties / id / description
        Added value: +"Memory id (e.g. from memory_search, memory_recall or memory_list)."
      • addedInput schema / properties / namespace / description
        Added value: +"Memory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace."
    • Changedmemory_boot1 field changed
      • addedInput schema / properties / namespace / description
        Added value: +"Memory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace."
    • Changedmemory_delete2 fields changed
      • addedInput schema / properties / id / description
        Added value: +"Memory id (e.g. from memory_search, memory_recall or memory_list)."
      • addedInput schema / properties / namespace
        Added value: +{
        +  "description": "Memory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace.",
        +  "type": "string"
        +}
    • Changedmemory_export3 fields changed
      • addedInput schema / properties / format / description
        Added value: +"Output format. Only json is supported (default)."
      • addedInput schema / properties / namespace / description
        Added value: +"Memory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace."
      • addedInput schema / properties / type / description
        Added value: +"Only export one memory type (fact, event, preference, relationship, boundary, habit, decision, note). Omit for all."
    • Changedmemory_get2 fields changed
      • addedInput schema / properties / id / description
        Added value: +"Memory id (e.g. from memory_search, memory_recall or memory_list)."
      • addedInput schema / properties / namespace
        Added value: +{
        +  "description": "Memory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace.",
        +  "type": "string"
        +}
    • Changedmemory_ingest7 fields changed
      • addedInput schema / properties / auto_extract / description
        Added value: +"Accepted for compatibility only; it is not stored and does not change processing."
      • addedInput schema / properties / conversation_id / description
        Added value: +"Conversation to append to. Defaults to the namespace's shared default conversation."
      • addedInput schema / properties / messages / description
        Added value: +"Messages in chronological order."
      • addedInput schema / properties / messages / items / properties / content / description
        Added value: +"Message text, or an OpenAI-style content parts array."
      • addedInput schema / properties / messages / items / properties / role / description
        Added value: +"One of user, assistant, system, tool. Other roles are dropped."
      • addedInput schema / properties / namespace / description
        Added value: +"Memory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace."
      • addedInput schema / properties / source / description
        Added value: +"Label for where the messages came from. Defaults to 'mcp'."
    • Changedmemory_list7 fields changed
      • addedInput schema / properties / cursor / description
        Added value: +"Legacy paging cursor; only used when the lifecycle store is disabled. Prefer offset."
      • addedInput schema / properties / include_ids / description
        Added value: +"Legacy mode only: also return the bare id list."
      • addedInput schema / properties / limit / description
        Added value: +"Page size. Defaults to 100."
      • addedInput schema / properties / namespace / description
        Added value: +"Memory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace."
      • addedInput schema / properties / offset / description
        Added value: +"Number of records to skip. Use paging.next_offset from the previous page."
      • addedInput schema / properties / status / description
        Added value: +"Only list memories with this status: active (default), archived or superseded."
      • addedInput schema / properties / type / description
        Added value: +"Only list one memory type (fact, event, preference, relationship, boundary, habit, decision, note)."
    • Changedmemory_pin3 fields changed
      • addedInput schema / properties / content / description
        Added value: +"The moment to keep, self-contained and readable on its own."
      • addedInput schema / properties / context_message_ids / description
        Added value: +"Ids of stored messages (e.g. message_ids from memory_ingest) to keep as surrounding context."
      • addedInput schema / properties / namespace / description
        Added value: +"Memory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace."
    • Changedmemory_recall5 fields changed
      • addedInput schema / properties / k / description
        Added value: +"Maximum number of memory hits. Defaults to 20."
      • addedInput schema / properties / min_score / description
        Added value: +"Relevance floor applied after reranking. Defaults to the server setting (0.15)."
      • addedInput schema / properties / namespace / description
        Added value: +"Memory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace."
      • addedInput schema / properties / query / description
        Added value: +"The question or topic to recall memories for."
      • addedInput schema / properties / types / description
        Added value: +"Only recall these memory types (fact, event, preference, relationship, boundary, habit, decision, note). Omit for all types."
    • Changedmemory_search4 fields changed
      • addedInput schema / properties / namespace / description
        Added value: +"Memory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace."
      • addedInput schema / properties / query / description
        Added value: +"What to look for, in natural language or keywords."
      • addedInput schema / properties / top_k / description
        Added value: +"Maximum number of records to return. Defaults to the server setting (50)."
      • addedInput schema / properties / types / description
        Added value: +"Only return these memory types (fact, event, preference, relationship, boundary, habit, decision, note). Omit for all types."
    • Changedmemory_supersede8 fields changed
      • addedInput schema / properties / namespace / description
        Added value: +"Memory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace."
      • addedInput schema / properties / new_content / description
        Added value: +"The up-to-date memory text."
      • addedInput schema / properties / new_fact_key / description
        Added value: +"fact_key for the new entry. Defaults to the old entry's fact_key."
      • addedInput schema / properties / new_type / description
        Added value: +"One of fact, event, preference, relationship, boundary, habit, decision, note. Other values become fact (default)."
      • addedInput schema / properties / old_id / description
        Added value: +"Id of the memory being replaced."
      • addedInput schema / properties / reason / description
        Added value: +"Short note on why the old memory is outdated; stored with the chain."
      • addedInput schema / properties / response_tendency / description
        Added value: +"E-axis: how to respond when the new memory fires"
      • addedInput schema / properties / valid_as_of / description
        Added value: +"When the new fact became true (ISO date or datetime)."
    • Changedmemory_upsert10 fields changed
      • changedInput schema / properties / authored_by / description
        Previous value: -"E-axis signature; only honored on hand sources (mcp/manual/api)"New value: +"E-axis signature; only honored on hand sources (mcp/manual/api/remember_now)"
      • addedInput schema / properties / confidence / description
        Added value: +"0 to 1, how sure you are it is true. Defaults to 0.8."
      • addedInput schema / properties / content / description
        Added value: +"The memory text, one self-contained statement."
      • addedInput schema / properties / fact_key / description
        Added value: +"Stable key for this fact, e.g. 'user:favorite_coffee'. Reusing a key updates that memory. Facts about the outside world rather than the user use the prefix 'world_fact:'."
      • addedInput schema / properties / importance / description
        Added value: +"0 to 1, how much this matters. Defaults to 0.6."
      • addedInput schema / properties / namespace / description
        Added value: +"Memory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace."
      • addedInput schema / properties / source / description
        Added value: +"Who is writing. Leave unset (defaults to 'mcp'). authored_by is only stored when source is mcp, manual, api or remember_now."
      • addedInput schema / properties / tags / description
        Added value: +"Free-form labels."
      • addedInput schema / properties / type / description
        Added value: +"One of fact, event, preference, relationship, boundary, habit, decision, note. Other values become fact (default)."
      • addedInput schema / properties / valid_as_of / description
        Added value: +"When the fact became true (ISO date or datetime). Used as the event date in recall."
  3. 14 tool updatesv0.1.0
    • First observeddiary_get
    • First observedglossary_set
    • First observedmemory_archive
    • First observedmemory_boot
    • First observedmemory_delete
    • First observedmemory_export
    • First observedmemory_get
    • First observedmemory_ingest
    • First observedmemory_list
    • First observedmemory_pin
    • First observedmemory_recall
    • First observedmemory_search
    • First observedmemory_supersede
    • First observedmemory_upsert

TDQS

A4.4/5.0

Scored across 10 tools

Disambiguation4/5

Most tools have clearly distinct roles (wake_up loads context, recall searches, forget deletes, notebook is a self-authored scratchpad), and descriptions actively disambiguate close pairs like remember vs keep_moment and recall vs list_memories. There is still mild overlap between remember and keep_moment, and between recall and list_memories, so an agent could occasionally misselect.

Naming Consistency4/5

All names are snake_case and most follow a verb or verb_noun pattern (recall, remember, forget, keep_moment, learn_word, read_diary, log_conversation, list_memories). The two exceptions, wake_up and notebook, are evocative but break the verb-first pattern slightly.

Tool Count5/5

Ten tools is a well-scoped set for a personal-memory server, with each tool covering a distinct part of the memory lifecycle. Nothing feels redundant or padded.

Completeness4/5

Coverage is strong: context loading, search, create/update/delete of memories, curated moments, glossary, diary reading, conversation logging, listing, and notebook CRUD are all present. Minor gaps exist, such as no explicit way to edit or remove a kept moment or an individual diary entry, but agents can work around these.

Maintenance

ActivityActive
ResponsivenessWithin a week

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    Provides cross-device access to a persistent knowledge graph via Cloudflare Workers, enabling memory storage and retrieval through both MCP protocol and REST API with full-text search capabilities.
    -
  • A
    license
    Not graded
    quality
    A
    maintenance
    Self-hosted semantic memory layer for Claude and MCP-compatible AI clients. Store notes, search by meaning not keywords, and recall relevant context automatically across sessions. Runs free on Cloudflare Workers, D1, Vectorize, and Workers AI
    4 npm
    840
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Self-hosted semantic memory for AI agents. Save worklogs, decisions, and notes via MCP, then recall them across sessions by meaning rather than keyword. Backed by Postgres + pgvector with local embeddings (multilingual-e5-base).
    1
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Provides persistent memory for MCP clients, enabling them to remember user preferences and behaviors across conversations using vector search and Cloudflare's infrastructure.
    13 npm
    MIT