Wazuh Autopilot is a self-hosted platform that works your Wazuh alerts with a swarm of Strands agents. They reach Wazuh only through the Wazuh MCP Server (v4.3.0, 55 tools). Alerts become incidents. Agents triage, correlate, investigate, enrich and plan the response, and every containment step goes through an autonomy policy you control, from "observe only" to "fully autonomous for low-risk actions". Everything runs in one container plus Postgres and ships with a web console.
⚡ Minutes, not hours · 🤖 13 agents / 37 skills · 🧭 NIST · MITRE · CIS · ISO · PCI · ✅ Policy-gated response · 🔭 Full tracing · 🔒 Air-gap ready
Quick start
git clone https://github.com/gensecaihq/Wazuh-Autopilot.git && cd Wazuh-Autopilot
docker compose -f docker-compose.yml -f docker-compose.demo.yml up -d --build
open http://localhost:8480 # [email protected] / Autopilot!2026
The demo runs against a simulated Wazuh fleet (mock-wazuh/: same tools and schemas as the real MCP server, live alerts, two planted compromises) and a scripted demo model, so it needs neither Wazuh nor an LLM key. Tool calls, policy decisions, approvals, execution and verification are all real. To see real reasoning, pick a model in Settings → Models.
For production, cp .env.example .env, point it at your Wazuh MCP Server and model provider, and run docker compose up -d. The first visit opens the setup wizard. See docs/QUICKSTART.md and docs/DEPLOYMENT.md.
Before enabling active response: the MCP key needs wazuh:write scope, and isolate_host, kill_process and quarantine_file rely on active-response scripts that don't ship with Wazuh, so deploy them on your agents first (details).
Upgrading from 1.x: 3.0 replaces the Node Runtime Service and the OpenClaw, Hermes and NemoClaw profiles with the Strands platform, and there's no in-place migration. Deploy 3.0 next to your existing install, point it at the same Wazuh MCP Server, and retire the old one once you're happy. Details in the changelog.
What you get
How it works
Wazuh ──► Wazuh MCP Server ◄──────────────── agents (read + verify tools only)
▲ │ alerts (poll or webhook)
│ ▼
│ Autopilot ── incidents ──► Strands swarm: triage → correlation → investigation → CTI → IR lead
│ │ │ propose_action
│ ▼ ▼
└── executor ◄── approved ◄── autonomy policy ── approvals queue (humans)
└── verify (wazuh_check_*) · audit · rollback
Details in docs/ARCHITECTURE.md.
Repository layout
backend/ FastAPI + Strands swarm, policy engine, executor (Python 3.12)
app/skills/ 37 SKILL.md skills
tests/ pytest suite
ui/ React + TypeScript console
mock-wazuh/ simulated Wazuh MCP server for demos and tests
litellm/ LiteLLM proxy config (compose profile)
docs/ documentation
Documentation
Development
cd backend && python3.12 -m venv .venv && . .venv/bin/activate
pip install -r requirements-dev.txt && pytest -q
cd ../ui && npm ci && npm run build
See CONTRIBUTING.md. The PyPI package is strands-agents: pip install strands installs an unrelated library, and strands-evals isn't the official evals package (strands-agents-evals is).
Acknowledgments
Thanks to @idrone3d for thorough field testing on self-hosted hardware and the findings in issue #33: idle inference cost from timer-driven agents, new alerts being grouped into closed cases, and proposals surviving expiry across restarts. The platform has no heartbeat polling: agents run on incidents, and the scheduled workflows (hunts, sweeps, briefings, platform-health checks; about a dozen runs a day by default) can be disabled or rescheduled in Workflows. It groups alerts only into open incidents and stores proposal expiry in the database.
Related projects
License
MIT, see LICENSE.