M5a spec: built-in policy for recall and memory; tool calls indexed; output summaries in M5c
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -121,6 +121,8 @@ its source and label, and each snippet at most 600 characters:
|
||||
Owner prefers answers in UTC.
|
||||
[3] session chat-1789…, 2026-09-21 09:15 UTC, the assistant said · private · untrusted
|
||||
…
|
||||
[4] session mm-dh45qg…, 2026-09-22 18:17 UTC, the assistant called · private
|
||||
http_fetch {"url":"https://example.org/notes"}
|
||||
```
|
||||
|
||||
`(no matches for "…")` when nothing is found. The query goes into FTS5 only as quoted terms: it
|
||||
@@ -177,9 +179,12 @@ appended.
|
||||
`{home}/index/memory.sqlite3`, directory 0700, file 0600, owned by `memoryd`. Disposable: deleting
|
||||
it and restarting `memoryd`, or `bxctl reindex`, rebuilds it from `sessions/` and `archive.md`.
|
||||
|
||||
**What is indexed.** From session logs: the `content` of `User` records and of `Assistant`
|
||||
records that have content. Not tool results (the bulk of every log, and the way injected text
|
||||
arrives), not `reasoning_content`, not tool call arguments. From `archive.md`: every entry.
|
||||
**What is indexed.** From session logs: the `content` of `User` records, of `Assistant` records
|
||||
that have content, and each tool call the assistant made, as its tool name and arguments
|
||||
(`read_file {"path":"/srv/notes/q3.txt"}`), so `recall` can answer "did we read that, and when".
|
||||
Not tool results (the bulk of every log, and the way injected text arrives) and not
|
||||
`reasoning_content`. A summary of a tool's output is M5c's (owner, 2026-09-24): it needs a model
|
||||
to write it. From `archive.md`: every entry.
|
||||
`memory.md` and `user.md` are not indexed: they are already in every prompt.
|
||||
|
||||
**Labels.** Walking a session log in order, `memoryd` keeps the session's label so far: the
|
||||
@@ -230,10 +235,11 @@ connection, the existing frames (`proto::frame`, `MAX_FRAME`). New message kinds
|
||||
- **Tools.** `ToolName` gains `Recall` and `Memory`; `ToolArgs` gains their parsed arguments
|
||||
(`proto` holds the serde structs, as for the other tools). Parsing enforces the shapes and
|
||||
limits in section 5. Neither tool has constraints (`paths`, `hosts`, `patterns` must be empty).
|
||||
- **Grants.** Ordinary grant files. The shipped examples:
|
||||
- **Grants: built in** (owner, 2026-09-24: an agent that cannot write memory is not worth
|
||||
running). `brokerd` holds two fixed grants, always present whatever is in `grants/`:
|
||||
|
||||
```toml
|
||||
# grants/recall.toml
|
||||
# built in: recall
|
||||
tool = "recall"
|
||||
mode = "auto"
|
||||
max_taint = "secret"
|
||||
@@ -242,7 +248,7 @@ connection, the existing frames (`proto::frame`, `MAX_FRAME`). New message kinds
|
||||
```
|
||||
|
||||
```toml
|
||||
# grants/memory.toml
|
||||
# built in: memory
|
||||
tool = "memory"
|
||||
mode = "ask"
|
||||
max_taint = "secret"
|
||||
@@ -250,8 +256,13 @@ connection, the existing frames (`proto::frame`, `MAX_FRAME`). New message kinds
|
||||
untrusted = false
|
||||
```
|
||||
|
||||
A grant of `memory` at `auto` is refused when grants are loaded: every memory edit is the
|
||||
owner's (brief, memory 7). The fixed sentence names the grant.
|
||||
Their names are `builtin-recall` and `builtin-memory`, and their `grant_sha256` is the hash of
|
||||
that text, so the audit log names them like any other grant. A file in `grants/` whose `tool`
|
||||
is `recall` or `memory` is a grant problem at load (`grants-invalid`), with the fixed sentence
|
||||
`the policy of recall and memory is built in; remove this grant`. So no grant file can turn
|
||||
memory edits off, or make them unattended; every edit is the owner's (brief, memory 7). With
|
||||
section 9 (no session without the memory block), an agent that can talk can always read its
|
||||
memory and propose edits to it.
|
||||
- **Where a decided call runs.** A composite runtime sends `Recall` and `Memory` specs to
|
||||
`memoryd`'s `brokerd` socket as a `tool_request`, and everything else to the configured runtime
|
||||
(Podman, or the refusing one). `[memory] socket` in `brokerd.toml` names the socket; without it,
|
||||
@@ -326,7 +337,8 @@ Offline, in `make gate`:
|
||||
archive and journal lines; the block; the quoted-terms query builder against FTS5 operators
|
||||
(`NEAR`, `*`, `^`, quotes, column filters); labels walked from a log; `max_class`; catching up
|
||||
from `progress`; a reindex equal to the incremental index; the recall log.
|
||||
- `brokerd`: parsing both tools; `memory` at `auto` refused at load; the composite runtime; the
|
||||
- `brokerd`: parsing both tools; the built-in grants present with an empty `grants/`; a grant
|
||||
file naming either tool refused at load; the composite runtime; the
|
||||
stricter label, with a runtime that returns a stricter and a laxer one.
|
||||
- `loopd`: the baseline with a fake `memoryd`; the refusal and its pointer; `session_updated`
|
||||
sent after a finished turn and not after a turn ending in tool calls.
|
||||
@@ -339,10 +351,11 @@ which `recall` then finds; a hit from a session that read a fetched page coming
|
||||
|
||||
## 15. For the owner's review
|
||||
|
||||
1. Tool results are not indexed (section 6). It keeps injected text out of `recall`, and keeps
|
||||
the index small; the price is that `recall` cannot find something only a tool returned, such
|
||||
as a file's contents, unless the assistant repeated it.
|
||||
2. `memory` at `auto` is refused at load (section 8), not merely discouraged.
|
||||
1. Decided: tool results are not indexed; tool calls are, by name and arguments (section 6).
|
||||
Summaries of a tool's output, where the tool opts in (a web fetch, say), come with M5c's
|
||||
summariser, labelled like the output they summarise.
|
||||
2. Decided: the policy of `recall` (`auto`) and `memory` (`ask`) is built in, and grant files
|
||||
cannot name them (section 8): memory edits can be neither turned off nor made unattended.
|
||||
3. Entries are named by their full text, not by number (section 5), so approvals are readable and
|
||||
stale edits fail; the arguments of a `consolidate` of a full `memory.md` are about 4,500
|
||||
characters, one approval post.
|
||||
|
||||
Reference in New Issue
Block a user