mem:audit is dominated by rows the daemon writes about its own index flushes. On one store
it had reached 31 MB / 84 028 entries, of which 59 876 (71%) were index_persist. That
makes memory_audit take ~2.2 s and adds the same rows to every startup read.
Why these rows do not belong there
The policy at the top of src/functions/audit.ts (issue #125) defines what the log is for:
Every structural deletion of a memory, observation, session, or semantic row MUST call
recordAudit.
Index shard writes and manifest publishes delete no user rows, so they are outside that
definition. The same comment block also names the failure mode this runs into:
Per-item audit rows would flood the audit log during routine sweeps.
IndexPersistence.save() is a routine sweep on a 5 s debounce, and it emits one row per shard
write plus rows for the manifest publish and the legacy cleanup — three for a single-document
BM25 save, more as shard count grows and again when a vector index is present.
Reproduction
// with a KV double, or against a live daemon watching mem:audit
const persistence = new IndexPersistence(kv, bm25WithOneDoc, null);
await persistence.save();
// mem:audit now holds 3 index_persist rows for one flush
There is no retention, prune, or rotation anywhere to absorb this: no *AUDIT* env var, no
cap key, and recordAudit writes unconditionally.
Proposal
Make index_persist auditing opt-in behind AGENTMEMORY_AUDIT_INDEX_PERSIST, off by default,
so the log matches the policy its own module states. Index persistence keeps working
identically; only the audit rows stop.
Retention as a mechanism is deliberately out of scope here — it is a larger design question
and worth its own issue. This change is the part that needs no policy decision, because the
policy already exists and this code sits outside it.
A PR follows. Happy to reshape it if you would rather solve this with retention instead, or
keep the rows and batch them into one per flush.
Environment
- agentmemory
0.9.29
- Node
v26.5.0
- macOS 26.5.2, arm64
Related
#125 (the coverage policy this cites), #1115 (orphaned index generations — the same subsystem
growing unboundedly for a different reason), #766 (audit events for failures).
mem:auditis dominated by rows the daemon writes about its own index flushes. On one storeit had reached 31 MB / 84 028 entries, of which 59 876 (71%) were
index_persist. Thatmakes
memory_audittake ~2.2 s and adds the same rows to every startup read.Why these rows do not belong there
The policy at the top of
src/functions/audit.ts(issue #125) defines what the log is for:Index shard writes and manifest publishes delete no user rows, so they are outside that
definition. The same comment block also names the failure mode this runs into:
IndexPersistence.save()is a routine sweep on a 5 s debounce, and it emits one row per shardwrite plus rows for the manifest publish and the legacy cleanup — three for a single-document
BM25 save, more as shard count grows and again when a vector index is present.
Reproduction
There is no retention, prune, or rotation anywhere to absorb this: no
*AUDIT*env var, nocap key, and
recordAuditwrites unconditionally.Proposal
Make
index_persistauditing opt-in behindAGENTMEMORY_AUDIT_INDEX_PERSIST, off by default,so the log matches the policy its own module states. Index persistence keeps working
identically; only the audit rows stop.
Retention as a mechanism is deliberately out of scope here — it is a larger design question
and worth its own issue. This change is the part that needs no policy decision, because the
policy already exists and this code sits outside it.
A PR follows. Happy to reshape it if you would rather solve this with retention instead, or
keep the rows and batch them into one per flush.
Environment
0.9.29v26.5.0Related
#125 (the coverage policy this cites), #1115 (orphaned index generations — the same subsystem
growing unboundedly for a different reason), #766 (audit events for failures).