Tenancy model
Every memory in the system is owned by an agent, identified by its agent_key — the same string every store keys on (memories, association graph, agent state, compartments, quarantine, vector index). The registry (memory_agents) ties that key to an owning user, a display name, and a status.
Owner → agents → credentials
- Owner (user) — a signed-in account. Registers agents and manages their credentials. Ownership is enforced server-side; a client cannot claim an agent by passing its key around.
- Agent — a registry row with an immutable
agent_keymatching^[a-z0-9][a-z0-9_-]{1,63}$. It is the join key for every memory store, so it is never renamed and never an update target — renames would orphan the memories. Onlydisplay_name,description, andstatusare editable. - Credential — a 256-bit random secret, shown in plaintext exactly once at mint and stored only as a sha256 hash (displayed thereafter by a 12-char prefix). Kinds:
trm_api_…API keys for the REST memory surface,trm_mk_…MCP tokens for/mcp.
Writes are opt-in per credential
A credential is minted with writes_enabled, which defaults to false: recall-only. With writes off, calls that would store or change memories fail with 403 {"error":"writes are off for this credential"}. Writes are enabled at mint time (the flag is not editable after the fact — mint a new credential instead).
Agents without an owner
Agents that existed before the registry were backfilled with owner_user_id = NULL. They belong to nobody: only an admin can manage them, write to them, or — the fix — reassign them to a user (PATCH /api/v1/agents/:key/owner, admin only). Until an agent is reassigned to you, it does not appear in your registry list; asking for it answers 404.
Revocation
Revocation (DELETE …/credentials/:id) sets revoked_at — the row stays listed as an audit record, but the secret stops verifying. On the REST surface this is immediate. On MCP it is session-lagged, stated plainly: an MCP session binds its credential claims at initialize, so a session opened before revocation keeps its agent binding and writes grant until it re-initializes. Reconnect to cut a leaked token's access for sure.
Suspension and admins
- Suspending an agent (registry status
suspended) disables its credentials; reactivating restores them. - A global admin sees all agents with
GET /api/v1/agents?all=true(silently ignored for non-admins), can manage any agent, and can reassign owners. Admins use the same endpoints — there is no separate admin API. - A plain JWT caller on MCP without a token is bound to its own personal agent, provisioned lazily as
user:<uuid>on first call. Self-asserted agent parameters are not trusted — see MCP setup.