Skip to main content
Each agent runs inside its own Docker container, serving a FastAPI app on :8400 with endpoints for task assignment, chat, status, capabilities, and results. Every agent container listens on the same port — the mesh bridges across Docker IPs.

Workers vs the Operator

Every agent is either a worker or the operator — the latter is a reserved agent ID auto-created at startup.
WorkerOperator
Resources384MB RAM / 0.15 CPU128MB RAM / 0.05 CPU
ToolsGranted via permissionsOperator-only tool surface (fleet_tool, operator_tools) plus standard tools
HeartbeatConfigurableForce-locked to every 15m
Control-plane flagsDefaults falseDefaults true (manage fleet/projects/agents, view metrics, route tasks, request creds)
Ceilingn/aCannot grant can_spawn=true or can_use_wallet=true
In managed hosting the operator is your primary chat partner — the agent you talk to when you say “spin up a new researcher” or “what’s my fleet doing today”.

Agent Container

┌─────────────────────────────────────────────────────────────┐
│                    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:    MAX_ITERATIONS=20                      │  │
│  │  Chat Mode:    CHAT_MAX_TOOL_ROUNDS=30 per turn,      │  │
│  │                CHAT_MAX_TOTAL_ROUNDS=200 per session, │  │
│  │                _MAX_SESSION_CONTINUES=5               │  │
│  │  Heartbeat:    HEARTBEAT_MAX_ITERATIONS=12            │  │
│  │                                                       │  │
│  │  All modes: LLM call -> tool execution -> context mgmt│  │
│  └──┬──────────┬──────────┬──────────┬──────────┬───────┘  │
│     │          │          │          │          │           │
│  ┌──▼───┐  ┌──▼───┐  ┌──▼──────┐ ┌─▼──────┐ ┌─▼─────────┐  │
│  │ LLM  │  │ Mesh │  │ Skill   │ │Work-   │ │ Context   │  │
│  │Client│  │Client│  │Registry │ │space   │ │ Manager   │  │
│  │(mesh │  │(HTTP)│  │(builtins│ │Manager │ │(token     │  │
│  │proxy)│  │      │  │+custom) │ │(/data/ │ │tracking,  │  │
│  └──────┘  └──────┘  └─────────┘ │workspace│ │compact)   │  │
│                                  └─────────┘ └───────────┘  │
└─────────────────────────────────────────────────────────────┘

Task Mode

Accepts a TaskAssignment from another agent or the operator. Runs a bounded loop (max 20 iterations, clamp 1–100 via OPENLEGION_MAX_ITERATIONS) of decide -> act -> learn. Returns a TaskResult with structured output and optional blackboard promotions. Task mode is used when an agent is given a specific objective with expected output — typically via the coordination tool’s hand_off.

Chat Mode

Accepts a user message. On the first message, loads workspace context — SOUL.md, INSTRUCTIONS.md, USER.md, MEMORY.md, HEARTBEAT.md, INTERFACE.md, AGENTS.md, plus read-only PROJECT.md and SYSTEM.md — into the system prompt (total bootstrap injection cap 48K chars), injects a live Runtime Context block (permissions, budget, fleet, cron), and searches memory for relevant facts. Per-turn cap: CHAT_MAX_TOOL_ROUNDS=30 (clamp 1–200). Session-total cap: CHAT_MAX_TOTAL_ROUNDS=200 (clamp 1–1000). Continuation prompts after a clean stop: _MAX_SESSION_CONTINUES=5. Chat mode is used for interactive conversations via CLI, Telegram, Discord, Slack, WhatsApp, or Webhook channels.

Heartbeat Mode

When a cron with heartbeat=true fires, the agent runs at most HEARTBEAT_MAX_ITERATIONS=12 iterations against an enriched context: HEARTBEAT.md rules, recent daily logs, probe alerts, and pending signal/task content. If the dispatch satisfies the skip-LLM optimization, the LLM is never called. See Triggering & Automation.

Self-Extending Skills

Agents can write their own Python skills at runtime using the create_skill tool and hot-reload them via reload_skills. Candidates run through an AST validator with 23 forbidden imports, 16 forbidden calls, and 11 forbidden attribute accesses (size cap 10,000 chars).
@skill(
    name="your_tool",
    description="What this does and when to use it",
    parameters={
        "param1": {"type": "string", "description": "What this param is for"},
    },
)
async def your_tool(param1: str, *, mesh_client=None) -> dict:
    return {"result": "value"}
Custom skills are Python functions decorated with @skill, auto-discovered from the agent’s skills_dir at startup.

Self-Improving via Learnings

Agents track tool failures in learnings/errors.md and user corrections in learnings/corrections.md. These are automatically injected into the system prompt each session, so agents avoid repeating past mistakes.

Tool Loop Detection

Both task and chat 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:
LevelTriggerAction
Warn2nd repeatSystem message: “Try a different approach”
Block4th repeatTool call skipped, error returned to agent
Terminate9th repeatLoop terminated with failure status
Memory retrieval tools (memory_search) are exempt — repeated searches are legitimate.

Spawning Other Agents

Agents have two paths to create helpers:
  • spawn_fleet_agent (from skill_tool) — creates a fully isolated container agent through the mesh host. Requires can_spawn=true, which the operator cannot grant. Useful for tasks that need their own tools, memory, and security boundary.
  • subagent_tool (spawn / list / wait) — creates a lightweight in-process subagent. Faster startup but shares the parent’s process.
Subagent limits: MAX_CONCURRENT=3 per parent, MAX_DEPTH=2 (parent → subagent → sub-subagent, then stop), default TTL 300s (max 600s), DEFAULT_MAX_ITERATIONS=10. Subagents cannot recurse beyond depth 2, cannot create skills, and cannot run browser tasks concurrently (the browser tool holds module-level per-agent state).

Workspace Files

Agents persist state at /data/workspace/. Caps and purpose are documented in detail in Memory System — the scaffold set is SOUL.md (4K), INSTRUCTIONS.md (12K), USER.md (4K), MEMORY.md (16K), HEARTBEAT.md (uncapped), INTERFACE.md (4K), with AGENTS.md (12K) at the engine root. PROJECT.md and SYSTEM.md are read-only bootstrap inclusions (SYSTEM.md 6K, auto-generated, refreshed every 5 min).