Skip to main content
Glama
Recall by Polign

Recall by Polign

Official

Polign Recall

Recall gives an agent memory and state that survive the conversation and the process. Memory is what the agent knows: facts a user stated, with every correction kept, so the agent can say what it believes now, what it believed before, and why. State is where the agent is: its progress, its notes to its next instance, and the tool calls it had in flight, so a run that crashes or moves machines resumes from its own records.

Recall is a Go library, a recall binary that serves the same operations as MCP tools and as HTTP, and a Python client. It stores everything in a database you run: polign_db, PostgreSQL, MongoDB or Qdrant. Apache 2.0.

Recall, mem0 and Zep answering questions about a user whose facts changed over nine months

One user over nine months, three homes, three employers, three work emails, six questions, Claude Opus 5.5 extracting, answering and judging for all three systems: Recall 18/18, mem0 18/18, Zep 12/18. Tokens to save one message: Recall 3.0k, mem0 12.7k, Zep 14.7k.

The code to the Recall repository.

Install

pip install polign-recall          # the Python client, the recall binary, and the database it runs
brew install polign/tap/recall     # the same for Homebrew
go install github.com/Polign/recall/cmd/recall@latest   # the binary alone; it fetches the database on first use

Then give it to the agent you use:

claude mcp add recall -- recall mcp -write      # Claude Code

Add to Cursor · Add to VS Code · any other MCP host: command recall, arguments mcp -write (details).

With nothing configured, memory lives in a local database in ~/.local/share/recall, started on first use and shared by every agent on the machine. No model and no API key are needed to start. To keep memory in a database you already run, see Backends.

Related MCP server: engram-mcp

What a correction looks like

Every change is kept. Three commands read the record:

$ recall history "which editor do I use"
user preferred editor
  believed now: user preferred editor: zed
  2026-09-01 10:00  stated, user_stated
      + user preferred editor: vim
  2026-09-20 10:00  replaced, user_stated
      - user preferred editor: vim
      + user preferred editor: emacs
  2026-10-05 10:00  replaced, user_stated
      - user preferred editor: emacs
      + user preferred editor: zed

$ recall ask -as-of 2026-09-25 "which editor do I use"
Believed as of 2026-09-25 00:00:
user preferred editor: emacs  (since 2026-09-20)
  replaced: vim  (since 2026-09-01)

$ recall diff -from 2026-09-15 -to 2026-10-31
Changed between 2026-09-15 00:00 and 2026-10-31 00:00:
- user home city: Lisbon
+ user home city: Porto
- user preferred editor: vim
+ user preferred editor: zed

Why Recall

  • Corrections are records, not overwrites. A new value replaces the old one by a rule you can read, and every answer arrives with what it replaced.

  • Any moment is readable. as_of, history and diff say what the agent believed then and when that changed.

  • Every answer has a source. recall explain shows the message a fact came from, the rule that decided it, and its history.

  • Agents resume from records. A crashed or moved agent gets its working state, recent turns and unfinished tool calls back, not a snapshot.

  • Your storage, your rules. Memory lives in a database you already run, and the vocabulary of what gets remembered is yours to define or leave open.

Quickstart

Python 3.10 or later. Save a preference, then correct it:

pip install polign-recall
python - <<'PY'
from polign_recall import Client

with Client(local_dir="./recall-data", typed=True) as memory:
    memory.remember("user", "prefers_editor", "vim")
    memory.remember("user", "prefers_editor", "neovim")
PY

A second process reads the current value, the history, and what was believed before the correction:

python - <<'PY'
from polign_recall import Client

with Client(local_dir="./recall-data", typed=True) as memory:
    print(memory.recall("user", "prefers_editor")[0].value)   # neovim

    events = memory.history("user", "prefers_editor")
    print([e.value for e in events])                           # ['vim', 'neovim']

    before = memory.recall("user", "prefers_editor", as_of=events[0].observed_at)
    print(before[0].value)                                      # vim
PY

The first client to open ./recall-data starts a local database for it and later clients share it; the memories stay there after the program exits. A bare Client() uses ~/.local/share/recall, the memory every agent on the machine shares. The Python client guide covers the rest: plain-text memory with a model, forgetting, history, and resuming an agent.

How memory works

A memory is a subject, a predicate and a typed value: user, prefers_editor, neovim. Predicates live in a registry that says what type a value has, whether the predicate holds one value or many, and which predicates it contradicts: dislikes excludes likes, gave_away excludes owns. A single-valued predicate replaces its value on a new statement; a multi-valued one accumulates. Forgetting records a withdrawal; nothing is deleted. Recall ships starter registries for coding, personal assistant, support, sales and voice agents, and you can change a registry later without touching what was already remembered.

You do not have to define predicates. With an open vocabulary the first use of a predicate defines it, and with a model configured the MCP tools take plain text and no predicates appear anywhere:

recall setup -extract-model anthropic:claude-haiku-4-5-20251001
remember("I switched from helix to zed last week")
recall("which editor do I use?")  ->  "user prefers editor: zed" (before: helix)
forget("my editor")

The model decides how each statement is filed. Once filed, replacement follows the predicate's rule, every filing is recorded, and a wrong filing is corrected with one event that every later answer follows. No model reconciles memory on its own: Recall applies the registry's rules, shows what may conflict, and lets the agent confirm the rest, so every correction reads back to the rule or statement that made it. recall mcp -typed serves the typed tools (remember(subject, predicate, value)) instead. The developer reference has the details and the Memory API is the contract.

State

The second half of Recall, with its own contract, docs/state-api-v1.md. An agent writes down where it is as it works, and a new process resumes from those records instead of from a snapshot:

  • Working state: goal, plan, progress, focus, decisions, open questions.

  • Turns, verbatim, and large tool outputs stored by reference.

  • Pointers to where the work lives: a branch, an object key, a process.

  • Actions: each tool call that touches the world, recorded before it runs and closed with its result, so a crash between the two is visible and the next resume lists the call as unconfirmed instead of repeating it.

Resume takes a lease on the agent id, so one process acts for an agent at a time, rebuilds the context within a token budget, and renders it as one briefing for the model:

agent, err := client.Resume(ctx, recall.ResumeRequest{AgentID: "coder-1", TokenBudget: 8000})
if err != nil {
    return err
}
defer agent.Release(context.Background())

briefing := agent.Resumed().Briefing // hand this to the model

In Python, an agent remembers a fact and records where it is, the process is killed, and a new process resumes from the records:

import os, signal
from polign_recall import Client

with Client(local_dir="./recall-data", agent=True, typed=True) as client:
    client.remember("user", "project_constraint", "deploy only on weekdays after 18:00 UTC")
    with client.resume("coder-1") as agent:
        agent.update_working_state(goal="Move billing to the v2 API",
                                   plan=["find call sites", "migrate them", "run the tests"])
        agent.record_turn("user", "Start with the charge endpoint.")
        agent.milestone("call sites found", progress="12 call sites listed")
        os.kill(os.getpid(), signal.SIGKILL)   # dies here, lease unreleased
import time
from polign_recall import Client

with Client(local_dir="./recall-data", agent=True, typed=True) as client:
    agent = client.resume("coder-1", token_budget=8000, defer_lease=True)
    print(agent.context.briefing)   # at once: the goal, plan, milestone, turn, and constraint
    while not agent.acquire():      # False until the dead process's lease expires
        time.sleep(1)
    agent.record_turn("assistant", "Picking up at the charge endpoint.")

Without defer_lease=True, resume raises lease_held until the crashed process's lease expires (Python client guide).

The same operations are MCP tools (agent_resume, update_working_state, record_turn, begin_action, ...) and, on recall serve, HTTP routes at POST /v1/agent/<verb>. Over HTTP the server holds the lease between requests: resume returns an epoch and every write carries it, so a stale process cannot write over its successor. The State API is beta; the records it writes are stable (STABILITY.md). The resume example kills an agent mid-task and continues it in a new process.

Serving many agents

recall mcp is one agent, one process. recall serve is the same memory and state for many agents over HTTP, each inside the namespace its key names. The server holds the database credentials; agents hold Recall keys.

recall serve -backend polign -url http://polign:23000 -bootstrap-key-file admin.key
recall key create -backend polign -url http://polign:23000 -namespace acme:agent-7 -expires 168h

Each namespace gets its own collection, so nothing a caller sends can reach another namespace's records. POST /mcp is MCP over streamable HTTP; POST /v1/<tool> takes a memory tool's arguments as the body, and POST /v1/agent/<verb> a state tool's. Any stdio MCP client reaches the server through recall connect with RECALL_URL and RECALL_API_KEY set.

On Kubernetes a pod needs no key at all. With recall serve -kubernetes, it posts its projected service account token and gets a short-lived key fixed to its own agent id, which recall connect and the Python client obtain and renew by themselves. The Helm chart is charts/recall in Polign/polign; the agent-sandbox demo runs it on kind.

Backends

local (default)

polign_db

PostgreSQL + pgvector

MongoDB

Qdrant

RECALL_BACKEND

local

polign

pgvector

mongodb

qdrant

RECALL_BACKEND_URL

a directory

http://host:23000

postgres://user:pw@host/db

mongodb://user:pw@host/db

http://host:6333

Memory, history, as-of

yes

yes

yes

yes

yes

Keyword search

yes

yes

yes

yes

no

Cached reads

yes

yes

yes

yes

no

State API (leases)

yes

yes

yes

yes

no

export RECALL_BACKEND=pgvector RECALL_BACKEND_URL=postgres://user:password@localhost:5432/mydb
recall mcp -write

Three settings name the database for every command: -backend, -url and -key, or the variables above. Everything else, including what each backend needs and how to add one, is in docs/backends.md.

Benchmark

LongMemEval user-facts subset, 267 questions about a user's own facts, preferences, updates and dates, with Claude Sonnet 5.5 as reader and judge and the upstream prompts:

What the reader is given

Score

Nothing

6.0

The full chat history

88.0

BM25 over sessions, top 10

89.9

Recall, built-in word search

88.8

Recall with a model embedder (OpenAI text-embedding-3-small, 512 dims)

92.9

Only the sessions that hold the answer

96.6

With word search Recall is even with BM25 overall and behind it on preference questions (70.0 against 83.3); a model embedder puts it ahead. Recall handed the reader about 28k tokens per question, against 44k for BM25 and 168k for the full history. The harness is in eval/longmemeval.

Integrations

Python

pip install polign-recall, then the client guide.

Go

go get github.com/Polign/recall, then the Go library guide.

MCP

Connect any agent to remember, recall and forget.

Claude Code

The Recall plugin: memory across coding sessions.

LangGraph

pip install recall-langgraph to resume LangGraph agents.

LiveKit, Vapi

recall-livekit and recall-vapi for caller memory in voice agents.

Pydantic AI

pip install recall-pydantic-ai for memory tools in Pydantic AI agents.

Vercel AI SDK

The Next.js chat example, one click to deploy.

OpenClaw

@polign/openclaw-recall on npm, the OpenClaw plugin.

Documentation

Developer reference · Memory API contract · State API contract · Backends · Connecting through MCP · Caching memory reads · Exporting and replaying history · What is stable and what is beta · Development guide

Support the project

If Recall kept your agent from acting on a stale fact, a star on this repository helps other people find it. Bugs, questions and ideas go in issues.

License

Apache 2.0.

Available Tools

5 tools
diffDiffA
Read-only

What was believed differently at one instant than at another: each thing that began or stopped being believed in between. Use it to say what changed over a period, such as since the last session or during an incident.

NameRequiredDescriptionDefault
toNothe later RFC3339 instant; omit for now
fromYesthe earlier RFC3339 instant, e.g. 2026-09-01T00:00:00Z

TDQS

A4/5.0
Behavior4/5

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

Annotations already establish readOnlyHint=true and openWorldHint=false, so safety is covered. The description earns its place by defining what the result actually contains (both things that began and things that stopped being believed), which matters because there is no output schema. It says nothing about ordering, volume, or handling of the open-ended 'to' default beyond what the schema notes.

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

Conciseness5/5

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

Two sentences, no filler: the definition comes first, the usage scenario second. Every clause carries meaning and nothing repeats the name or title.

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

Completeness4/5

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

For a two-parameter read-only tool with full schema coverage and no output schema, the description supplies the one thing structured data cannot: what a 'diff' means in this belief model and what the result enumerates. Only the ordering/shape of the returned set is left implicit.

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% and both parameters already document the RFC3339 format and the 'omit for now' behavior for `to`. The description reinforces the notion of two instants but adds no syntax or edge-case detail beyond the schema, so the baseline of 3 applies.

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

Purpose4/5

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

The description states a specific operation with a precise semantic definition: the set of things that began or stopped being believed between two instants. This distinguishes it in substance from remember/recall/forget, though it never names the closest sibling (history) so the agent must infer the boundary.

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 concrete when-to-use framing — 'to say what changed over a period, such as since the last session or during an incident' — which maps real scenarios onto the tool. It stops short of stating exclusions, e.g. when to prefer history over diff.

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

forgetForgetA

Stop believing what a description names, such as "my editor" or "that I live in Lisbon". Returns what was withdrawn. Nothing is deleted: it stays in the history, and remembering it again brings it back.

NameRequiredDescriptionDefault
textYeswhat to forget, described in words

TDQS

A3.9/5.0
Behavior4/5

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

With no annotations, the description carries the full burden and does meaningful work: it discloses that nothing is deleted, that the belief remains in history, that the operation is reversible via `remember`, and that it returns what was withdrawn. It omits what happens on a miss (forgetting something not held) and any auth/permission expectations.

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

Conciseness5/5

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

Three short sentences, each doing distinct work: what it does, what it returns, and the reversibility guarantee. No redundancy and the core action is front-loaded.

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

Completeness4/5

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

No output schema exists, and the description compensates by stating the return value and the non-destructive persistence semantics. For a one-parameter tool this is nearly complete; only edge-case behavior for a non-existent belief 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 single `text` parameter is already documented; the description adds real meaning by showing the expected form is a natural-language belief description rather than an ID or key, with two worked examples. That is more than the schema conveys.

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

Purpose4/5

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

The verb phrase "stop believing what a description names" plus concrete examples ("my editor", "that I live in Lisbon") makes the operation identifiable, and the closing clause implicitly contrasts it with the sibling `remember` which restores the belief. It is clear but phrased metaphorically rather than as a plain verb+resource statement, which costs a point.

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

Usage Guidelines3/5

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

Usage is only implied: an agent can infer you call this when a stored belief should no longer be held, and the description notes that remembering it again reverses the effect. There is no explicit when-to-use/when-not-to-use guidance and no direct routing against siblings like `recall` or `history`.

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

historyHistoryA
Read-only

How something remembered changed, in words: every statement about it, oldest first, each with what it began and ended believing, and what is believed now. Use it when the user asks what changed, when, or why something is believed, and to show a correction whole. Something since forgotten still has its history.

NameRequiredDescriptionDefault
questionYeswhat to trace, in words, such as "my editor"

TDQS

A4.1/5.0
Behavior5/5

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

Beyond the readOnlyHint and openWorldHint annotations, the description discloses return behavior in useful detail: every statement is returned oldest first, each with its beginning and ending beliefs, plus the current belief. It also adds the non-obvious edge case that forgotten items still retain history.

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

Conciseness4/5

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

The description is short and front-loads the core behavior before usage guidance and the forgotten-item edge case. The first sentence is dense and slightly abstract, but no sentence is clearly wasted.

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

Completeness5/5

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

For a simple one-parameter read-only tool with no output schema, the description is complete: it explains the return ordering and content, gives usage conditions, and covers the forgotten-item case. An agent has enough information 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?

There is only one required parameter and the schema already has full description coverage, including an example. The main description does not add syntax or format details beyond the schema, so the baseline of 3 is appropriate.

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

Purpose4/5

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

The description states a specific resource and scope: a chronological history of statements about something remembered, including past and current beliefs. It is clear enough to distinguish from a simple recall, though it does not explicitly name or contrast with the sibling tools.

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 clear usage cues: when the user asks what changed, when, or why something is believed, and when showing a correction whole. It also notes that forgotten items still have history. It does not explicitly say when to prefer a sibling like diff instead.

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

recallRecallA
Read-only

Ask what is remembered, in words, before assuming anything about the user. Answers are what is believed now, as sentences. Each lists under before what it replaced and when, so a correction comes with the answer, and under elsewhere anything else believed about the same thing in other words, such as a later dislike beside a like; the newer statement usually holds. days_ago says how long ago it was stated. A time named in the question, such as "last week", is searched first. Each also gives under said the sentence it was drawn from, as the user said it. Pass as_of to ask what was believed at an earlier instant. Leave out question to get everything believed about the user, a profile to start a conversation with. Pass since to get only what changed after then, newest first: at the start of a session, since the last one, it says what is new.

NameRequiredDescriptionDefault
as_ofNoRFC3339 instant, e.g. 2026-09-01T00:00:00Z. Answers as of then rather than now.
sinceNoRFC3339 instant. Only what was stated after then, each with what it replaced.
questionNowhat you want to know; omit for the user's profile, or with since for everything that changed

TDQS

A4.1/5.0
Behavior5/5

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

Annotations already cover the safety profile (readOnlyHint=true, openWorldHint=false), yet the description goes far beyond them: it discloses the returned fields (before, elsewhere, said, days_ago), the resolution heuristic that the newer statement usually holds, that a time named in the question is searched first, and that 'since' results come newest first. With no output schema, this disclosure is doing essential work.

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

Conciseness3/5

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

The opening sentence front-loads purpose and the key usage trigger, which is good, but the middle devolves into long run-on clauses ('Each lists under before what it replaced and when, so a correction comes with the answer, and under elsewhere anything else believed...') that are hard to parse. Some points are restated, e.g. 'since' is explained twice with slightly different framing.

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

Completeness4/5

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

For a zero-required-parameter read tool with no output schema, the description is substantially complete: it explains both intent variants and the shape of returned data. Gaps are the lack of sibling differentiation (history/diff) and no indication of result size, limits, or ordering for the default profile call.

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 all three parameters are already documented, but the description adds intent-level meaning: 'as_of' asks what was believed at an earlier instant, 'since' narrows to only what changed and returns newest first, and omitting 'question' yields the full profile. That is genuine value beyond the schema, though the RFC3339 format itself is left to the schema.

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

Purpose4/5

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

The description makes clear this is a retrieval operation over what the system believes about the user, returning those beliefs as sentences with provenance (before/elsewhere/said). The verb phrasing 'Ask what is remembered, in words' is idiosyncratic but the resource and output shape are unambiguous. It does not distinguish itself from siblings like history or diff, which likely overlap with the 'since' changed-since-last-time behavior.

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

Usage Guidelines4/5

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

Usage contexts are explicit and actionable: call before assuming anything about the user, omit 'question' to get a profile to start a conversation, pass 'since' at the start of a session to see what is new, pass 'as_of' for a historical view. What's missing is any exclusion or named alternative — nothing says when to prefer history or diff over this tool, which matters given the overlap.

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

rememberRememberA

Keep something worth remembering about the user or their work: a preference, a fact, a decision, or a correction. Pass the passage as text, in the user's words where you can, or pass the conversation as messages with their roles, so that only what the user said or agreed to is kept and nothing the assistant suggested. The server works out what it says. A newer statement replaces an older one about the same thing, and the older one stays in the history. Restating something already known changes nothing.

NameRequiredDescriptionDefault
textNowhat to remember; or pass messages
messagesNoa conversation to remember instead of text, in order: only what the user said or agreed to is kept
observed_atNowhen it was said, as an RFC3339 instant like 2023-05-20T02:21:00Z; omit for now. Use it only for something said earlier, such as an imported conversation.

TDQS

A4.5/5.0
Behavior5/5

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

With no annotations, the description carries the full burden and does so well: it discloses that only user-attributed content is kept, that newer statements supersede older ones about the same subject, that superseded entries remain in history, and that redundant restatement is a no-op. These deduplication and idempotency semantics are exactly the behavioral traits an agent cannot infer from 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.

Conciseness4/5

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

Purpose and content types are front-loaded, followed by parameter guidance and then behavioral rules, so structure matches reading order. It is a dense paragraph with no wasted clause, though splitting the deduplication rules into their own sentence group would aid scanning.

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

Completeness4/5

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

For a mutation-style tool with no annotations and no output schema, the description covers write semantics, attribution rules, conflict resolution, and idempotency. The remaining gap is what a successful call returns (confirmation, identifier, or nothing), which the agent may want to know for follow-up calls.

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 meaning: it explains the text-vs-messages tradeoff and the filtering behavior of messages ('only what the user said or agreed to is kept'), plus the intent behind observed_at. It stops short of clarifying what happens when both text and messages are passed, which the schema also leaves open.

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

Purpose5/5

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

Opens with a specific verb and object: 'Keep something worth remembering about the user or their work,' then enumerates the acceptable content types (preference, fact, decision, correction). The write-side framing clearly separates it from recall/forget/history/diff siblings without relying on the name alone.

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

Usage Guidelines4/5

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

Gives concrete usage guidance: prefer the user's own words for text, use messages when you want role-filtering, and reserve observed_at for earlier/imported statements. It never explicitly excludes a sibling tool by name, but the write-vs-read boundary is unambiguous from context.

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. 5 tool updatesv0.22.1
    • First observeddiff
    • First observedforget
    • First observedhistory
    • First observedrecall
    • First observedremember

TDQS

A4.1/5.0

Scored across 5 tools

Disambiguation4/5

The five tools cover clearly different operations: storing, querying, withdrawing, tracing one item's history, and comparing beliefs across time. The only mild overlap is between recall's `since` mode and diff, which both answer 'what changed', though their descriptions differentiate instants versus periods.

Naming Consistency4/5

All names are single, lowercase words with a consistent terse style. However, remember/recall/forget are verbs while history and diff are nouns, a minor deviation from a pure verb convention.

Tool Count5/5

Five tools is well scoped for a focused memory service, with each tool earning its place across the read/write/history lifecycle. No tool feels redundant or missing from the core set.

Completeness5/5

The surface covers the full memory lifecycle: write (remember), read (recall with profile, point-in-time, and delta views), soft delete (forget), per-item history, and cross-instant diff. No dead ends are apparent for the stated purpose.

Maintenance

ActivityActive
ResponsivenessOutdated data

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    B
    maintenance
    Open-source AI memory layer for LLM agents. Importance scoring, temporal decay, hierarchical memory (facts, summaries, themes), YMYL prioritization, and active retrieval with contradiction detection. Supports OpenAI, Anthropic, Ollama. Local-first with SQLite + FAISS.
    14 PyPI
    50
    Apache 2.0
  • A
    license
    Not graded
    quality
    D
    maintenance
    Integrates an Engram brain with Claude Code via MCP, providing tools for searching, retrieving, and adding memories.
    17 npm
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Local memory for AI agents in one SQLite file on your own machine. Facts carry a validity window and a confidence score, so an outdated one is superseded and downweighted rather than deleted, and retrieval fuses BM25, vector similarity and a knowledge graph.
    3
    Business Source 1.1
  • A
    license
    Not graded
    quality
    B
    maintenance
    Self-hosted long-term memory for AI agents on your own Postgres. Facts are dated, versioned and superseded rather than silently overwritten, every recall ships with an inspectable trace, and agents can correct wrong memories from inside the conversation.
    2
    Apache 2.0