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.
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:
- Daedalus does LLM recon and gains a foothold.
- The executive maps the situation to ATT&CK technique / chain IDs.
- Those are queued on a BAS agent in the target's zone (agents poll out through NAT — no inbound ports).
- The agent runs them safely (dry-run by default) and reports what ran and what the defenses caught.
- 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.