Aelios
Aelios gives an AI assistant persistent, searchable long-term memory across conversations and clients, with tools to save, recall, organize, and curate that memory.
Load conversation context: Retrieve core memories, recent diary and summary entries, kept moments, private vocabulary, and notebook page names at the start of a conversation.
Recall relevant knowledge: Search memories and private terms by query, with type, relevance, result-count, and history options; recalled memories are protected from expiration.
Remember and update information: Save facts, events, preferences, relationships, boundaries, habits, decisions, notes, and world knowledge with optional tags, confidence, importance, and dates; replace outdated memories while preserving earlier versions.
Curate memories: Preserve meaningful moments in the person’s own words, browse active/archived/superseded memories, and archive or permanently erase unwanted memories.
Learn private language: Teach and update nicknames, in-jokes, project names, aliases, definitions, and examples so they can be recognized during recall.
Read diaries and trace origins: Review daily or weekly impressions and inspect where a memory came from before relying on its details.
Feed nightly consolidation: Incrementally log conversations for later diary writing and memory extraction, with duplicate lines skipped; gateway-recorded chats do not need this.
Maintain working notebooks: List, read, create, rewrite, append to, and delete named pages for ongoing notes; pages are not automatically recalled, modified overnight, or expired.
Separate memory spaces: Use namespaces to keep different memory spaces apart unless the API key is bound to a fixed space.
Integrates with Cloudflare services including Workers AI, AI Gateway, D1, and Vectorize for memory storage, embeddings, optional full chat forwarding, and overnight consolidation.
Supports OpenAI-compatible chat completions and the OpenAI Responses API, forwarding to OpenAI models and enabling memory for Codex.
Provides a Telegram integration branch (tg-bot), though it is noted as stuck at 2026-.
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 modelLet 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).
Click Fork at the top of this page.
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 tonpm ciand the deploy command tonpm run deploy. The deploy command creates the D1 database, the Vectorize index and the queue for you.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.devDon't run a bare wrangler deploy — it won't create the databases.
Not recommended: the one-click button.
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>/adminEnter your Worker address and the key from step 1, then go to Settings.
Upstream: your Cloudflare account ID (32 characters). For full chat forwarding, also add a
CLOUDFLARE_API_TOKENWorker secret.Assistant: click Add assistant, for example:
Field
What it means
Example
Name
The segment in the URL, lowercase English
coderPrimary model
Only these models remember and recall
anthropic/claude-opus-4-5Keys
Who may use this assistant
check the primary key
Click Save.
One assistant, one address. Name it coder and the address is:
https://<your Worker address>/coder/v1Only 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, … |
|
Claude Code |
|
Codex |
|
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:
Open your fork on GitHub and click Sync fork → Update branch.
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.
Fork this repo.
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_NAMEandCMP_VECTORIZE_NAMEwith those names. Otherwise the build creates new, empty ones and your memories look gone (they're still in the old database).In Settings → Build, click Disconnect, then Connect and pick your fork, with build command
npm ciand deploy commandnpm run deploy.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:
Open Nightly and check the space shown under Viewing at the top left.
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.
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.
Each press handles one batch (
DREAM_MAX_MESSAGESmessages, 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:
Cloudflare → AI → AI Gateway: create a gateway and store each vendor's key under it.
Add the
CLOUDFLARE_API_TOKENWorker secret.In
/adminSettings, 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"):
/admin→ Settings → Models & upstream → ChatGPT plan → Manage → Continue with ChatGPT. Sign in and approve.Your browser then lands on a
127.0.0.1page that fails to load. That is expected: copy the whole address from the address bar, paste it into the box in/adminand press Finish sign-in.Use models named
chatgpt/<model>. The Test button lists what your account can use. To give one memory, addchatgpt/*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_getandmemory_export, add&tools=allto 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 barewrangler 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, notclaude-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
How the gateway routes, remembers, and recalls: docs/memory-gateway.md
What happens to requests, how thinking is handled: docs/request-contract.md
Which secrets are required: SECRETS.md
For maintainers: endpoints, MCP tools, and the memory lifecycle — see the sections below.
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 |
|
D1 |
|
Vectorize |
|
Queue |
|
Embedding |
|
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 check |
GET |
| Admin panel |
GET |
| Model list (the upstream catalog, or your saved model list) |
POST |
| OpenAI-compatible chat |
POST |
| Anthropic messages |
POST |
| OpenAI responses |
GET |
| Model picker for |
POST |
| Connectivity test for one model (owner key): |
GET / POST |
| ChatGPT plan sign-in (owner key): |
GET |
| Authorized assistant routing hints only; read-only, no outgoing requests |
POST |
| Recall / optional recording for clients that send model requests themselves |
GET / POST |
| MCP memory tools |
GET / POST |
| List / create memories |
POST |
| Dynamic recall (preferred by hooks) |
POST |
| Raw search (unmetered) |
POST |
| Ingest raw chats |
GET |
| Cold-start pack |
GET |
| Diary |
POST |
| Rewrite one diary entry from that day's chat: |
GET |
| Dream runs from the last 7 days, the active task, cursors |
POST |
| Run Dream by hand: |
POST |
| Mark a task unconfirmed for over 20 minutes as interrupted: |
GET / POST / DELETE |
| Precious originals / glossary |
GET / POST / PATCH / DELETE |
| Notebook pages; |
GET / POST |
| Review queue; |
GET |
| Export the space's memories and precious lines ( |
GET |
| Earlier versions of a memory rewritten in place |
GET / POST |
| Import: |
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;
forcedoes 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/resolvewith{"run_id":"…"}, samememory:writescope) 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-rewritewith{"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 verifyTests 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 toolsforgetADestructiveIdempotent
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 } }.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | Memory id (from recall or list_memories). | |
| namespace | No | Memory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace. | |
| permanent | No | true erases the memory for good. Default false: archive it, which can be undone. |
TDQS
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.
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.
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.
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.
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.
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 }.
| Name | Required | Description | Default |
|---|---|---|---|
| content | Yes | The moment, in their words where it matters; readable on its own later. | |
| namespace | No | Memory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace. | |
| context_message_ids | No | Optional ids of logged messages around it (message_ids from log_conversation). |
TDQS
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.
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.
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.
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.
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.
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_wordADestructiveIdempotent
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 }.
| Name | Required | Description | Default |
|---|---|---|---|
| term | Yes | The word or phrase exactly as it is used. | |
| aliases | No | Other spellings or forms that should match. Replaces any existing aliases. | |
| examples | No | Example sentences using it. Replaces any existing examples. | |
| namespace | No | Memory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace. | |
| definition | Yes | What it means between you. |
TDQS
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.
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.
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.
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.
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.
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_memoriesARead-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.
| Name | Required | Description | Default |
|---|---|---|---|
| type | No | Only list one memory type (fact, event, preference, relationship, boundary, habit, decision, note). | |
| limit | No | Page size. Defaults to 100. | |
| offset | No | Records to skip; use paging.next_offset from the previous page. | |
| status | No | active (default), archived or superseded. | |
| namespace | No | Memory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace. |
TDQS
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.
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.
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.
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.
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.
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_conversationAIdempotent
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 } }.
| Name | Required | Description | Default |
|---|---|---|---|
| messages | Yes | The person's and your messages, oldest first. | |
| namespace | No | Memory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace. | |
| conversation_id | No | The conversation_id returned by your first call in this conversation. Leave it out the first time. |
TDQS
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.
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.
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.
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.
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.
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.
notebookADestructive
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 }.
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | Page name, up to 60 characters, e.g. 经济师进度. Needed for every action but list. | |
| action | Yes | list, read, write (replace the whole page), append or delete. | |
| content | No | write: the whole new page. append: the text to add at the end. | |
| namespace | No | Memory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace. |
TDQS
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.
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.
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.
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.
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.
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_diaryARead-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).
| Name | Required | Description | Default |
|---|---|---|---|
| date | No | YYYY-MM-DD for one day. Days already rolled into a week return that week. | |
| week | No | ISO week label for a week, e.g. 2026-W29. | |
| memory_id | No | A memory id from recall or list_memories. Returns where it came from instead of a day's diary. | |
| namespace | No | Memory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace. |
TDQS
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.
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.
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.
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.
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.
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.
recallARead-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.
| Name | Required | Description | Default |
|---|---|---|---|
| k | No | Maximum number of memory hits. Defaults to 20. | |
| query | Yes | What to recall, in the person's words or your own. | |
| types | No | Only recall these memory types (fact, event, preference, relationship, boundary, habit, decision, note). Omit for all types. | |
| min_score | No | Relevance floor after reranking. Defaults to the server setting (0.15); lower it to see more. | |
| namespace | No | Memory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace. | |
| include_history | No | When true, also return older versions that were replaced. Default false. |
TDQS
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.
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.
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.
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.
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.
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 } }.
| Name | Required | Description | Default |
|---|---|---|---|
| tags | No | Free-form labels. | |
| type | No | One 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. | |
| reason | No | With replaces: a short note on what changed. | |
| content | Yes | One self-contained sentence to remember. | |
| fact_key | No | Optional 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. | |
| replaces | No | Id of the memory this one updates (from recall). The old version is kept as history. | |
| namespace | No | Memory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace. | |
| confidence | No | 0 to 1, how sure you are. Defaults to 0.8. | |
| importance | No | 0 to 1, how much this matters. Defaults to 0.6. | |
| authored_by | No | Optional signature marking this as hand-written; it ranks above memories distilled overnight. | |
| valid_as_of | No | When this became true (ISO date or datetime), if it is not today. | |
| response_tendency | No | Optional: how you want to respond when this memory comes up. |
TDQS
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.
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.
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.
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.
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.
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_upARead-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).
| Name | Required | Description | Default |
|---|---|---|---|
| namespace | No | Memory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace. |
TDQS
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.
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.
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.
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.
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.
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.
24 tool updates
v2.1.0- Removed
diary_get - Added
forget - Removed
glossary_set - Added
keep_moment - Added
learn_word - Added
list_memories - Added
log_conversation - Removed
memory_archive - Removed
memory_boot - Removed
memory_delete - Removed
memory_export - Removed
memory_get - Removed
memory_ingest - Removed
memory_list - Removed
memory_pin - Removed
memory_recall - Removed
memory_search - Removed
memory_supersede - Removed
memory_upsert - Added
notebook - Added
read_diary - Added
recall - Added
remember - Added
wake_up
14 tool updates
v0.1.2- Changed
diary_get1 field changed- added
Input schema / properties / namespace / descriptionAdded value: +"Memory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace."
- Changed
glossary_set5 fields changed- added
Input schema / properties / aliases / descriptionAdded value: +"Other spellings or names that should match this term. Replaces any existing aliases." - added
Input schema / properties / definition / descriptionAdded value: +"What the term means." - added
Input schema / properties / examples / descriptionAdded value: +"Example sentences using the term. Replaces any existing examples." - added
Input schema / properties / namespace / descriptionAdded value: +"Memory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace." - added
Input schema / properties / term / descriptionAdded value: +"The word or phrase exactly as it is used."
- Changed
memory_archive2 fields changed- added
Input schema / properties / id / descriptionAdded value: +"Memory id (e.g. from memory_search, memory_recall or memory_list)." - added
Input schema / properties / namespace / descriptionAdded value: +"Memory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace."
- Changed
memory_boot1 field changed- added
Input schema / properties / namespace / descriptionAdded value: +"Memory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace."
- Changed
memory_delete2 fields changed- added
Input schema / properties / id / descriptionAdded value: +"Memory id (e.g. from memory_search, memory_recall or memory_list)." - added
Input schema / properties / namespaceAdded value: +{ + "description": "Memory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace.", + "type": "string" +}
- Changed
memory_export3 fields changed- added
Input schema / properties / format / descriptionAdded value: +"Output format. Only json is supported (default)." - added
Input schema / properties / namespace / descriptionAdded value: +"Memory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace." - added
Input schema / properties / type / descriptionAdded value: +"Only export one memory type (fact, event, preference, relationship, boundary, habit, decision, note). Omit for all."
- Changed
memory_get2 fields changed- added
Input schema / properties / id / descriptionAdded value: +"Memory id (e.g. from memory_search, memory_recall or memory_list)." - added
Input schema / properties / namespaceAdded value: +{ + "description": "Memory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace.", + "type": "string" +}
- Changed
memory_ingest7 fields changed- added
Input schema / properties / auto_extract / descriptionAdded value: +"Accepted for compatibility only; it is not stored and does not change processing." - added
Input schema / properties / conversation_id / descriptionAdded value: +"Conversation to append to. Defaults to the namespace's shared default conversation." - added
Input schema / properties / messages / descriptionAdded value: +"Messages in chronological order." - added
Input schema / properties / messages / items / properties / content / descriptionAdded value: +"Message text, or an OpenAI-style content parts array." - added
Input schema / properties / messages / items / properties / role / descriptionAdded value: +"One of user, assistant, system, tool. Other roles are dropped." - added
Input schema / properties / namespace / descriptionAdded value: +"Memory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace." - added
Input schema / properties / source / descriptionAdded value: +"Label for where the messages came from. Defaults to 'mcp'."
- Changed
memory_list7 fields changed- added
Input schema / properties / cursor / descriptionAdded value: +"Legacy paging cursor; only used when the lifecycle store is disabled. Prefer offset." - added
Input schema / properties / include_ids / descriptionAdded value: +"Legacy mode only: also return the bare id list." - added
Input schema / properties / limit / descriptionAdded value: +"Page size. Defaults to 100." - added
Input schema / properties / namespace / descriptionAdded value: +"Memory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace." - added
Input schema / properties / offset / descriptionAdded value: +"Number of records to skip. Use paging.next_offset from the previous page." - added
Input schema / properties / status / descriptionAdded value: +"Only list memories with this status: active (default), archived or superseded." - added
Input schema / properties / type / descriptionAdded value: +"Only list one memory type (fact, event, preference, relationship, boundary, habit, decision, note)."
- Changed
memory_pin3 fields changed- added
Input schema / properties / content / descriptionAdded value: +"The moment to keep, self-contained and readable on its own." - added
Input schema / properties / context_message_ids / descriptionAdded value: +"Ids of stored messages (e.g. message_ids from memory_ingest) to keep as surrounding context." - added
Input schema / properties / namespace / descriptionAdded value: +"Memory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace."
- Changed
memory_recall5 fields changed- added
Input schema / properties / k / descriptionAdded value: +"Maximum number of memory hits. Defaults to 20." - added
Input schema / properties / min_score / descriptionAdded value: +"Relevance floor applied after reranking. Defaults to the server setting (0.15)." - added
Input schema / properties / namespace / descriptionAdded value: +"Memory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace." - added
Input schema / properties / query / descriptionAdded value: +"The question or topic to recall memories for." - added
Input schema / properties / types / descriptionAdded value: +"Only recall these memory types (fact, event, preference, relationship, boundary, habit, decision, note). Omit for all types."
- Changed
memory_search4 fields changed- added
Input schema / properties / namespace / descriptionAdded value: +"Memory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace." - added
Input schema / properties / query / descriptionAdded value: +"What to look for, in natural language or keywords." - added
Input schema / properties / top_k / descriptionAdded value: +"Maximum number of records to return. Defaults to the server setting (50)." - added
Input schema / properties / types / descriptionAdded value: +"Only return these memory types (fact, event, preference, relationship, boundary, habit, decision, note). Omit for all types."
- Changed
memory_supersede8 fields changed- added
Input schema / properties / namespace / descriptionAdded value: +"Memory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace." - added
Input schema / properties / new_content / descriptionAdded value: +"The up-to-date memory text." - added
Input schema / properties / new_fact_key / descriptionAdded value: +"fact_key for the new entry. Defaults to the old entry's fact_key." - added
Input schema / properties / new_type / descriptionAdded value: +"One of fact, event, preference, relationship, boundary, habit, decision, note. Other values become fact (default)." - added
Input schema / properties / old_id / descriptionAdded value: +"Id of the memory being replaced." - added
Input schema / properties / reason / descriptionAdded value: +"Short note on why the old memory is outdated; stored with the chain." - added
Input schema / properties / response_tendency / descriptionAdded value: +"E-axis: how to respond when the new memory fires" - added
Input schema / properties / valid_as_of / descriptionAdded value: +"When the new fact became true (ISO date or datetime)."
- Changed
memory_upsert10 fields changed- changed
Input schema / properties / authored_by / descriptionPrevious 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)" - added
Input schema / properties / confidence / descriptionAdded value: +"0 to 1, how sure you are it is true. Defaults to 0.8." - added
Input schema / properties / content / descriptionAdded value: +"The memory text, one self-contained statement." - added
Input schema / properties / fact_key / descriptionAdded 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:'." - added
Input schema / properties / importance / descriptionAdded value: +"0 to 1, how much this matters. Defaults to 0.6." - added
Input schema / properties / namespace / descriptionAdded value: +"Memory space to use. Defaults to 'default'. Ignored when the API key is bound to a fixed namespace." - added
Input schema / properties / source / descriptionAdded value: +"Who is writing. Leave unset (defaults to 'mcp'). authored_by is only stored when source is mcp, manual, api or remember_now." - added
Input schema / properties / tags / descriptionAdded value: +"Free-form labels." - added
Input schema / properties / type / descriptionAdded value: +"One of fact, event, preference, relationship, boundary, habit, decision, note. Other values become fact (default)." - added
Input schema / properties / valid_as_of / descriptionAdded value: +"When the fact became true (ISO date or datetime). Used as the event date in recall."
14 tool updates
v0.1.0- First observed
diary_get - First observed
glossary_set - First observed
memory_archive - First observed
memory_boot - First observed
memory_delete - First observed
memory_export - First observed
memory_get - First observed
memory_ingest - First observed
memory_list - First observed
memory_pin - First observed
memory_recall - First observed
memory_search - First observed
memory_supersede - First observed
memory_upsert
TDQS
Scored across 10 tools
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.
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.
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.
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
Related MCP Connectors
Persistent memory for AI agents across Claude, ChatGPT and any MCP client.
Persistent memory for AI assistants. Save once; recall from Claude, ChatGPT, or any MCP client.
Hosted memory for AI agents over MCP. One memory shared by all your agents.
One memory, every AI. A shared, user-owned markdown memory your AI clients read and write over MCP.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceProvides 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.-
- AlicenseNot gradedqualityAmaintenanceSelf-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 AI4 npm840MIT
- AlicenseNot gradedqualityDmaintenanceSelf-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).1MIT
- AlicenseNot gradedqualityCmaintenanceProvides persistent memory for MCP clients, enabling them to remember user preferences and behaviors across conversations using vector search and Cloudflare's infrastructure.13 npmMIT