Store a new memory in the knowledge base. Use to capture anything worth
remembering across sessions: decisions, bugs, patterns, architecture choices,
preferences, facts, workflows, or context. Do not use for ephemeral or
session-only notes.
``type`` must be one of: fact, decision, pattern, bug, architecture, preference,
workflow, context. ``confidence`` is one of: verified (confirmed true), inferred
(assumed, not yet confirmed), stale (outdated), deprecated (no longer valid) —
defaults to "inferred". ``tags`` is comma-separated. ``namespace`` scopes the
memory to a project or domain; omit to use the configured default namespace.
``source`` records what generated this memory (e.g. a file path or tool name).
``metadata`` is an optional free-form JSON string for extra structured data.
When ``dedupe_check`` is True (default), the response includes a
``similar_memories`` list of up to 3 existing memories in the same
namespace whose content/title overlap strongly with this one — a
non-blocking hint so the caller can choose to update/relate/consolidate
instead of accumulating near-duplicates. Disable for bulk imports.
**Usually EMPTY, and that is the signal working.** Each hit carries
``similarity`` (0-1) and its ``basis``: ``cosine`` over embeddings, or
``lexical`` token overlap when they are unavailable. Unlike a search
relevance it has magnitude and is comparable between calls - it says
how close the two texts are, not how this candidate ranked.
When ``relation_check`` is True (default), the response also includes a
``suggested_relations`` list of up to 3 not-already-linked memories worth
EXAMINING for a relationship. Topical overlap is only how they were
found; it is not itself a reason to link. Ask whether one of them is the
memory this one *supersedes*, *contradicts*, was *caused_by*, or belongs
under - and if the honest answer is "they are just both about the same
area", link nothing. Search already surfaces topical neighbours, so a
`related_to` edge that says only "these are similar" adds no retrieval
signal and competes with the directional edges that do. Same gate as
above, set softer; ``similar_memories`` are merge candidates instead.
Both hint lists are COMPACT: title plus a ~200-char ``summary``, never
full bodies. They are enough to decide whether to merge, link, or move
on; call ``memory_recall`` when a candidate warrants a closer look.
Both carry ``similarity`` + ``basis``, never a search ``score``: these
lists are not a ranking of the corpus, they are a measurement against
what you just wrote.
The response may also carry ``contradicted_memories``: older memories
whose state claim THIS memory just resolved. Recording "PR #10 merged"
makes every memory still asserting "PR #10 open" knowably wrong, and
now is when fixing it is cheapest. Each entry gives the stale memory's
``id``, ``title``, the ``ref`` at issue, what it ``asserts``, and both
sides' evidence.
Reconcile by correcting the stale claim — the claim is now genuinely
false, so the text should change. That is the opposite of rewording
prose to silence a hint while the claim stays wrong. Advisory only:
nothing was mutated.
Update one or more fields of an existing memory. Use to correct outdated
information, promote confidence after confirming an inference, retype a
misfiled memory, or add/replace tags. Do not create a new memory when the
right action is to update an existing one — find the id first with
memory_recall.
All fields are optional; only provided fields are changed. ``tags``
(comma-separated) replaces the full tag set when provided — omit to leave tags
unchanged. Pass ``metadata=""`` to clear metadata; omit to leave it unchanged.
``type`` retypes the memory (same values as memory_store). Retyping is the
right fix when a memory was filed under the wrong kind — e.g. durable
reference material saved as ``workflow`` picks up point-in-time review
hints, because ``pattern``/``preference`` are the types exempt from them.
Retyping does not re-embed: the vector derives from title + content only.
``resolve_claims`` reconciles a stale state claim WITHOUT EDITING THE
PROSE — comma-separated refs (e.g. "gingugu#10"), or "all" for every
open claim on this memory. Use it when the text is accurate history: a
session log that said "PR #10 open" was correct on the day it was
written, and rewriting it to stay current destroys the record. The
memory body is left byte-identical; only the claim's resolution is
recorded. Reach for ``content`` instead only when the memory asserts
something that was never true.
"all" means every OPEN claim, never an ``unverified`` one. An unverified
ref is one the prose names without saying what became of it, so sweeping
it under "all" would record that you checked something you did not. Name
such a ref explicitly to resolve it — that path works and is the honest
way to say "I looked, and it merged".
When ``relation_check`` is True (default) and ``title`` or ``content`` was
provided, the response includes a ``suggested_relations`` list of up to 3
not-already-linked memories worth examining for a relationship - same
semantics as ``memory_store``: overlap is how they were found, and only a
directional fact (supersedes / contradicts / caused_by / parent_of /
child_of) justifies an edge. Tag-only or confidence-only updates skip the
check since the matching surface didn't change. Entries are compact
(title + a ~200-char ``summary``) and carry ``similarity`` + ``basis``,
as in ``memory_store``; an empty list means nothing was close enough to
be worth your time.
``pinned`` marks a memory as ALWAYS loaded by memory_context for its
namespace, ahead of and exempt from ranking, in addition to ``limit``.
Reserve it for the few rules that would cause real damage if missed —
the ones you would want in front of you before touching anything, not
merely useful or frequently relevant material. Ranking already handles
"relevant"; a pin is for "inviolable". Capped per namespace (currently
20): pinning is a budget, so spending it on a merely-handy memory
crowds out a rule that governs behaviour. Pass ``pinned=False`` to
unpin. Pinning does not touch ``last_confirmed`` — it is a retrieval
decision, not a claim that the content is still true.
Mark a memory as no longer valid or permanently remove it. Default behavior
(hard_delete=False) sets confidence to "deprecated", keeping the memory as a
historical record but excluding it from future search results by default. Use
hard_delete=True only when the memory must be permanently erased (e.g. sensitive
data stored by mistake). Prefer deprecation over deletion when in doubt.
``reason`` is optional but recommended for audit trail — recorded in logs.
Search memories by relevance using hybrid BM25 + semantic ranking. Use for
natural-language queries when you want the best-matching memories for a topic.
Prefer over memory_search when you have a query string and want scored results.
Use memory_search instead when you need date filters, type filters, or a
specific sort order.
``compact=True`` returns title + a ~200-char ``summary`` instead of full
content (related extras included) — the right mode for broad exploratory
queries where full bodies would flood the client's tool-result budget.
Recall the one or two memories that matter with a targeted follow-up.
``namespace`` accepts a single name or a comma-separated list (e.g.
"crow,my-project") to search several namespaces in one ranked pass.
Unlike memory_context, ``limit`` is the TOTAL result cap: the best
``limit`` matches across all listed namespaces, not per namespace. A
multi-namespace response carries ``namespaces`` and stamps each memory
with its source ``namespace``.
``tags`` is comma-separated; ALL provided tags must match. ``confidence`` sets
a minimum confidence threshold (verified > inferred > stale > deprecated).
``include_deprecated`` also returns deprecated memories (stale ones are always
included). ``include_related`` also surfaces memories directly linked to the top
hits via spreading activation: useful for pulling in a related cluster.
``explain=True`` adds a ``score_breakdown`` to each hit: the weighted
``relevance``/``freshness``/``access``/``confidence`` terms that ``score``
is the sum of. Use it to answer "why did this rank here?": a result
carried by ``confidence`` and ``freshness`` with a near-zero relevance
term matched the query barely or not at all. Off by default because it
is a diagnostic, not something worth paying for on every read.
Load the most relevant memories for the current session. Call this at session
start with a brief description of the current task to prime the agent with
useful context. Combines relevance to the task hint with recency, confidence,
and access frequency to select the top memories. Also triggers spreading
activation to wake related dormant memories.
``namespace`` accepts a single name or a comma-separated list (e.g.
"crow,my-project"): a multi-namespace call loads every namespace in one
shot and de-duplicates memories that surface in more than one, and each
memory is stamped with its source ``namespace``. ``limit`` applies per
namespace and defaults to MEMORY_AUTO_CONTEXT_LIMIT (10). ``task_hint``
is a short description of what you are working on (e.g. "fix auth bug")
— omit to surface generally high-value memories. ``compact=True``
returns title + a ~200-char ``summary`` instead of full content — pull
the full body with memory_recall when a memory matters.
Context loads refresh each surfaced memory's dormancy clock but do not
count as real accesses: ``access_count`` is reserved for
memory_recall/memory_search hits, so protocol-driven session-start
loads don't inflate ranking signals.
A surfaced memory may carry ``review_hints`` — advisory signals that
its content describes point-in-time state (an open PR, a "waiting on"
note, a passed expiry date) that hasn't been confirmed recently.
Reconcile with memory_update / memory_forget if it's no longer true.
``explain=True`` adds a ``score_breakdown`` to each memory: the weighted
terms ``score`` is the sum of, plus ``type_boost`` where the
architecture/decision boost applied. It is the way to see which bucket a
memory came from: the recency and cross-namespace buckets are scored
with a synthetic relevance, so a constant relevance term across several
hits means they were selected for recency or reach, not for matching the
task hint. Pinned memories carry no breakdown: they never entered the
ranking at all.
Advanced filtered search across memories with full control over filters and
sort order. Use when you need to filter by type, date range, confidence level, or
sort by something other than relevance. Prefer memory_recall when you just have a
natural-language query and want the best-matching scored results.
``ids`` fetches memories by exact ID (comma-separated, e.g. from a
memory_stats review sample) — the precise-fetch path. When given, every
other filter is ignored: results come back in the requested order,
deprecated memories included (you named them), with a ``missing`` list
for any ID not found.
All parameters are optional — omitting all returns all memories up to limit.
``namespace`` accepts a single name, a comma-separated list (e.g.
"crow,my-project"), or None to search every namespace; ``limit`` is always the
total result cap. A multi-namespace response carries ``namespaces`` and stamps
each memory with its source ``namespace``.
``tags`` is comma-separated; all provided tags must match. ``sort_by`` is one of:
relevance, created, accessed, decay_score. A ``created``/``accessed`` sort
orders the whole matching corpus before the limit, so it returns the true
newest (or least recently read) rows and narrowing ``limit`` narrows that
answer instead of changing it. With a query, that corpus is the keyword
match set: a date sort asks something relevance cannot answer, so the
semantic cohort does not vote in it and results carry no ``score``.
``confidence`` sets a minimum
confidence threshold (verified > inferred > stale > deprecated). ``created_after``
and ``created_before`` accept ISO 8601 date strings (e.g. "2025-01-01").
``include_deprecated`` also returns deprecated memories (stale ones are always
included). ``compact=True`` returns title + a ~200-char ``summary`` instead of
full content — the right mode for broad sweeps where full bodies would flood
the client's tool-result budget; pull full bodies with a targeted follow-up.
``claims`` restricts results to the reconciliation backlog — memories that
still assert a PR/MR is open. "open" is every unresolved claim;
"contradicted" narrows to those a later memory in the same namespace has
already recorded as resolved, which are answerable immediately from what the
brain already holds. Composes with every other filter, so
``claims="open", namespace="gingugu", sort_by="created"`` is a working
sweep. Close them out with ``memory_update(resolve_claims=...)``, which
records the resolution WITHOUT editing the memory's prose.
"unverified" is a different set and NOT a backlog: memories naming a
PR/MR whose prose never says what became of it. They assert nothing, so
they are absent from every ``open`` count and from ``claims.sample``.
Most narrate work that long since shipped — this filter is how you read
them, not a queue to work down. Resolve one by naming its ref
explicitly; ``resolve_claims="all"`` deliberately leaves them alone.
``orphans=True`` restricts results to memories no relation touches — the
graph backlog that ``memory_stats``' ``graph.orphans`` counts. An orphan
is reachable only by direct search: spreading activation can never wake
it, so a verified, frequently-recalled orphan is retrieval the graph is
leaving on the table. Composes with every other filter and works with or
without a query, so ``orphans=True, namespace="crow", sort_by="accessed"``
walks the ones costing the most first. Reconnect them with
``memory_relate`` — and only where a directional fact exists to record;
an orphan is better left alone than wired up with an invented edge.
``explain=True`` adds a ``score_breakdown`` to each hit: the weighted
terms ``score`` is the sum of. Results with no ranking behind them carry
none: an ``ids`` fetch and a ``created``/``accessed`` sort were not
ranked, and a listing with no query scores every row on the same flat
relevance, which the breakdown shows as an identical relevance term.
Return health statistics for the memory store. Use to monitor memory growth,
identify dormant memories, and get a per-namespace breakdown of counts and
confidence distribution. Call at session start alongside memory_context to assess
the state of the knowledge base.
``stats.dormant_count`` reports memories untouched for 90+ days — a resting
signal only, never a confidence change. Dormant memories wake automatically on
recall via spreading activation. Memory is never auto-forgotten.
``review_limit`` raises the ``review.sample``, ``claims.sample`` and
``graph.orphan_sample`` caps (default 5, max 100) so a reconciliation sweep can
enumerate every flagged memory — pair with memory_search's ``ids`` parameter to
pull the full bodies.
``stats.graph.orphan_sample`` names the memories behind ``graph.orphans``: those
no relation touches, which spreading activation can never reach. Ordered by
confidence, then access count, then recency, so the orphans costing the most
retrieval come first, each row carrying its ``namespace``.
``memory_search(orphans=True)`` pulls the same set with full bodies;
``memory_relate`` reconnects one — where a directional fact genuinely exists.
``stats.claims`` is the state-claim backlog: memories still asserting a PR/MR
is open. ``claims.sample`` enumerates them, contradicted first, each row
tagged ``contradicted`` (a later memory in the same namespace already recorded
that ref as resolved). ``open`` counts every unresolved claim while
``open_actionable`` — what the sample lists — excludes claims on deprecated
memories. ``memory_search(claims="open")`` pulls the same set with full bodies;
``memory_update(resolve_claims=...)`` closes them without editing prose.
``claims.unverified`` counts refs a memory names without ever saying what
became of them. It is reported for visibility, not action: those refs assert
nothing, so they are excluded from ``open`` and from ``sample`` on purpose.
Read them with ``memory_search(claims="unverified")``.
``flag_stale`` is deprecated and ignored — auto-demotion to stale contradicted
the never-forget model and has been removed. Retained so existing callers do not
error. ``namespace`` scopes the stats to a single namespace; omit for global.
Search or slice WITHIN one memory's body, without loading the whole thing.
Recall and search answer "which memory?"; this answers "where in it?".
Between a full body and a ~200-char compact summary there was nothing:
asking whether a long memory mentions a particular decision, and where,
meant pulling every byte of it into context. Use this instead once you
know which memory you want.
Two modes, composable:
- **Find**: pass ``query`` for a literal, case-insensitive substring
scan. Each match returns its ``start``/``end`` character offsets, its
1-indexed ``line``, and an ``excerpt`` with ``context_chars`` of
surrounding text on each side. ``total_matches`` is the true count
even when ``max_matches`` caps what comes back, so you can tell "that
was all of them" from "that was the first 10 of 300".
- **Slice**: pass ``start`` and/or ``end`` character offsets to read an
exact range. Omitted bounds mean start-of-body and end-of-body. Feed
back the offsets from a find to read the full passage around a hit.
Passing both searches only inside the range, with offsets still
reported absolute against the full body.
The scan is literal and deterministic: no ranking, no stemming, no
model. Asking twice gives the same answer in the same order, and
matches come back in the order they appear in the text, never by
relevance. ``length`` (total characters) and ``lines`` come back on
every call, so a first call with no query is a cheap way to size a
memory before deciding how to read it.
Reading a memory this way credits it as a real access, the same as
naming it in ``memory_search(ids=...)``.
Create a directional link between two memories. Relations are used by
spreading activation (recalling one memory wakes its related cluster) and are
returned when include_related=True in memory_recall.
**An edge must encode something search cannot infer.** Recall already ranks
by hybrid text + semantic similarity, so "these two memories are about the
same topic" is knowledge the index has for free. What only a relation can
record is direction and time: which memory REPLACED which, what CAUSED what,
what CONTRADICTS what, what CONTAINS what. Prefer, in this order:
``supersedes``, ``contradicts``, ``caused_by``, ``parent_of``/``child_of``.
Reach for ``related_to`` only when a genuine connection exists that none of
those describe - it is the fallback, not the default.
Quality over volume: spreading activation surfaces at most 3 neighbours per
seed memory, and it weights by relation type - a directional edge outranks
``related_to``, so on any memory with more than 3 edges the ``related_to``
ones are what lose their slot. A vague edge is therefore not merely
low-value, it is likely to never fire at all; and precise edges still
compete against each other for those 3 slots, so a handful of them
retrieves better than a dense mesh. If you cannot name the directional fact
an edge records, do not create it.
A mislabelled edge is repairable: ``memory_unrelate`` retypes or removes one.
``source_id`` is the memory making the claim about ``target_id``. ``relation_type``
must be one of: supersedes (source replaces target), contradicts (conflicting
claims), caused_by (source was caused by target), parent_of (source contains
target), child_of (source belongs to target), related_to (fallback: a real
connection none of the above captures).
Enumerate graph edges with both endpoints resolved to titles. Read-only.
``memory_stats`` reports that the graph is, say, 70% ``related_to`` — this is
how you see WHICH edges those are, in order to judge them. Pair it with
``memory_unrelate`` to run a repair sweep: enumerate a page, decide each edge
on its merits, submit the batch, advance ``offset``.
Each row carries both endpoints' ids, titles and namespaces, the relation
type, and each endpoint's ``degree`` (total edges touching it). Degree is the
one that decides reachability: spreading activation visits at most 3
neighbours per seed, so edges on a high-degree memory may never fire. It
ranks candidates by confidence then relation type, so the ones dropped
there are ``related_to`` first - which is what makes a high-degree,
mostly-``related_to`` memory the best target for a repair sweep.
``namespace`` matches an edge when **either** endpoint lives there, since
relations legitimately cross namespaces. ``relation_type`` filters to one
type (``related_to`` is the usual repair target). ``memory_id`` returns every
edge touching one memory, in either direction. Ordering is stable, so a paged
sweep sees each edge exactly once — but note that repairing edges as you page
changes what matches, so re-run from ``offset=0`` when filtering on a type
you are actively retyping away from.
Repair the graph: retype a mislabelled edge, turn a backwards one around, or
remove one that should not exist. The counterpart to ``memory_relate`` — without
it, an edge written in haste is permanent, and every wrong edge keeps competing
for one of the 3 spreading-activation slots on its memories forever.
**Retype** by passing ``new_relation_type`` alongside ``relation_type``. The
edge is relabelled in place: direction, creation time and metadata survive,
because the usual repair is "right connection, wrong label" and the graph
should keep an honest record of when the link was first drawn. If an edge of
the new type already joins the pair, the two collapse into one and the
outcome reports ``merged`` rather than ``retyped`` — the edge count drops by
one, and nothing is fabricated to hide that.
**Reverse** by passing ``reverse=True`` alongside ``relation_type``. The
endpoints are swapped on the same row, so id, creation time and metadata
survive exactly as they do for a retype — the connection was right, only the
arrow pointed the wrong way. Reversing COMBINES with ``new_relation_type``, in
one write, because an edge recorded backwards is often mislabelled as well.
Note that reversing ``parent_of``/``child_of`` is the same operation as flipping
between the two types: do one or the other, not both. As with a retype, an
existing edge in the target direction absorbs this one and reports ``merged``.
**Delete** by omitting ``new_relation_type`` and ``reverse``. With ``relation_type``, only
that edge goes; without it, every edge from ``source_id`` to ``target_id``
goes, whatever the type. Deletion here is not the bulk prune the graph
guidance warns against: the caller names each edge, exactly as
``memory_forget`` names a memory.
**Batch** by passing ``edges`` — an array of up to 100 objects, each with
``source_id``, ``target_id`` and optionally ``relation_type`` /
``new_relation_type`` / ``reverse``, i.e. the same decision made once per edge:
[{"source_id": "a", "target_id": "b",
"relation_type": "related_to", "new_relation_type": "caused_by"},
{"source_id": "c", "target_id": "d",
"relation_type": "caused_by", "reverse": true},
{"source_id": "e", "target_id": "f", "relation_type": "related_to"}]
A batch is reviewed decisions submitted together, NOT a criteria-driven
sweep, and that is deliberate. There is no "retype every ``related_to`` in
this namespace" option, because the whole point of retyping is that each edge
deserves a different type based on what it actually records — a blanket
relabel would manufacture directional claims that were never true, and a
false ``caused_by`` is worse than an honest ``related_to``.
The batch is validated in full before anything is written, so a malformed op
fails the whole call rather than leaving the graph half-repaired. Individual
outcomes (``retyped``, ``reversed``, ``merged``, ``deleted``, ``not_found``,
``unchanged``) are reported per edge. Use ``dry_run=True`` to preview a sweep
first; nothing is written and each op reports what it would have done.
Find the edges to repair with ``memory_edges``.
Combine multiple memories into one to reduce redundancy and knowledge bloat.
Use when several related memories about the same topic have accumulated over time.
Do not use on memories that are still actively distinct — prefer memory_relate
to link them instead.
``memory_ids`` is comma-separated (minimum 2 ids required). ``strategy`` is one
of: merge (concatenate all content into one memory), summarize (produce a
condensed combined summary), deduplicate (keep the highest-confidence entry and
deprecate the rest). ``keep_originals=True`` (default) preserves originals as
deprecated; set False to hard-delete them.
**Suggest mode:** omit ``memory_ids`` entirely for a read-only near-duplicate
scan of ``namespace`` (or the resolved default). Returns candidate clusters
found by pairwise embedding similarity at or above ``min_similarity`` (falls
back to exact-title clusters when embeddings are absent or sparse). Nothing
is written — inspect the clusters, then call again with ``memory_ids`` to
actually consolidate. An empty ``memory_ids`` string is still an error, so
a caller that built its id list from an empty collection fails loudly.
+7 more tools listed on main page