Blog

Multi-Agent Memory Design

An implementation sketch for per-Agent memory, project memory, and layered short-term, long-term, and important memory.

Published: Category: Runtime

A useful multi-Agent memory system should not behave like one shared notebook that every Agent can rewrite. Eva-CLI can treat memory as a runtime-owned service with two scopes: each Agent keeps a private memory space, and the project keeps a shared memory module that only accepts promoted, validated facts.

Diagram of per-Agent private memory flowing through a promotion policy into layered project memory and ContextBuilder retrieval.
Each Agent keeps private memory while the runtime promotes validated facts into short-term, long-term, or important project memory.

Memory scopes

The first boundary is ownership. Agent memory belongs to a single Agent identity and records local preferences, task history, capability observations, and working assumptions. Project memory belongs to the workspace and stores facts that should survive across Agents, such as architecture decisions, reusable constraints, release notes, user preferences, and known risks.

Agents should read project memory through the runtime, but they should not write to it directly. Writes go through a promotion path that records the source Agent, evidence, confidence, freshness, and reason for promotion. That keeps shared memory useful without turning it into an unreviewed transcript.

Layered project memory

The project memory module can be split into layers with different retention and retrieval behavior. Short-term memory is a session or task window: active goals, recent tool results, unresolved questions, and temporary assumptions. Long-term memory stores stable facts: repository conventions, architecture decisions, dependency choices, and recurring workflows. Important memory is a protected layer for high-signal constraints that should be retrieved before ordinary long-term entries, such as security rules, irreversible operational limits, and user-level preferences.

These layers should use the same record shape but different policies. A memory record can include scope, layer, owner, title, body, tags, source, confidence, priority, created time, last accessed time, expiration, and revision. Short-term entries can expire aggressively. Long-term entries require deduplication and periodic summarization. Important entries require explicit promotion, stronger provenance, and a small review surface.

Write path

The runtime should normalize every write request before persistence. A good write path is: capture an event, classify its candidate layer, check permissions, merge it with similar records, attach provenance, and write an append-only revision. For project memory, an Agent can propose a memory, but a memory policy decides whether it becomes short-term, long-term, or important.

This makes conflict handling concrete. If two Agents disagree, the memory module keeps separate claims until evidence resolves them. If a fact becomes obsolete, the system marks it superseded instead of silently deleting it. Agents then see the current summary while the audit trail remains available for debugging.

Read path

Context building should be selective. The ContextBuilder can retrieve important project memory first, then relevant long-term project records, then the requesting Agent's private memory, and finally short-term entries tied to the active task. Ranking should combine tags, semantic similarity, recency, priority, confidence, and the current topic.

The key rule is budget control: memory retrieval should produce a compact context pack, not a dump. Each pack can include required constraints, likely useful facts, open questions, and sources. That keeps Agents grounded while leaving room for live task context.

Implementation sketch

A pragmatic implementation starts with a Rust-owned memory service behind a small API: write memory, propose project memory, promote memory, search memory, summarize memory, and expire memory. Storage can begin with structured JSON or SQLite records, then add vector indexes later when semantic retrieval becomes necessary.

Lua Agents call the API through capability-checked functions. The Rust runtime owns permissions, persistence, promotion rules, and compaction jobs. This keeps Agent behavior hot-reloadable while memory integrity stays inside the stable runtime boundary.

Why this shape works

Per-Agent memory preserves specialization. Project memory gives the whole workspace continuity. Layering short-term, long-term, and important memory prevents urgent context, durable knowledge, and non-negotiable constraints from competing in the same bucket. The result is a memory system that can grow with more Agents without losing traceability or control.