Runtime internals
This page is the architecture-depth companion to the rest of the Agents section: how the runtime enforces per-agent permissions, scopes memory, and attributes logs. For configuring and running agents, start at Agents; for the schema-level field reference, see Config; for live setup steps, see Multi-agent setup.
Permissions model
Each agent’s effective SecurityPolicy is built by SecurityPolicy::for_agent(config, alias):
- Start from the agent’s risk profile (
[risk_profiles.<profile>]). - Set the boundary to the per-agent workspace dir (
<install>/agents/<alias>/workspace/). - Walk
[agents.<alias>.workspace.access]:Read→ sibling’s workspace lands in the read-only allowlist.Write/ReadWrite→ sibling’s workspace lands in the read-write allowlist.
- If
[agents.<alias>.workspace.unrestricted_filesystem]istrue, flipworkspace_onlyoff.
The read-only allowlist is honored by file_read (and other read-side tools); the read-write allowlist gates file_write, file_edit, git_operations, and the shell tool’s path-touching invocations. POSIX device files (/dev/null, /dev/zero, /dev/random, /dev/urandom) are always readable so shell idioms keep working without per-agent config.
SubAgent spawns enforce the rule that a child cannot escalate beyond its parent. The validator’s full axis list and the budget-sharing behavior are documented at Delegation → Permission inheritance.
Memory model
Each agent has its own Arc<dyn Memory> instance. The factory (zeroclaw_memory::create_memory_for_agent) dispatches by backend kind:
- SQLite / Postgres / Lucid: shared install-wide store. The
agentstable maps alias → UUID, and thememoriestable carriesagent_idreferencing that UUID. The factory wraps the inner backend inAgentScopedMemory, which stamps the bound agent’s UUID on every store viastore_with_agentand filters every recall viarecall_for_agentswith the resolved allowlist. - Markdown: per-agent dir. Each agent’s
MarkdownMemorywrites to<install>/agents/<alias>/workspace/MEMORY.mdandmemory/YYYY-MM-DD.md. Cross-agent recall is composed byAgentScopedMarkdownMemory, which holds the bound agent’sMarkdownMemoryplus a peer set of(alias, MarkdownMemory)pairs and unions their results with[<alias>]attribution prefixes on each row. - Qdrant: shared collection, payload-keyed. The
agent_idpayload field is the per-agent attribution;recall_for_agentsover-fetches and post-filters by payload. - None: no-op stub. The wrapper still exists so the runtime path is uniform.
Cross-backend cross-agent memory is not supported: the schema validator at config load rejects read_memory_from entries that point at a sibling on a different backend.
Not supported today
- Cross-backend cross-agent memory access (e.g. SQLite agent reading a Postgres agent’s rows).
- Agent rename (the
agents.idUUID indirection is the rename-ready foundation, but no CLI/UI surface exists). - Pre-delete archive and restore.
- Per-agent secret namespacing: there is a single workspace-wide
SecretStore. - Lucid wire-format extensions for cross-agent scoping.
- A dedicated
zeroclaw agentsmanagement CLI for creating/deleting/listing agents.