Multi-tenant agent platform architecture, security model, coordination patterns, and skill development
Folders are agents. Each folder is a tenant: isolated memory, persona, skills, routes. MCP over unix socket. Tool calls go through `gated`; host controls what agents can reach. Defense-in-depth. Container isolation + DNS filtering + per-group MCP sockets + secret injection.
Each folder is a tenant. Authority is scoped by path depth:
| Tier | Folder Path | Authority | Tools Available |
|---|---|---|---|
| 0 | root |
Unrestricted | All MCP tools, migrations, vhost management |
| 1 | world/ |
World-scoped | Routing, group creation, token issuance, observe |
| 2 | world/team/ |
Send-only | Reply, like, send_file, observe (read-only) |
Folder depth determines tier. gated enforces grants at tool-call time.
No privilege escalation — agents can only delegate to children or escalate to parent.
When a message arrives:
platform=, chat_jid=, sender=)/home/node/ (group workspace), /workspace/web/ (optional web surface)gated via MCP socket
Containers are ephemeral. All state is in /home/node/ (volume-mounted) or
messages.db (WAL, host-side SQLite).
| Primitive | Lifecycle | Isolation | Use |
|---|---|---|---|
| Group | Persistent | Folder boundary | Agent identity, memory, persona, skills |
| Topic | Transient | Session ID | One conversation thread, forkable |
| Session | Ephemeral | Claude Code session | LLM context window, reset via /new |
| Layer | Mechanism | Threat Mitigated |
|---|---|---|
| Container | Docker isolation, no --privileged |
Process escape, host filesystem access |
| Network | Crackbox DNS filtering + allowlist | Exfiltration, C2 communication |
| MCP | Per-group unix socket, grants enforced by gated |
Cross-tenant tool access, privilege escalation |
| Secrets | AES-256-GCM at rest, env-var injection, no disk persistence | Secret theft via disk access or container inspect |
Per-folder egress sandbox. Wraps each container with:
--security-opt no-new-privileges
Agent can only reach what operator explicitly permits. Example allowlist:
["api.anthropic.com", "*.github.com", "pypi.org"].
See crackbox docs and
SECURITY.md.
Each group gets its own unix socket (/ipc/<group_id>.sock).
gated brokers every tool call, enforces grants, and logs actions.
Agents cannot reach other groups' sockets — Docker mounts only the agent's own socket.
Secrets are AES-256-GCM encrypted in secrets.db. At container start,
gated decrypts and injects as env vars. No disk persistence inside container.
Secrets never written to /home/node/ or logs.
Three MCP tools for hierarchical coordination:
delegate_group(group, prompt, chatJid) —
hand work down to a child. Child runs async, parent doesn't block.
escalate_group(prompt, chatJid) —
hand work up to parent. Parent responds back through this child.
observe_group(source) —
watch another group's messages without taking over.
Use delegate for specialist work. Use escalate when authority is needed.
Use observe for ambient awareness (sibling monitoring, aggregation).
fork_topic(parent, child) — create a new topic from another's session state.
Child gets a fresh session ID but starts with parent's Claude Code context. Use for:
Skills can specify ALWAYS or NEVER triggers in SKILL.md:
ALWAYS:
- "download this video" → acquire
- "transcribe this" → acquire
NEVER:
- Static pages → do NOT use agent-browser, use acquire instead
Gateway reads these at session start and surfaces them in <skills> block.
Agent uses them for fast dispatch without re-reading every SKILL.md.
Pattern for long-running tasks that survive session resets:
~/state/.json Named after "ralph loop" (stateless iteration). Use for multi-page scrapes, batch processing, or any task that takes >1 session.
For APIs with pagination or long-running operations:
~/state/ or ~/facts/page=N), Stripe list cursorsDetect file changes without storing full content:
~/state/fingerprints.jsonUse for monitoring codebases, watching config files, or tracking external resources.
Chain multiple agents for staged processing:
ingest → classify → route → specialist → review → publish
Each stage is a separate group. Use delegate_group or direct message routing.
Example: support intake → triage agent → specialist teams → summary agent → publish.
| Aspect | MCP Tools | In-Context Skills |
|---|---|---|
| Context window | Tool name + description only | Full SKILL.md in system prompt |
| Authority | Host-enforced grants | Agent-enforced (prompt-based) |
| State | Stateless, always available | Loaded at session start, persists |
| Best for | Platform operations (routing, groups, tokens) | Workflow patterns, domain knowledge, multi-step procedures |
Rule: Use MCP for side effects (send message, create group, issue token). Use in-context skills for knowledge and workflow guidance.
Each skill is a directory under ~/.claude/skills/<name>/ with:
SKILL.md — description, workflow, ALWAYS/NEVER triggers
Gateway reads SKILL.md at session start, injects into system prompt.
Skills compose — agent can invoke multiple skills per turn.
(Research in progress. Placeholder for skill discovery, versioning, dependencies, and performance evals.)
Measurable improvements from skill-based workflows: