Skip to content

Record to memory

Capture a decision, finding, or checkpoint in the research tree, then find it again later. This guide assumes you already know what the memory tree is — if not, read Memory first.

Pick the right entry type

Choose the type that matches what you're recording:

Type Record when
decision A choice was made and you want the rationale preserved.
checkpoint You're summarizing present state — what's done, what's next.
experiment You tried something with a pass/fail outcome.
note The user shared a finding, gotcha, or limitation worth keeping.
annotation You (the agent) hit a tool/API limitation or learned a durable user preference. Record these automatically, no prompt.
todo The user asked to be reminded of work for later.

Notes vs. annotations

For when to use note versus annotation, see Memory.

Record an entry

  1. Find the parent. Call recall (use view="outline" on a large tree) to locate the active subproject and the open phase within it.
recall(project="angelo", view="outline")
  1. Record under the most specific entry. Decisions and checkpoints hang off the phase; notes, annotations, and experiments hang off the deepest entry they relate to.
record(
  project="angelo",
  parent_id="plan-7192aeb8",
  type="decision",
  title="Use DVC for large artifacts",
  body="Chose DVC over git-lfs because ...",
  files="memory/artifacts.py",
)
  1. Always pass files when the entry references code. The server commits the listed files and pins the entry to the resulting commit SHA, so the reference is immutable and reproducible. Omitting the parent defaults to the project root — prefer being explicit.

Record before you commit

Every git commit must be preceded by a record() call. Write the entry (with files), then run git — the entry rides up with your push.

Search and recall

  • Find by keyword or file path — use search:
search(query="auto-invalidation", project="angelo")
  • Read the tree — use recall. Start with view="outline" on a big tree, then drill into a node with entry_id, or collapse depth with depth=N:
recall(project="angelo", entry_id="deci-a0778370")
  • Pick up last session's context — use session(action="pickup"). No query returns the latest session; a query semantically searches past sessions:
session(action="pickup", project="angelo", query="artifacts remote work")

Search memory before grepping the codebase — prior work and answers often already live in the tree.

Relate two entries

Cross-link entries that inform each other with relate:

relate(
  action="link",
  entry_a="deci-a0778370",
  entry_b="plan-c9b3afda",
  rationale="The plan implements this decision",
)

Mark work done

Close a todo (or discard anything superseded) with discard:

discard(entry_id="todo-1234abcd", reason="completed")

Tidy up: merge duplicates and bulk-edit

Over time a tree accumulates near-duplicates and mis-tagged entries. Three relate actions clean this up without losing history:

  • Find duplicates. relate(action="suggest", entry_id=..., project=..., mode="duplicate") returns near-duplicate candidates — entries with both high embedding similarity and lexical overlap. It only proposes; it never merges.
  • Merge losslessly. relate(action="merge", entry_a=<loser>, entry_b=<winner>) collapses the loser into the winner: its children are reparented, its tags, files, and relationships are unioned onto the winner, every entry that pointed at the loser is redirected to the winner, and the loser is soft-discarded with reason merged_into:<winner> (reversible, preserves history).
  • Bulk tag/retype. relate(action="bulk", ids="id1,id2,id3", add_tags="x", remove_tags="y", set_type="decision") applies tag and type changes across many entries in a single commit.
relate(action="merge", entry_a="deci-olddupe1", entry_b="deci-canonical9")

Reference

For the full parameter list of every tool, see MCP tools → memory. For why the tree is structured the way it is, see Memory.

Semantically related entries from the memory graph.