License: PolyForm Perimeter 1.0.1 Python 3.10+ Tests: 5800+ Discord Twitter LiteLLM Docker

Run autonomous, self-hosted AI agent fleets that are isolated, auditable, and production-ready. Every agent runs in its own Docker container, API keys never leave the credential vault, and per-agent budgets cap spend. A source-available, security-first OpenClaw alternative for teams. Chat via Telegram, Discord, Slack, or WhatsApp. 100+ LLM providers via LiteLLM.

What is OpenLegion? · Quick Start · OpenLegion vs OpenClaw · Security Model · Docs


Demo

https://github.com/user-attachments/assets/8bd3fe95-5734-474d-92f0-40616daf91ad

openlegion start → inline setup → multiple agents running. Live cost tracking. No configuration files edited by hand. Connect Telegram, WhatsApp, Slack, and Discord.

Table of Contents


What is OpenLegion?

OpenLegion is a secure, self-hosted AI agent runtime for running fleets of autonomous AI agents in production. Each agent runs in its own hardened Docker container (or microVM), with its own memory, tools, schedule, and budget. Agents never hold API keys - every LLM and API call routes through a central credential vault that also enforces per-agent spend limits. A trusted mesh host coordinates the fleet through shared state and pub/sub events, with permission ACLs checked on every cross-agent action.

It is source-available under the PolyForm Perimeter License 1.0.1: you can self-host it for free — including for your own commercial, internal operations — read the entire ~77,000-line codebase, and audit it in a day. The one thing you can't do is offer it to others as a product or service that competes with OpenLegion (e.g. reselling it as your own hosted/managed service). Managed hosting is available from OpenLegion LLC for teams that prefer not to run their own infrastructure. OpenLegion is built as a production- and team-focused OpenClaw alternative - it keeps the autonomy of single-user assistant frameworks and adds container isolation, credential vaulting, per-agent budgets, and auditable workflows.

In one line: a multi-agent framework where security, isolation, and cost control are part of the architecture, not an afterthought.


Who is OpenLegion for?

  • Developers and AI builders who want a programmable, self-hosted runtime for multi-agent systems instead of a hosted black box.
  • Self-hosters and technical founders who need AI agents that run on their own infrastructure, with data and credentials never leaving their control.
  • Teams running agents in production that need per-agent budgets, permission ACLs, Docker/microVM isolation, and a codebase small enough to audit.
  • OpenClaw, CrewAI, LangGraph, and AutoGen users who have outgrown single-user or library-only setups and now need security and cost controls around their agents.
  • Managed-hosting customers who want the same runtime without operating the infrastructure themselves.

If you just want a personal assistant on one machine, a single-user tool is simpler. OpenLegion is for when agents become shared, always-on, or handle anything you cannot afford to leak or overspend.


Quick Start

Requirements: Python 3.10+, Docker (running), at least one LLM provider key (Anthropic, OpenAI, Gemini, Moonshot, Deepseek, xAI, Groq, Minimax, Zai, or Ollama — the setup wizard walks you through it; existing Anthropic Claude CLI or OpenAI Codex CLI logins can be imported).

macOS / Linux:

git clone https://github.com/openlegion-ai/openlegion.git && cd openlegion
./install.sh                     # checks deps, creates venv, makes CLI global
openlegion start                 # inline setup on first run, then launch agents

Windows (PowerShell):

git clone https://github.com/openlegion-ai/openlegion.git
cd openlegion
powershell -ExecutionPolicy Bypass -File install.ps1
openlegion start

Windows note: Docker Desktop (not Docker Engine) is required on Windows. WSL2 must be enabled. See Docker's WSL2 backend guide if containers fail to start.

First install downloads dependencies into a venv; this may take several minutes the first time. Subsequent installs are fast.

First run: On the very first openlegion start, Docker builds the openlegion-agent:latest and openlegion-browser:latest images from the Dockerfile.agent and Dockerfile.browser in the repo root. The browser image is significantly larger (Camoufox + KasmVNC + Openbox + Xvnc) and can take several minutes with no progress output — this is normal. Subsequent starts are fast.

Background mode: openlegion start -d polls for startup for up to 90 seconds. If a Docker image build is needed on first run, this timeout may be exceeded — wait for the build to finish and re-run openlegion start -d.

First run also creates: config/agents.yaml, config/permissions.json, config/mesh.yaml, agent volumes, and an operator agent that you didn't define — that's a built-in fleet-management agent (lighter resource caps, excluded from cost/quota math). See CLI Reference for openlegion reset if you want to wipe state and start over.

Need help? See the full setup guide for platform-specific instructions and troubleshooting.

Common commands

# Start (interactive REPL); use /add inside the REPL to register more agents
openlegion start

# Run in background
openlegion start -d
openlegion chat <agent_name>   # connect from another terminal to an agent you created
openlegion stop                # clean shutdown
openlegion reset               # destructive: wipe config/, data/, agent_tools/* (keeps .env)

OpenLegion vs OpenClaw

OpenLegion is an OpenClaw alternative built for production and team use. OpenClaw is the most popular personal AI assistant framework (200K+ GitHub stars) and is genuinely great for single-user setups. The trade-off shows up once agents become shared, always-on, or handle untrusted input - areas where it has documented security and cost gaps:

  • 42,000+ exposed instances with no authentication (Bitsight, Feb 2026)
  • 341 malicious skills found stealing user data (Koi Security via The Hacker News)
  • CVE-2026-25253: one-click remote code execution
  • No per-agent cost controls — runaway spend is a real risk
  • No deterministic routing — a CEO agent (LLM) decides what runs next
  • API keys stored directly in agent config

OpenLegion was designed from day one assuming agents will be compromised.

OpenClaw OpenLegion
API key storage Agent config files Vault proxy — agents never see keys
Agent isolation Process-level Docker container per agent + microVM option
Cost controls None Per-agent daily + monthly budget caps
Multi-agent routing LLM CEO agent Fleet model — blackboard + pub/sub coordination
LLM providers Broad 100+ via LiteLLM with health-tracked failover
Test coverage Minimal 5800+ tests across 193 test files including full Docker E2E
Codebase size 430,000+ lines ~77,000 lines in src/ — still auditable in a day

What It Does

OpenLegion is an autonomous AI agent framework for running multi-agent fleets in isolated Docker containers. Each agent gets its own memory, tools, schedule, and budget — coordinated through blackboard shared state and pub/sub events with no LLM routing layer.

Chat with your agent fleet via Telegram, Discord, Slack, WhatsApp, or CLI. Agents act autonomously via cron schedules, webhooks, and heartbeat monitoring — without being prompted.

5800+ tests passing across 193 test files. Fully auditable in a day. No LangChain. No Redis. No Kubernetes. No CEO agent. Source-available (PolyForm Perimeter).

  1. Security by architecture — every agent runs in an isolated Docker container (microVM when available). API keys live in the credential vault — agents call through a proxy and never handle credentials directly. Defense-in-depth with 6 security layers.

  2. Production-grade cost control — per-agent LLM token tracking with enforced daily and monthly budget caps at the vault layer. Agents physically cannot spend what you haven't authorized. View live spend with /costs in the REPL.

  3. Acts autonomously — cron schedules, heartbeat probes, and webhook triggers let agents work without being prompted.

  4. Self-aware and self-improving — agents understand their own permissions, budget, fleet topology, and system architecture via auto-generated SYSTEM.md and live runtime context. They learn from tool failures and user corrections, injecting past learnings into future sessions.

  5. Self-extends — agents write their own Python tools at runtime and hot-reload them. Agents can also spawn sub-agents for specialized work.

  6. Multi-channel — connect agents to Telegram, Discord, Slack, and WhatsApp. Also accessible via CLI and API.

  7. Real-time dashboard — web-based fleet observability with consolidated navigation, slide-over chat panels, keyboard command palette, grouped request traces, live event streaming, streaming broadcast with real-time per-agent responses, LLM prompt/response previews, agent management, agent settings editor (personality, instructions, preferences, heartbeat rules, memory, activity logs, learnings), cost charts, cron management, and embedded KasmVNC viewer for persistent browser agents.

  8. Tracks and caps spend — per-agent LLM cost tracking with daily and monthly budget enforcement.

  9. Fails over across providers — configurable model failover chains cascade across LLM providers with per-model health tracking and exponential cooldown.

  10. Token-level streaming — real-time token-by-token LLM responses across CLI, dashboard, Telegram, Discord, and Slack with progressive message editing and graceful non-streaming fallback.


Architecture

OpenLegion's architecture separates concerns across three trust zones: untrusted external input, sandboxed agent containers, and a trusted mesh host that holds credentials and coordinates the fleet. All inter-agent communication flows through the mesh. Agents do not contact each other directly — no direct peer-to-peer connections.

┌──────────────────────────────────────────────────────────────────────────┐
│                           User Interface                                │
│                                                                         │
│   CLI (click)          Webhooks            Cron Scheduler               │
│   - setup              - POST /webhook/    - "0 9 * * 1-5"             │
│   - start (REPL)         hook/{id}         - "every 30m"               │
│   - stop / status      - Trigger agents    - Heartbeat pattern          │
│   - chat / status                                                       │
└──────────────┬──────────────────┬──────────────────┬────────────────────┘
               │                  │                  │
               ▼                  ▼                  ▼
┌──────────────────────────────────────────────────────────────────────────┐
│                         Mesh Host (FastAPI)                              │
│                         Port 8420 (default)                              │
│                                                                         │
│  ┌────────────┐ ┌─────────┐ ┌───────────┐ ┌────────────────────────┐   │
│  │ Blackboard │ │ PubSub  │ │  Message   │ │   Credential Vault     │   │
│  │ (SQLite)   │ │         │ │  Router    │ │   (API Proxy)          │   │
│  │            │ │ Topics, │ │            │ │                        │   │
│  │ Key-value, │ │ subs,   │ │ Permission │ │ LLM, image_gen,        │   │
│  │ versioned, │ │ notify  │ │ enforced   │ │ Apollo, Hunter,        │   │
│  │ TTL, GC    │ │         │ │ routing    │ │ Brave Search           │   │
│  └────────────┘ └─────────┘ └───────────┘ └────────────────────────┘   │
│                                                                         │
│  ┌──────────────┐ ┌──────────────┐ ┌──────────────┐                    │
│  │  Permission  │ │  Container   │ │    Cost      │                    │
│  │  Matrix      │ │  Manager     │ │   Tracker    │                    │
│  │              │ │              │ │              │                    │
│  │ Per-agent    │ │ Docker life- │ │ Per-agent    │                    │
│  │ ACLs, globs, │ │ cycle, nets, │ │ token/cost,  │                    │
│  │ default deny │ │ volumes      │ │ budgets      │                    │
│  └──────────────┘ └──────────────┘ └──────────────┘                    │
└──────────────────────────────────────────────────────────────────────────┘
               │
               │  Docker Network (bridge by default; host opt-in via
               │  OPENLEGION_HOST_NETWORK=1 / _BROWSER_ALLOW_HOST_NETWORK=1)
               │
     ┌─────────┼──────────┬──────────────────────┐
     ▼         ▼          ▼                      ▼
┌─────────┐ ┌─────────┐ ┌─────────┐       ┌─────────┐
│ Agent A │ │ Agent B │ │ Agent C │  ...  │ Agent N │
│ :8400   │ │ :8400   │ │ :8400   │       │ :8400   │
└─────────┘ └─────────┘ └─────────┘       └─────────┘
  Each agent: isolated Docker container, own /data volume,
  own memory DB, own workspace, 384MB RAM, 0.15 CPU. FastAPI
  listens on :8400 *inside* the container; host port is allocated
  dynamically by the runtime. The built-in `operator` agent runs
  with lighter caps (128MB / 0.05 CPU).

To reach an agent from the host, use the mesh proxy at :8420, not the agent's internal :8400.

Trust Zones

Level Zone Description
0 Untrusted External input (webhooks, user prompts). Sanitized before reaching agents.
1 Sandboxed Agent containers. Isolated filesystem, no credentials. External network access gated through SSRF-protected mesh proxy — restricted Docker bridge with NAT egress; private/CGNAT/IPv4-mapped/6to4/Teredo ranges blocked by http_tool.py. The shared browser container has its own iptables egress filter (set up by entrypoint with NET_ADMIN, then dropped) — that is the authoritative SSRF control for browser-initiated traffic.
2 Trusted Mesh host. Holds credentials, manages containers, routes messages.

Mesh Host

The mesh host is the central coordination layer. It runs on the host machine as a single FastAPI process.

Blackboard (Shared State Store)

SQLite-backed key-value store with versioning, TTL, and garbage collection. Team agents' blackboard access is automatically scoped to teams/{name}/* — agents use natural keys (e.g. tasks/research_abc123) while the MeshClient transparently namespaces them under the team. Solo agents have no automatic team scoping; they can access only keys explicitly granted via ACL.

The on-disk prefix is teams/{name}/*.

Namespace Purpose Example
tasks/* Task assignments tasks/research_abc123
context/* Shared agent context context/prospect_acme
signals/* Inter-agent signals signals/research_complete
history/* Append-only audit log history/action_xyz

These prefixes are conventions, not enforced schemas — agents can write any key that matches their blackboard_write glob.

Credential Vault (API Proxy)

Agents never hold API keys. All external API calls route through the mesh. The vault uses a two-tier prefix system: OPENLEGION_SYSTEM_* for LLM provider keys (never agent-accessible) and OPENLEGION_CRED_* for agent-tier tool/service keys. Budget limits are enforced before dispatching LLM calls and token usage is recorded after each response. OPENLEGION_SYSTEM_* credentials are never resolvable by agents (mesh-proxy-only). OPENLEGION_CRED_* are gated by per-agent allowed_credentials. Misclassifying one as the other yields silent invisibility.

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). Streaming failover is supported — if streaming fails mid-response (including empty/zero-length responses that indicate upstream provider failure), the next model in the chain retries the full request from the start.

Permission Matrix

Every inter-agent operation is checked against per-agent ACLs. The shape — agents call the blackboard with natural keys (e.g. read_blackboard("tasks/foo")) and MeshClient transparently namespaces them under the active team, so the patterns below are matched against the resolved key (teams/myteam/tasks/foo):

{
  "researcher": {
    "can_message": ["*"],
    "can_publish": ["research_complete"],
    "can_subscribe": ["new_lead"],
    "blackboard_read": ["teams/myteam/*"],
    "blackboard_write": ["teams/myteam/*"],
    "allowed_apis": ["llm", "brave_search"],
    "allowed_credentials": ["brightdata_*"],
    "browser_actions": null
  }
}

Matching is exact match (or *) for can_message, can_publish, and can_subscribe, and glob (fnmatch) for blackboard_read, blackboard_write, and allowed_credentials.

browser_actions semantics: null (default) = all known actions allowed; ["*"] = explicit allow-all; specific list (e.g. ["browser_navigate", "browser_screenshot"]) = narrow allowlist; [] = deny all browser use even when can_use_browser is true.

Blackboard patterns use the teams/{name}/* namespace. When an agent joins a team, it receives read/write access to that namespace. Solo agents have no automatic team scoping; they can access only keys explicitly granted via ACL.

Team scope is enforced by default (env: OPENLEGION_TEAM_SCOPE_MODE=enforce). Agents in different teams cannot read each other's blackboard without explicit permission.

Container Manager

Agent containers are slim — no browser. Browsing is handled by a shared browser service container (Camoufox + KasmVNC).

Agent container:

  • Image: openlegion-agent:latest (Python 3.12, system tools — no browser)
  • Network: Bridge with port mapping (macOS/Windows) or host network (Linux)
  • Volume: openlegion_data_{agent_id} mounted at /data (agent names with spaces/special chars are sanitized)
  • Resources: 384MB RAM, 0.15 CPU (agents are I/O-bound — waiting on LLM APIs). The built-in operator agent runs at 128MB / 0.05 CPU.
  • Security: no-new-privileges, cap_drop=[ALL], read_only=True, tmpfs=/tmp, non-root UID 1000
  • Port: 8400 (FastAPI, inside the container; host port allocated dynamically)

Browser service container (shared across all agents):

  • Image: openlegion-browser:latest (Camoufox stealth browser + KasmVNC)
  • Resources: 2–8GB RAM, 1–2 CPU, 512MB–2GB shared memory — scaled by OPENLEGION_MAX_AGENTS plan tier
  • Ports: 8500 (browser API) is the only exposed port. Per-agent KasmVNC instances run internally on 6100..6163 and are reverse-proxied by the mesh at /agent-vnc/{agent_id}/... (no direct port exposed to the host).
  • Capacity: autoscales by OPENLEGION_MAX_AGENTS — ≤1 agent → 1 session; ≤5 → 5; ≤15 → min(N, 10); >15 → min(N, 30). Absolute cap 64 via OPENLEGION_BROWSER_MAX_CONCURRENT (legacy alias MAX_BROWSERS). Managed deployments may layer their own plan tiers on top of these autoscale rules. Restart the browser service to apply a change.

Browser Capabilities

Beyond the basic navigation/screenshot/click tools, the browser service ships with:

  • CAPTCHA solving. Optional 2captcha or capsolver provider configured per-fleet via CAPTCHA_SOLVER_KEY + CAPTCHA_SOLVER_PROVIDER. Solver credentials (CAPTCHA_SOLVER_KEY, CAPTCHA_SOLVER_KEY_SECONDARY, CAPTCHA_SOLVER_PROXY_LOGIN, CAPTCHA_SOLVER_PROXY_PASSWORD) are env-only by design — they bypass the OPENLEGION_CRED_* vault and are stripped from config/settings.json at load (_ENV_ONLY_FLAGS in src/browser/flags.py). Auto-solve runs after browser_navigate; behavioral / persistent challenges escalate to request_captcha_help which posts a card to the dashboard for the user to clear via the live VNC viewer. Disabled fleet-wide with CAPTCHA_DISABLED=1. Behavioral / vendor JS challenges that 2captcha and capsolver cannot solve escalate via request_captcha_help, surfacing a VNC card to the user.
  • Per-agent + per-tenant solver cost caps. CAPTCHA_COST_LIMIT_USD_PER_AGENT_MONTH and CAPTCHA_COST_LIMIT_USD_PER_TENANT_MONTH enforce monthly spend with 50/80/100% threshold alerts. Per-tenant rollups available at /dashboard/api/billing/captcha-rollup (requires a dashboard session cookie and the X-Requested-With CSRF header).
  • Fingerprint health monitoring. A rolling per-agent rejection window detects when a fingerprint is "burned" (>50% rejection over the last 10 events across Cloudflare / DataDome / PerimeterX / Imperva / Akamai BMP signals); subsequent CAPTCHA envelopes carry fingerprint_burn=True and a retry_with_fresh_profile hint. Operator clears state manually after profile rotation.
  • JS-challenge detection. Vendor-specific selectors detect Cloudflare 1xxx / Under Attack / Press & Hold and similar interstitials before the agent attempts to extract content.
  • Mobile emulation profiles. BROWSER_DEVICE_PROFILE env var (per-agent or fleet-wide) selects a mobile UA + viewport + touch profile when sites gate on desktop fingerprints. Configured via env, not the dashboard.
  • Session continuity (opt-in). BROWSER_SESSION_PERSISTENCE_ENABLED=1 enables a per-agent storage-state sidecar so cookies and localStorage survive container restarts. Default-off; operator/curl-only management via /dashboard/api/agents/{id}/session.
  • Two-stage workspace upload. browser_upload_file reads from the agent's /data and uploads via a stage-then-apply protocol with idempotency keys and a tmpfs partial reaper, so a half-completed upload can never end up attached to a form. Per-file cap 50 MB (OPENLEGION_UPLOAD_STAGE_MAX_MB), max 5 files per call.

Agent Architecture

Each agent container runs a FastAPI server with endpoints for task assignment, chat, status, capabilities, and results.

┌─────────────────────────────────────────────────────────────┐
│                    Agent Container                           │
│                                                              │
│  FastAPI Server (:8400)                                      │
│    POST /task    POST /chat    POST /chat/reset               │
│    GET /status   GET /result   GET /capabilities              │
│    GET /workspace  GET|PUT /workspace/{file}                  │
│    GET /heartbeat-context                                     │
│                                                              │
│  ┌──────────────────────────────────────────────────────┐    │
│  │                     AgentLoop                         │    │
│  │                                                       │    │
│  │  Task Mode: bounded 20-iteration loop                 │    │
│  │  Chat Mode: conversational with tool use              │    │
│  │                                                       │    │
│  │  Both: LLM call → tool execution → context mgmt      │    │
│  └──┬──────────┬──────────┬──────────┬──────────┬───────┘    │
│     │          │          │          │          │             │
│  ┌──▼───┐  ┌──▼───┐  ┌──▼──────┐ ┌─▼──────┐ ┌─▼─────────┐ │
│  │ LLM  │  │ Mesh │  │ Tool   │ │Work-   │ │ Context   │ │
│  │Client│  │Client│  │Registry │ │space   │ │ Manager   │ │
│  │(mesh │  │(HTTP)│  │(builtins│ │Manager │ │(token     │ │
│  │proxy)│  │      │  │+custom) │ │(/data/ │ │tracking,  │ │
│  └──────┘  └──────┘  └─────────┘ │workspace│ │compact)   │ │
│                                   └─────────┘ └───────────┘ │
└─────────────────────────────────────────────────────────────┘

Task Mode (POST /task)

Accepts a TaskAssignment for task execution. Runs a bounded loop (max 20 iterations) of decide → act → learn. Returns a TaskResult with structured output and optional blackboard promotions.

Chat Mode (POST /chat)

Accepts a user message. On the first message, loads bootstrap workspace files into the system prompt — TEAM.md (team members only), SYSTEM.md, INSTRUCTIONS.md, SOUL.md, USER.md, MEMORY.md — injects a live Runtime Context block (permissions, budget, fleet, cron), and searches memory for relevant facts. Executes tool calls in a bounded loop with three caps from loop.py: CHAT_MAX_TOOL_ROUNDS=30 per turn, CHAT_MAX_TOTAL_ROUNDS=200 total before auto-compaction kicks in, and _MAX_SESSION_CONTINUES=5 auto-continuations (hardcoded, not env-overridable — after which the session halts with an error rather than continuing forever).

Tool Loop Detection

Both modes include automatic detection of stuck tool-call loops. A sliding window tracks recent (tool_name, params_hash, result_hash) tuples and escalates through three levels:

Level Trigger Action
Warn 2nd identical call System message: "Try a different approach"
Block 4th identical call Tool skipped, error returned to agent
Terminate 9th call with same params Loop terminated with failure status

memory_search is exempt since repeated searches are legitimate. Detection uses SHA-256 hashes of canonicalized parameters and results over a 15-call sliding window.

Built-in Tools

Tool Purpose
run_command Shell command execution with timeout
read_file Read file contents from /data
write_file Write/append file in /data
list_files List/glob files in /data
http_request HTTP GET/POST/PUT/DELETE/PATCH
browser_navigate Open URL, extract page text via shared browser service. Auto-detects CAPTCHAs and may auto-solve or surface a help envelope.
browser_get_elements Accessibility tree snapshot with element refs (e1, e2, ...)
browser_find_text Locate elements by visible/accessible name (Unicode case-fold match)
browser_screenshot Capture page screenshot
browser_click Click element by ref or CSS selector
browser_click_xy Click at viewport-relative pixel coordinates (canvas / non-accessible widgets)
browser_type Fill input by ref or CSS selector
browser_fill_form Fill multiple labeled form fields in one call
browser_hover Hover over element to trigger dropdowns/tooltips
browser_scroll Scroll page up/down or scroll element into view
browser_wait_for Wait for CSS selector to appear/disappear
browser_press_key Press keyboard key or shortcut (Escape, Enter, Control+a)
browser_go_back / browser_go_forward Navigate browser history
browser_open_tab Open a URL in a new tab (becomes the active page)
browser_switch_tab List open tabs or switch to a specific tab
browser_upload_file Upload workspace files to a file-input element (1-5 files)
browser_download Click a ref to trigger a download and save it as an artifact (≤50MB)
browser_inspect_requests List recent network request URLs (redacted; no bodies or headers)
browser_reset Reset browser session (profile preserved)
browser_detect_captcha CAPTCHA detection (usually not needed — browser_navigate auto-detects)
browser_solve_captcha Explicitly request a CAPTCHA solve on the current page
request_captcha_help Hand a behavioral / persistent CAPTCHA to the user via the dashboard viewer
request_browser_login Navigate browser to a URL and send a VNC login card to the user for manual credential entry
generate_image Generate an image via Gemini or DALL-E 3 and save as an artifact
memory_search Hybrid search across workspace files and structured DB
memory_save Save fact to workspace and structured memory DB
web_search Search the web via DuckDuckGo (HTML scrape — no API key, but subject to occasional rate limits / CAPTCHAs)
notify_user Send notification to user across all connected channels
list_agents Discover agents on your team (solo agents see only themselves)
read_blackboard Read from the shared blackboard
write_blackboard Write to the shared blackboard
list_blackboard Browse blackboard entries by prefix
publish_event Publish event to mesh pub/sub
subscribe_event Subscribe to a pub/sub topic at runtime
hand_off Hand a work item to another agent via structured coordination protocol
check_inbox Check for pending work items handed off by other agents
update_status Update the status of an in-progress work item visible to coordinators
complete_task Mark a coordination work item as complete with a result
watch_blackboard Watch blackboard keys matching a glob pattern
claim_task Atomically claim a task from the shared blackboard
save_artifact Save deliverable file and register on blackboard
update_workspace Update identity files (SOUL.md, INSTRUCTIONS.md, USER.md, HEARTBEAT.md)
set_cron Schedule a recurring job (set heartbeat=true for autonomous wakeups)
list_cron / remove_cron Manage scheduled jobs
create_tool Write a new Python tool at runtime
reload_tools Hot-reload all tools
spawn_fleet_agent Spawn an ephemeral sub-agent in a new container
spawn_subagent Spawn a lightweight in-container subagent for parallel subtasks
list_subagents List active subagents and their status
wait_for_subagent Wait for a subagent to complete and return its result
vault_generate_secret Generate and store a random secret (returns opaque handle)
vault_list List credential names (names only, never values)
wallet_get_address Get Ethereum/Solana wallet address for an agent (requires [wallet] extras)
wallet_get_balance Get wallet balance (ETH or SOL) (requires [wallet] extras)
wallet_read_contract Read data from an Ethereum smart contract (requires [wallet] extras)
wallet_transfer Transfer ETH or SOL to an address (requires [wallet] extras)
wallet_execute Execute an Ethereum smart contract function (requires [wallet] extras)
get_system_status Query own runtime state: permissions, budget, fleet, cron, health
read_agent_history Read another agent's conversation logs

Custom tools are Python functions decorated with @tool, auto-discovered from the agent's tools_dir at startup. Agents can also create new tools at runtime and hot-reload them.

Agents also support MCP (Model Context Protocol) — any MCP-compatible tool server can be plugged in via config, giving agents access to databases, filesystems, APIs, and more without writing custom tools.


Operator & Teams

OpenLegion is built around one autonomous loop: you talk to the operator, the operator builds teams, and the fleet carries the work toward a goal — pulling you in for credentials, approvals, or genuine forks, not for routine coordination.

  • Operator — a built-in agent (operator; lighter caps, excluded from cost/quota math) that is your entry point. It creates agents and teams, sets goals, watches progress, and reallocates work. It is the only agent that can apply fleet templates, install a team lead, or confirm hard config edits. It is not a message router — work still flows peer-to-peer.

  • Team lead — every non-solo team has one accountability owner. The mesh auto-appoints the first non-operator member the moment a team reaches two or more real members (on create and on add), and re-appoints another member automatically whenever the current lead leaves by any path (removed, offboarded, evicted by a move, or deleted). The lead is an ordinary member under the ordinary security model — it plans and stewards, gaining no routing privilege. Team stewardship (goal-coverage probes, standups, blocked-task escalation, delivery review) is gated on there being a lead, so a leaderless team is never silently left un-stewarded.

  • Goals that reach the workers — the operator sets a team's north star and up to ten success criteria with set_team_goal. The goal is persisted, mirrored into a ## Goal section of the team's TEAM.md, and pushed to members — so a running worker picks it up on its next turn, not only at onboarding. Redirecting a busy team is no longer inert. update_team_context (writes ## Context) and team briefs are section-scoped, so updating one never clobbers the goal.

  • A spend envelope per team — teams carry daily/monthly USD budgets the operator reallocates within. Enforcement can be set fail-closed (OPENLEGION_TEAM_ENVELOPE_FAIL_CLOSED, default fail-open) so a budget-store outage stops spend instead of waving it through.

  • Observe and correct, without leaving chatinspect_teams (goal, criteria, budget), inspect_team_spend (per-team spend by period), inspect_agents at profile depth (budget headroom + track record), and assess_team_progress (success criteria bundled with the team's actual completed outputs, for an evidence-grounded verdict). The dashboard Team Room shows the goal side at a glance: north star, success criteria, probe names, and each member's current and blocked work. (Per-team spend is an inspect_team_spend / mesh read, not shown in the Team Room.)

Honest failure is part of the loop: when a worker asks for a credential that cannot be delivered, request_credential returns an explicit failure envelope instead of reporting success — so autonomous work parks visibly rather than silently forever.

Today's guardrails are spend caps + Docker/microVM isolation + SSRF egress filtering. By design the current posture does not yet gate individual outbound actions (publish / email / purchase) behind a broker; that action-broker layer and an immutable human spend ceiling are planned follow-ups. See docs/plans/2026-07-16-autonomous-team-delivery.md for the roadmap and current implementation status.


Memory System

Five layers give agents persistent, self-improving memory:

Layer 5: Context Manager          ← Manages the LLM's context window
  │  Monitors token usage
  │  Proactive flush at 60% capacity
  │  Auto-compacts at 70% capacity
  │  Extracts facts before discarding messages
  │
Layer 4: Learnings                ← Self-improvement through failure tracking
  │  learnings/errors.md         (tool failures with context)
  │  learnings/corrections.md   (user corrections and preferences)
  │  Auto-injected into system prompt each session
  │
Layer 3: Workspace Files          ← Durable, human-readable storage
  │  Bootstrap files loaded into the first-message system prompt:
  │    TEAM.md (team members only), SYSTEM.md, INSTRUCTIONS.md,
  │    SOUL.md, USER.md, MEMORY.md
  │  Other workspace files:
  │    HEARTBEAT.md             (autonomous monitoring rules)
  │    INTERFACE.md, AGENTS.md  (channel + roster context)
  │    memory/YYYY-MM-DD.md     (daily session logs)
  │  FTS5 keyword search across files
  │
Layer 2: Structured Memory DB     ← Hierarchical vector database
  │  SQLite + sqlite-vec + FTS5
  │  Hybrid search: 0.7 vector similarity + 0.3 FTS5 keyword
  │  Auto-categorization with category-scoped search
  │  3-tier retrieval: categories → scoped facts → flat fallback
  │  Reinforcement scoring with access-count boost + recency decay
  │
Layer 1: Salience Tracking        ← Prioritizes important facts
     Access count, decay score, last accessed timestamp
     High-salience facts auto-surface in initial context

Write-Then-Compact Pattern

Before the context manager discards messages, it:

  1. Asks the LLM to extract important facts from the conversation
  2. Stores facts in both MEMORY.md and the structured memory DB
  3. Summarizes the conversation
  4. Replaces message history with: summary + last 3–4 messages (role-aware, preserving message alternation invariant)

Nothing is permanently lost during compaction.

Cross-Session Memory

Facts saved with memory_save are stored in both the workspace (daily log) and the structured SQLite database. After a reset or restart, memory_search retrieves them via hybrid search:

Session 1: User says "My cat's name is Whiskerino"
           Agent saves to daily log + structured DB

  ═══ Chat Reset ═══

Session 2: User asks "What is my cat's name?"
           Agent recalls "Whiskerino" via memory_search

Triggering & Automation

Agents act autonomously through trigger mechanisms running in the mesh host (not inside containers, so they survive container restarts).

Cron Scheduler

Persistent cron jobs that dispatch messages to agents on a schedule. Agents can schedule their own jobs using the set_cron tool.

Supports 5-field cron expressions (minute hour dom month dow), interval shorthand (every 30m, every 2h), and state persisted to config/cron.json. Cron jobs can also dispatch in tool-mode (tool_name + tool_params), invoking a built-in tool directly without an LLM round — useful for cheap deterministic monitoring. For example, set_cron with tool_name="http_request" and tool_params={"url": "...", "method": "GET"} polls an endpoint on a schedule without spending tokens.

Heartbeat System

Cost-