The first multi-tenant tier. One ai-memory process, but a swarm of agents — typically 10 concurrent — each writing into its own namespace, recalling with scope visibility filters, and gated by per-namespace governance with a pending-approval queue.
This is the canonical shape for a workstation running a planner, a coder, a reviewer, and a handful of skills as separate Claude Code agents — all sharing the same memory store but each siloed by namespace.
Every agent has a namespace position — typically agents/<role> or org/team/role. Memories are written with that namespace, and the indexed scope_idx generated column captures the agent's visibility scope (private / team / unit / org / collective).
When agent agents/planner calls memory_recall and passes as_agent=agents/planner, compute_visibility_prefixes() (src/storage/mod.rs) walks the namespace ancestors and returns [agents/planner, agents/, '']. The recall SQL then WHEREs on scope_idx IN (...) — the planner sees its own private memories plus anything scoped team or collective that an ancestor namespace publishes.
This is the same machinery T1 has — but at T2 it's actually doing work.
Set a policy with memory_namespace_set_standard:
# 1. store the standard memory that carries the policy, capture its id
ai-memory --json store -T "secops namespace standard" -c "write gating" -n agents/secops
# 2. bind it — the JSON merges into the standard's metadata.governance
ai-memory namespace set-standard --namespace agents/secops --id <standard-memory-uuid> \
--governance '{"write":"approve","promote":"owner","delete":"approve"}'
Now any agent writing into agents/secops triggers the governance gate (check_agent_action()) which returns Pending(action_id). The write isn't committed — it's parked in pending_actions. The owning operator (or a designated approver agent) calls memory_pending_list, inspects the diff, and either memory_pending_approve or memory_pending_reject. Approved writes get committed; rejected ones are dropped with an audit row.
Per-namespace policy means a strict-write namespace can sit next to a permissive one. The hierarchy lets you set a default at org/ and override at org/team/.
Before an agent invokes a skill, it can ask: "is auto-tag actually wired here?"
$ curl -s http://127.0.0.1:9077/api/v1/capabilities # or the memory_capabilities MCP tool
{
"schema_version": "3",
"tier": "semantic",
"version": "0.7.0",
"features": {
"keyword_search": true,
"hybrid_recall": true,
"auto_tagging": false,
"contradiction_analysis": false,
"cross_encoder_reranking": false,
...
},
"permissions": { ... }, "hooks": { ... },
"approval": {"pending_requests": 7, ...}
}
Capabilities v2 shipped in v0.6.3; at v0.7.0 the envelope defaults to schema_version "3" (v1/v2 still negotiable via Accept-Capabilities) — agents discover what's available at runtime instead of hard-coding assumptions.
# Run as a long-lived HTTP daemon on the workstation
ai-memory --db /var/lib/ai-memory/store.db serve \
--host 127.0.0.1 --port 9077
# Each agent is a separate MCP client (or HTTP client) pointing at the same store.
# MCP is stdio JSON-RPC, not an HTTP endpoint — spawn ai-memory mcp directly.
# In .mcp.json for each agent's Claude Code config:
{
"mcpServers": {
"memory": {
"command": "ai-memory",
"args": ["mcp", "--profile", "full"],
"env": {"AI_MEMORY_AGENT_ID": "agents/planner"}
}
}
}
# HTTP clients (non-MCP agents) connect to the daemon's REST surface:
# curl -s -X POST http://127.0.0.1:9077/api/v1/recall \
# -H "X-Agent-Id: agents/planner" -d '{"context": "..."}'
# Agents pass as_agent=agents/<role> on every recall
# Per-namespace policies set once, enforced forever:
ai-memory namespace set-standard --namespace agents/secops --id <standard-memory-uuid> \
--governance '{"write":"approve","delete":"approve"}'
GovernancePolicy (src/models/mod.rs) per namespace, hierarchical with parent inheritance, supports any / registered / owner / approve for each of write / promote / delete. Namespace metadata lives in namespace_meta and is the source of truth for the gate.memory_agent_register). Auto-tagging, contradiction detection, query expansion, and consolidation all run through the same scope visibility — a skill at skills/auto-tag with team scope only sees memories its team published. Skills can be subject to the same governance policies as humans-in-the-loop.memory_links.signature (reserved as a schema v15 column at v0.6.3) is POPULATED at v0.7.0 with Ed25519 per-link attestation — see src/signed_events.rs + the V-4 cross-row hash chain at schema v34. Peers verify signatures on receive.| Dimension | T2 ceiling | When it bites |
|---|---|---|
| Concurrent writers | ~10–20 before mutex contention shows up | Bulk imports starve real-time agents |
| Total memories | ~10⁶ before HNSW RAM cost is noticeable | Vector index lives in-process |
| Write throughput | ~500-2000 writes/sec (single SQLite writer) | Bulk operations should chunk |
| Recall p95 | sub-10ms at 10⁵ memories with HNSW | Scales to 10⁶ with care |
| Network exposure | loopback by default, mTLS available | Set up TLS before binding non-loopback |
| Cross-machine sharing | none | Walk to Tier 3 |
src/storage/mod.rs — compute_visibility_prefixes() (scope visibility)src/storage/mod.rs — visibility_clause() (SQL filter)src/storage/mod.rs — namespace_meta table for per-namespace policysrc/models/mod.rs — PendingAction structsrc/models/mod.rs — GovernancePolicysrc/mcp/mod.rs — as_agent parameter on recalldocs/AI_DEVELOPER_GOVERNANCE.md — governance contractdocs/CHANGELOG.md — v0.6.2 (governance GA), v0.6.3 (taxonomy + capabilities v2)