Apply P21: identity and experience; memory writes without approval; built-in policy
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
+32
-22
@@ -176,39 +176,49 @@ a multi-turn tool conversation and tool parsing had no failures in 20 trials.
|
||||
Memory is what carries continuity across epoch compaction, so it is required. It must not break
|
||||
the inference contract, and it must not become a way for injected text to persist.
|
||||
|
||||
1. **Memory files.** Three files, read once per epoch into the baseline, in this order after the
|
||||
system prompt: `memory/soul.md`, the persona, written only by the owner (at most 4,000
|
||||
characters); `memory/memory.md`, the agent's core notes on its work (at most 2,200 characters);
|
||||
and `memory/user.md`, its core notes on the owner (at most 1,375 characters). Each file is shown
|
||||
with how full it is. The agent edits the last two with a `memory` tool: `add`, `replace` and
|
||||
`remove` an entry, and `consolidate`, one edit that marks every entry of a file kept,
|
||||
rewritten, moved or dropped. Moved entries are appended to `memory/archive.md` (append-only,
|
||||
each entry with the date and session it was first approved in), where `recall` finds them;
|
||||
nothing leaves `memory.md` silently. Every edit is `ask`, and the approval shows `consolidate`
|
||||
as a diff. An approved edit takes effect at the next epoch, never mid-session. A write over a
|
||||
file's limit is refused with a pointer to `consolidate`.
|
||||
1. **Identity and experience.** Memory is two things. **Identity** is who the agent is and what
|
||||
it holds true about its work and its owner: three files read once per epoch into the baseline,
|
||||
in this order after the system prompt: `memory/soul.md`, the persona, written only by the owner
|
||||
(at most 4,000 characters); `memory/memory.md`, the agent's core notes on its work (at most
|
||||
2,200 characters); and `memory/user.md`, its core notes on the owner (at most 1,375
|
||||
characters), each shown with how full it is. **Experience** is what it has seen or been told:
|
||||
`memory/notes.md` (append-only) and the session logs, never in the prompt, found with
|
||||
`recall`, each item labelled with its source and trust. Not everything remembered is believed.
|
||||
The agent writes memory with a `memory` tool, without asking: `note` records something seen,
|
||||
in any session; `add`, `replace`, `remove` and `consolidate` (one edit marking every entry of a
|
||||
file kept, rewritten, moved or dropped) edit identity, and only a session that has not read
|
||||
untrusted content may use them. In a session that has, an identity `add` becomes a `note` and
|
||||
the other edits are refused. What leaves an identity file goes to `notes.md` as moved or
|
||||
dropped; nothing is deleted. A write takes effect at the next epoch, never mid-session. A
|
||||
write over a file's limit is refused with a pointer to `consolidate`.
|
||||
2. **Everything else is retrieved, not injected.** A `recall(query, k)` tool returns size-capped
|
||||
snippets with their source (a file and line, or a Honcho workspace). An `ask_memory` tool asks
|
||||
Honcho's dialectic. Results are appended like any tool result, so the cache prefix is untouched.
|
||||
3. **Local index.** SQLite FTS5 over the session logs and `memory/archive.md`, kept by `memoryd`
|
||||
snippets, each with a source tag (`identity` for entries moved out of identity, `memory` for
|
||||
trusted experience, `memory-tainted` for experience from sessions or workspaces that are not
|
||||
trusted), where it came from, and its class. An `ask_memory` tool asks Honcho's dialectic.
|
||||
Results are appended like any tool result, so the cache prefix is untouched.
|
||||
3. **Local index.** SQLite FTS5 over the session logs and `memory/notes.md`, kept by `memoryd`
|
||||
and rebuildable with `bxctl reindex`. It needs no network and no model, so it still answers
|
||||
when Honcho is down. `memoryd` counts `recall` hits per archive entry and when each was last
|
||||
found. Retrieval sits behind a `Retriever` trait.
|
||||
when Honcho is down. `memoryd` counts `recall` hits per note and when each was last found. Retrieval sits behind a `Retriever` trait.
|
||||
4. **Honcho.** The fleet's memory service; it and the models it calls run on the owner's hosts. Each
|
||||
Boxmaker writes finished turns to its own workspace, and only turns from sessions that saw no
|
||||
untrusted content and are within a configured data class; `memoryd` enforces this itself. Entries
|
||||
moved by `consolidate` are written there too. Honcho's own extraction, summaries and
|
||||
consolidation replace a flush job of ours. What Honcho holds is derived from the session logs and
|
||||
`memory/archive.md`, and can be rebuilt from them.
|
||||
`memory/notes.md`, and can be rebuilt from them.
|
||||
5. **Workspaces and trust.** `memoryd` can read other workspaces. The owner marks each one
|
||||
trusted or untrusted; untrusted is the default. Results from an untrusted workspace are marked
|
||||
untrusted and taint the session. Honcho's conclusions carry no per-entry provenance, so the
|
||||
filter is applied when writing and the label is per workspace.
|
||||
6. **Provenance on recall.** Recalled text is presented as data with its source and data class,
|
||||
never placed in the system prompt, and taints the session with that class. Entries from
|
||||
`memory/archive.md` come back as approved memory.
|
||||
7. **The tools go through `brokerd`** under ordinary grants and run in `memoryd`: `recall` and
|
||||
`ask_memory` `auto`, every `memory` edit `ask`.
|
||||
never placed in the system prompt, and taints the session with that class; a `memory-tainted` hit
|
||||
marks the session untrusted.
|
||||
7. **The tools go through `brokerd`** and run in `memoryd`. Their policy is built in, and no grant
|
||||
file can change it: `recall`, `ask_memory` and `memory` are all `auto`. What protects the
|
||||
prompt is which sessions may edit identity (item 1), plus a check on every write (no control
|
||||
or invisible characters, no chat-template markup, a short list of instruction phrases), run
|
||||
again when the prompt is built. Every write is journalled in `memory/edits/`, listed by
|
||||
`bxctl memory log`, and the latest edit of a file can be undone. An owner setting stages
|
||||
identity writes for review instead (off by default).
|
||||
8. **No memory text leaves the owner's hosts.** Honcho and the models it calls run on the owner's
|
||||
hosts, and each is listed in `docs/egress.md`.
|
||||
|
||||
@@ -217,7 +227,7 @@ the inference contract, and it must not become a way for injected text to persis
|
||||
Files are the source of truth. SQLite is allowed only for rebuildable indexes and queues.
|
||||
|
||||
- `sessions/<id>/<epoch>.jsonl` — append-only session log
|
||||
- `memory/soul.md`, `memory/memory.md`, `memory/user.md`, `memory/archive.md` — owner-readable memory
|
||||
- `memory/soul.md`, `memory/memory.md`, `memory/user.md`, `memory/notes.md`, `memory/edits/` — owner-readable memory
|
||||
- `index/` — FTS5, kept by `memoryd`; disposable and rebuildable from `memory/` and `sessions/`
|
||||
- `grants/*.toml` — owner-written
|
||||
- `audit/*.jsonl` — hash-chained
|
||||
|
||||
Reference in New Issue
Block a user