Memory architecture
本頁內容尚未翻譯。
This page is the single end-to-end map for durable agent memory. It covers the write-side and lifecycle contracts owned by Memory Improvement Spec A. The retrieval ranking details may be expanded when Spec B lands, without changing the ownership and lifecycle boundaries documented here.
End-to-end flow
Section titled “End-to-end flow”message / explicit action / import | v classifier + policy gate | v memory_events queue | v deterministic or LLM worker ----> reject / retry audit state | v user-scoped upsert (pattern v3) | +----> trust, decay, TTL and capacity lifecycle | +----> 2s write-through embedding | `-- failure remains pending for backfill v semantic + keyword hybrid retrieval | v permission check + prompt-budget pack | v <agent-memory> injection- Ingest creates
memory_eventsfor supported conversations. The lightweight classifier records why an event should proceed; it does not write a durable memory itself. - The leader-elected memory worker drains deterministic events and LLM events
separately. LLM extraction goes through
LlmGateway, and every result is recorded on its event for retry and auditability. - Accepted results upsert
agent_memories. Explicit REST/action creates and confirmed imports enter the same table through their own validated paths. - New runtime creates attempt an embedding through
LlmGatewaywith a two-second bound. HTTP and action writes spawn this work so request latency is not coupled to the provider; the background worker awaits it because it is already outside the chat turn. Semantic edits use the same spawned write-through path. Failures and imports leave the row pending for the five-minute embedding backfill safety net. - Retrieval combines vector and keyword candidates, filters inactive rows and unauthorized user-scoped rows, then builds a prompt-budgeted memory pack. Injected memory IDs are retained as message evidence links.
Ownership and isolation
Section titled “Ownership and isolation”agent_memories.user_id is the principal that produced a memory. For
scope = 'user_agent', every read must satisfy one of these conditions:
- the row’s
user_idmatches the requesting user; or user_id IS NULL, which is the explicit compatibility rule for legacy and shared snapshot rows.
The agent_id boundary still applies. System seeds retain their existing
global visibility. User-scoped dedup keys use
v3:{type}:{scope}:{user}:{hint}, and daily semantic dedup also requires
user_id IS NOT DISTINCT FROM so maintenance cannot merge two users’ rows.
Message-memory is a separate source. In group conversations, both the user and the target agent must be members before group messages can become candidates.
Lifecycle and retention
Section titled “Lifecycle and retention”The normal delete API is reversible: it sets lifecycle_status = 'deleted',
archive_reason = 'user_delete', and archived_at. The restore endpoint only
reactivates those rows within 30 days. User-facing lists, counts, exports,
grant snapshots, and retrieval exclude inactive rows; administrative data
exports also exclude deleted rows.
Other lifecycle transitions are soft as well:
- low trust, supersede, dedup, expiry, and active-cap pressure archive rows;
- extractor-created
ephemeralmemories expire after seven days, extended by a later matching upsert; - grant revoke/refresh marks obsolete shared snapshots deleted;
- the hard-cap sweep is the routine physical deletion path for archived or deleted memory rows. Account erasure remains the exceptional compliance purge path.
Pinned rows are protected from normal archive selection, subject to the pinned-active cap. Capacity scoring combines trust, explicitness, recent confirmation, and staleness.
Grants and cache coherence
Section titled “Grants and cache coherence”Agent-to-agent grants are explicit snapshots, not a live fan-out subscription.
Grant creation copies the source agent’s active, non-system, non-shared rows;
user_agent rows are limited to the caller (legacy NULL remains compatible),
and every copied row has user_id = NULL. Refresh atomically retires the old
snapshot and copies a new one; revoke retires it. The UI exposes a manual
refresh control so this snapshot behavior is visible.
Every memory mutation crosses the retrieval cache’s Surface::Memory
invalidation boundary: CRUD, worker apply, import confirmation, and grant
grant/revoke/refresh. Redis failure is logged and the 30-second cache TTL is the
safety net; it does not roll back a committed database write.
Operations and current UI decision
Section titled “Operations and current UI decision”- The memory/skill background job is advisory-lock leader elected.
- Event recovery runs every minute, embedding backfill every five minutes, and dedup/expiry/capacity maintenance daily.
memory_eventsis the write audit and retry record;agent_memoriesis the durable serving model. Embeddings are derived indexes, never canonical data.- The management panels fetch when opened. Realtime pushes for worker-created memories are intentionally not implemented in this iteration; the bounded staleness is accepted and documented rather than presenting a partial live contract.
Spec B hand-off
Section titled “Spec B hand-off”Spec B owns retrieval ranking, fallback branches, and injection-quality
changes. It must preserve the user predicate in every candidate branch and the
MemoryInjectionRequest struct boundary. No read-side ranking change may
weaken the ownership, lifecycle, or cache contracts above.
Build a7f47a5ca54ddcf7806cd48b81ce1b9827042766