Manually-triggered, multi-stream agent memory — a personal knowledge graph. Exposes mechanical ops (create/edit/remove streams, notes, entities) as MCP tools for agents like Claude Code.
Pensieve demonstrates strong naming conventions (verb_noun pattern: list_streams, create_stream, add_note) and comprehensive parameter descriptions. All 24 tools have clear, domain-specific descriptions (avg ~150 chars). Input schemas are present with typed parameters. However, output schemas are not explicitly documented in the source code, responses are inferred from implementation. Error handling is minimal; most tools lack recovery guidance. No tool annotations (readOnlyHint, destructiveHint, idempotentHint) despite clear risk profiles (WRITE, REVERSIBLE, READ_ONLY). Parameter descriptions are strong but some lack format constraints (e.g., 'stream' and 'note' IDs lack pattern/format specs). Composition is excellent, tools chain well (list_entities → add_note with entity resolution). Missing: output schema documentation, error classification, and confirmation patterns for destructive ops.
Attach a by-reference pointer (file/dir/URL) to a stream or note — for external context without duplication.
Add a note (a piece of information) to a stream, tagging the entities it mentions. Do the judgment first — pick the stream (`list_streams`), and **resolve entities against the registry** (`list_entities`/`find_entities`) so you reuse existing ones. A change in the world is a *new* note; use `edit_note` only to fix a mistake. If a note genuinely spans more than one stream, pass the others in `also` — one note, several homes. **Never duplicate** a note across streams. Most notes belong to one.
Create a new stream — a top-level domain of work/life.
Demote a promoted entity back to the registry (its thread dissolves; notes stay in the stream as loose notes).
Rename an entity or add/remove aliases (for dedup and recall).
Rewrite a note's text — only to fix a genuine mistake. A change in the world is a *new* note (`add_note`), not an edit.
Output schemas not documented in source code. Tool descriptions explain what is returned (e.g., 'show its name, kind, aliases, note count, and all notes'), but formal JSON Schema output definitions are absent. LLMs cannot plan downstream tool calls without knowing response structure.
No tool annotations (readOnlyHint, destructiveHint, idempotentHint) despite clear risk profiles. Tools are labeled READ_ONLY, WRITE, or REVERSIBLE in metadata, but MCP tool annotations are not applied. This prevents clients from warning users or enforcing safety policies.
Minimal error handling and no recovery guidance. Tools raise ValueError or PensieveError but do not provide actionable next steps. E.g., 'No stream X' should suggest 'Call list_streams() to see available streams.' Agents cannot self-correct without explicit guidance.
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 62 | <=2025-11-25 | v2 |
Rename or repurpose a stream. The id (slug) is immutable — only display fields change.
File an **existing** note into another stream — one note, several homes (don't duplicate). Use when a note you already captured also belongs in a second stream.
Fuzzy-search the entity registry by name/alias (a candidate shortlist). Use to check "do I already have a 'Rafia'?" before creating a new entity, and to recall ("what do I know about X?").
Recall an entity — show its name, kind, aliases, note count, and all notes that reference it.
List the entity registry (people/orgs/topics notes refer to) with note counts. Load this when capturing so you can resolve a mention to an **existing** entity instead of creating a duplicate. `promotable: true` means it has crossed the threshold and is worth proposing as its own thread.
List all streams (the top-level domains) in the user's Pensieve.
Promote an entity to its own thread (a first-class node under the stream). Once promoted, new notes tagging it land under the thread automatically. Reversible via `demote_entity`.
Remove an asset pointer. **Soft and reversible** — bring it back with `restore_asset`.
Remove an entity (unlink it from all notes; notes survive). **Soft and reversible** — bring it back with `restore_entity`.
Remove a note. **Soft and reversible** — bring it back with `restore_note`. An entity that loses its last live note disappears (derived). Tell the user it's recoverable.
Remove a stream and its threads. **Soft and reversible** — bring it back with `restore_stream`. Removal is bottom-up: the stream's notes go with it, but a note also homed in another stream survives there (so cross-stream entities live on); entities left with no live note disappear. Tell the user it's recoverable.
Bring back a removed asset pointer.
Bring back a removed entity (re-link it to its notes).
Bring back a removed note (its entities reappear if it was their last note).
Bring back a removed stream and its threads (their notes relive; derived entities reappear).
Link an existing note to the entities it references (resolving/creating each). Use when you spot a subject in a note that wasn't tagged at capture time. Resolve against the registry first (`list_entities`/`find_entities`) to avoid duplicates.
Remove a note from one of its streams (it stays in the others). Refuses to remove a note's last home — use `remove_note` for that.
Remove an entity tag from a note — correct a mis-tag (e.g. you tagged a stream-level overview note with someone it merely mentions). If the entity is promoted, the note is also detached from its thread.
ID parameters lack format constraints. 'stream', 'note', 'entity', and 'asset' parameters accept strings but do not specify expected format (e.g., 'stream-1', 'note-3'). LLMs may pass invalid IDs. Add regex patterns or enum constraints to parameter schemas.
No confirmation or dry-run pattern for destructive operations. remove_stream, remove_note, remove_entity, and remove_asset are soft-reversible but still destructive. Consider adding a 'confirm' parameter or separate 'preview_removal' tool to prevent accidental data loss.