Many agents, one host, one shared memory.
A planner, a coder and a reviewer share one store through ai-memory serve. Each agent writes into its own namespace, recalls through scope visibility, and passes a per-namespace governance gate with a pending-approval queue. The host's wake hub tells an agent the moment a message for it lands.
One daemon, one file, every writer takes its turn.
HTTPS agents talk to the daemon. An MCP agent's ai-memory mcp child and the operator's CLI verbs are not clients of that daemon: they open the same SQLite file in-process. That is why a CLI recall sees the same memories as the daemon, and also why every one of these processes queues on the same file lock for writes.
Correction (#4254). Earlier guides described the CLI at this tier as a thin client of the daemon. It is not: CLI verbs such as store and recall open the database in-process (src/daemon_runtime.rs dispatches them to src/cli/store.rs and src/cli/recall.rs with the local path). Only sync and doctor --remote speak HTTPS to a daemon or peer. Sources: src/handlers/routes.rs, src/identity/authority.rs, src/wake_hub/routing.rs, src/wake_sink/in_process.rs.
Who sees what, who may write where.
Recall takes as_agent: the engine computes visibility prefixes from the caller's namespace and its ancestors, and the SQL filter compares them against an indexed scope column. A write into a namespace whose standard says "write":"approve" is parked, not committed.
Sources: src/models/namespace.rs (scopes, governance levels and decisions), src/storage/mod.rs (visibility prefixes and clause, pending decisions), src/handlers/create.rs (the 202 pending response), src/governance/capability.rs.
One write, one recall, one wake.
- Write. The coder POSTs a memory with
X-Agent-Id: org/team-a/coderand its own API key. The key is matched to an enrolled agent, the namespace standard is read, the decision is Allow, and the row commits. - Recall. The planner recalls with
as_agent=org/team-a/planner. Its own private rows come back, plus rows scopedteam,unit,orgorcollectivewhose subtree contains the planner; the coder's private rows do not. - Governed write. The coder writes into
org/secops, whose standard requires approval. The answer is202with a pending id; an approver lists it withmemory_pending_listand approves or rejects it. - Message. The planner calls
memory_notifyfor the reviewer. The inbox row commits first; the daemon then publishes a content-free wake to the host's hub, and the reviewer'swake-listensession does one catch-up inbox read. If the hint is lost, the reviewer's backstop poll (at least once a minute) still finds the row.
A shared workstation or a single VM.
# TLS is mandatory on every listener, loopback included (#3705).
# A team host brings its own certificate: verify it and install it once
# (or pass --tls-cert / --tls-key to serve). Only the single-operator
# singleton shape mints a local CA certificate for you.
ai-memory tls import --cert /etc/ai-memory/tls/fullchain.pem --key /etc/ai-memory/tls/key.pem \
--ca /etc/ai-memory/tls/ca.pem --host 127.0.0.1
# One daemon per host (loopback by default; a non-loopback bind refuses to start without api_key in config.toml)
ai-memory --db /var/lib/ai-memory/ai-memory.db serve --host 127.0.0.1 --port 9077
# HTTPS agents identify themselves on every call and trust the daemon's CA
curl -s --cacert /etc/ai-memory/tls/ca.pem -X POST https://127.0.0.1:9077/api/v1/recall \
-H "X-Agent-Id: org/team-a/planner" -H "X-API-Key: $PLANNER_KEY" \
-H "Content-Type: application/json" \
-d '{"context":"release blockers","as_agent":"org/team-a/planner"}'
# Govern a namespace: store the standard memory, then bind it with a policy
ai-memory --db /var/lib/ai-memory/ai-memory.db store -T "secops standard" -c "writes need approval" -n org/secops
ai-memory --db /var/lib/ai-memory/ai-memory.db namespace set-standard --namespace org/secops \
--id <standard-memory-id> --governance '{"write":"approve","promote":"owner","delete":"approve"}'
# Wake plane on this host: publish the allowlist, run the hub, listen per agent
ai-memory identity hub-cache --daemon-producer --include-agent org/team-a/reviewer --out /run/ai-memory-hub/hub-allow.json
ai-memory wake-hub --socket /run/ai-memory-hub/hub.sock --hub-id team-host --allowlist /run/ai-memory-hub/hub-allow.json
ai-memory wake-listen --agent-id org/team-a/reviewer --socket /run/ai-memory-hub/hub.sock --hub-id team-host --unread-only --json
Flags verified against src/daemon_runtime.rs, src/cli/namespace.rs, src/cli/identity_hub_cache.rs, src/cli/wake_hub.rs and src/cli/wake_listen.rs. Attaching the daemon's wake sink to the hub, key directories and the snapshot refresher are covered step by step in the wake plane guide.
Governance, wake plane and identity at Tier 2.
Per namespace, inherited
Each of write, promote and delete takes any, registered, owner or approve; a standard can name a parent so a default at org/ applies below it. Capability tokens are on by default and can only lift Pending to Allow.
One hub per host
The hub is a Unix-socket switch with per-recipient queues and an allowlist; the daemon reaches it under the reserved wake-hub-producer identity. Wakes carry a digest, never the body.
Per-agent keys
An X-API-Key that matches an enrolled agent key proves that principal; agents also hold Ed25519 keypairs (src/identity/keypair.rs).
When Tier 2 stops fitting.
| Dimension | Tier 2 behaviour | Move up when |
|---|---|---|
| Writers | The daemon, MCP children and CLI processes share one SQLite file; writes serialize on its lock. | Write contention shows up in latency: PostgreSQL tier. |
| Throughput | Every HTTPS request terminates at the one daemon. | One daemon is the bottleneck: add peers at Tier 3. |
| Availability | One host, one disk; snapshots with backup, no live replica. | You need a current second copy: Tier 3. |
| Wake reach | The hub reaches agents on this host only. | Agents on other hosts: federation at Tier 3. |
| Transport | TLS on every bind, loopback included; the daemon refuses to start in cleartext. Loopback by default; an mTLS allowlist is available on serve. | Add the allowlist and api_key before binding beyond loopback. |
| Shared filesystems | The SQLite file must sit on a local disk: NFS, SMB, FUSE or EFS locking is unsafe (architectural limit 4), so the daemon cannot be scaled out over a shared volume. | You need more than one host: Tier 3 or the PostgreSQL tier. |
Reasoning for each: architectural limits.