Overview
Trust Zones
OpenLegion defines four trust zones plus a 2.5 operator-or-internal tier. Defense-in-depth: each zone has its own credential set, network policy, and entry conditions.| Level | Zone | Allowed actions |
|---|---|---|
| 0 | Untrusted | External input — webhook bodies (1MB cap), channel messages, user prompts. Sanitized via sanitize_for_prompt() before reaching agents. |
| 1 | Sandboxed (agents) | Agent containers. UID 1000, cap_drop=ALL, no-new-privileges, read-only root FS, tmpfs=/tmp 100m noexec/nosuid. No LLM API keys — all provider calls proxy through mesh. |
| 2 | Trusted (mesh) | Mesh host process. Holds credentials, manages containers, routes inter-agent messages. |
| 2.5 | Operator-or-internal | _require_operator_or_internal gate. Fleet-wide metrics, per-agent metrics, stale-tasks, audit/archive endpoints. |
| 3 | Loopback-only | Requires both x-mesh-internal: 1 header and loopback IP. Caddy strips x-mesh-internal from inbound public traffic. |
Mesh Host
The mesh host is the central coordination layer — a single FastAPI process running on the host machine.Blackboard
SQLite WAL key-value store with atomic CAS viawrite_if_version and an audit log that supports undo/archive. Keys are auto-namespaced under projects/{name}/ so fleets in different projects can’t collide.
| Namespace | Purpose | Example |
|---|---|---|
tasks/* | Task assignments and handoffs | tasks/researcher/h_abc123 |
context/* | Shared agent context | context/prospect_acme |
signals/* | Inter-agent signals | signals/research_complete |
history/* | Append-only audit log | history/action_xyz |
PubSub & Lanes
PubSub fan-outs events to subscribers; both publish and subscribe are gated bycan_publish / can_subscribe. Lanes are per-agent FIFO queues with three modes:
followup(default) — append-and-wake.steer— inject into a busy agent’s loop (rate-limited 10 wakeups / 3600s).collect— batch messages while busy; drain on idle.
MessageRouter resolves either a literal agent ID or capability:<name> to a container URL and blocks cross-project routing when OPENLEGION_PROJECT_SCOPE_MODE=enforce.
Credential Vault
Agents never hold API keys. All external API calls route through the mesh. The vault uses a two-tier prefix system:OPENLEGION_SYSTEM_*— LLM provider keys and other mesh-only secrets. Never agent-accessible.OPENLEGION_CRED_*— agent-tier credentials. Access controlled per-agent viaallowed_credentials(fnmatch glob, case-insensitive).
$CRED{name}) — the real value is substituted by the mesh proxy. The handle is the only thing visible inside the agent container.
Model Failover
Configurable failover chains cascade across LLM providers transparently.ModelHealthTracker applies exponential cooldown per model (transient errors: 60s -> 300s -> 1500s, billing/auth errors: 1h). Permanent errors (400, 404) don’t cascade. Streaming failover is supported — if a connection fails mid-stream, the next model in the chain picks up.
Permission Matrix
Every inter-agent operation is checked against per-agent ACLs inconfig/permissions.json. Default policy: deny; missing file means deny-all.
can_use_browser, browser_actions (allowlist or ["*"]), can_spawn, can_manage_cron, can_use_wallet, wallet_allowed_chains, wallet_spend_limit_per_tx_usd, wallet_spend_limit_daily_usd, wallet_rate_limit_per_hour, wallet_allowed_contracts, plus six control-plane flags (can_manage_fleet, can_manage_projects, can_edit_agent_config, can_view_fleet_metrics, can_route_tasks, can_request_user_credentials).
Operator (reserved role)
A reserved agent ID,operator, is auto-created at startup. In managed hosting it is the user’s primary chat partner — the agent that can manage your fleet on your behalf (apply templates, edit agents, archive projects, confirm hard edits). Resources are lighter than a worker: 128MB RAM, 0.05 CPU (workers default to 384MB / 0.15 CPU). The operator has the control-plane flags listed above set to true by default.
Operator ceiling: the operator cannot grant can_spawn=true or can_use_wallet=true to any agent. Those capabilities must be set by a human operator outside the chat surface.
Container Manager
Each agent runs in an isolated Docker container with:- Image:
openlegion-agent:latest(Python 3.12, slim, no Node.js). - Network: Docker bridge with port mapping (macOS/Windows) or host network (Linux).
- Volume:
openlegion_data_{agent_id}mounted at/data(names with spaces/special chars are sanitized). - Resources (worker): 384MB RAM, 0.15 CPU quota,
pids_limit=256. - Resources (operator): 128MB RAM, 0.05 CPU quota.
- Security:
no-new-privileges, runs as UID 1000, read-only root filesystem,cap_drop=ALL,tmpfs=/tmp100MB noexec/nosuid. - Port: every agent container listens on
:8400internally. The mesh bridges across Docker IPs — there is no incrementing port-per-agent.
:8500 and hosts one Camoufox per agent on Xvnc displays :100..:163 (64 slots) paired with KasmVNC ports 6100..6163. Resources scale with OPENLEGION_MAX_AGENTS: Basic (≤1 agent) 2GB/512MB/1.0 CPU; Growth (2–5) 4GB/1GB/1.5 CPU; Pro (6–15) 8GB/2GB/2.0 CPU; Pro Max (>15) 16GB/4GB/4.0 CPU. Note: OPENLEGION_MAX_AGENTS=0 (the default for “unlimited”) counter-intuitively maps to the Basic tier.
The browser container has its own egress filter (iptables OUTPUT REJECTs RFC1918, loopback, link-local, CGNAT, and IANA-reserved IPv4+IPv6; allows in-container loopback; fail-closed). See Security.
Projects
Multi-project namespaces let you run separate agent fleets with isolated configuration. Each project has its ownagents.yaml, permissions.json, and auto-scoped blackboard — keys are namespaced under projects/{name}/ so fleets in different projects can’t collide. OPENLEGION_MAX_PROJECTS (default unlimited) caps the number of projects.
Design Principles
| Principle | Rationale |
|---|---|
| Messages, not method calls | Agents communicate through HTTP/JSON. Never shared memory or direct invocation. |
| The mesh is the only door | No agent has network access except through the mesh. No agent holds credentials. |
| Private by default, shared by promotion | Agents keep knowledge private. Facts are explicitly promoted to the blackboard. |
| Default deny, fail-closed | Permissions deny by default; SSRF and egress filters reject on DNS error or missing rule. |
| Fleet model, not hierarchy. No CEO agent. | Coordination is blackboard + pub/sub + handoffs, not a master agent routing tasks. |
| Small enough to audit | ~77,000 lines in src/. The runtime is auditable in a day. |
| Skills over features | New capabilities are agent skills, not mesh-level code. |
| SQLite for all state | Single-file databases. No Redis, no external services. WAL mode for concurrent reads. |
| Zero vendor lock-in | LiteLLM supports 100+ providers. Markdown workspace files. No proprietary formats. |
