Skip to content

Architecture

Daedalus splits cleanly into a control plane that holds all state and never touches a target, and an executor that is the only thing that runs untrusted, agent-authored commands. Inference — the LLM reasoning that drives the agents — is a third, pluggable tier.

Daedalus platform architecture

Control-plane flow

flowchart TB
    subgraph Orchestrator["Orchestrator — control plane"]
        API["REST API + web console"]
        SCH["Scheduler<br/>(dispatch + concurrency cap)"]
        RUN["Runner<br/>(one turn = one agent dispatch)"]
        ACC["Accountant<br/>(budget ledger, per-team)"]
        MCP["Board tools<br/>(what agents call)"]
        DB[("SQLite<br/>agents · tasks · ledger · findings")]
        API --- SCH --- RUN --- ACC
        RUN --- MCP
        API --- DB
    end

    subgraph Inference["Inference"]
        OLL["Ollama<br/>local GPU models"]
        CLOUD["Cloud LLM CLI<br/>(configurable executive)"]
    end

    subgraph Executor["Executor — sandbox"]
        EXE["Sandbox API"]
        SB["ephemeral tool containers<br/>isolated · vpn · lan"]
        EXE --> SB
    end

    RUN -->|local turn| OLL
    RUN -->|cloud turn| CLOUD
    MCP -->|run_in_sandbox| EXE

Components

Component Role
Control plane REST API, web console, in-process scheduler; owns all state
Scheduler decides which agents run and when; enforces the concurrency cap and the rate-limit / autonomy brakes
Runner executes one agent turn end to end: reserve → spawn → stream → settle
Accountant the budget ledger — reservations, settlement, per-team ceilings
Board tools the tools agents call: task / flag / foothold / vuln / sandbox
Local provider an agentic ReAct loop over local Ollama models
Web console mobile-first UI (Board · Recon · Findings · Activity · Config)
Sandbox API runs each command in a fresh, isolated tool container

Why two hosts

The orchestrator holds state and never touches a target directly. The executor is the only thing that runs untrusted, agent-authored commands, and it does so in throwaway containers on an isolated network. Keeping them separate means the blast radius of a rogue command is one disposable container, not the control plane.

Ingress

The console and API sit behind an identity-aware proxy: requests must carry a valid access assertion or they are refused at the edge, before they ever reach the application. Health and metrics endpoints, and the public agent-distribution path, are the deliberate exceptions. Interactive shells are proxied to the executor on a separate path. See RBAC & access for how identity flows through to per-feature authorization.

Distributed BAS

Beyond single-node testing, Daedalus composes with Halberd, a breach-and-attack simulation agent fleet, to turn a single foothold into measured detection coverage:

  1. Daedalus does LLM recon and gains a foothold.
  2. The executive maps the situation to ATT&CK technique / chain IDs.
  3. Those are queued on a BAS agent in the target's zone (agents poll out through NAT — no inbound ports).
  4. The agent runs them safely (dry-run by default) and reports what ran and what the defenses caught.
  5. Results are stored as detection-coverage data, cross-linked to findings by ATT&CK technique, and surface in the report's Validation & detection coverage section.

BAS runs on real endpoints you control — installing an agent on a host is the consent for that host. Dry-run is the default, risk levels gate what can run, and a confirm step guards any live (non-dry-run) execution.