Today I moved Halo from a single autonomous loop to a proper five-agent architecture: Planner, Orchestrator, Vulnerability Discovery, Attacker, and Debugger. Here’s how it came together, and what I learned wiring it up against a real target.
The Core Design Principle
Before writing any code, the architecture came down to one rule: only two agents are allowed to touch tools. Vuln Discovery owns recon (nmap, httpx, gobuster, nikto). Attacker owns exploitation (sqlmap, hydra, searchsploit). Planner and Orchestrator are pure logic — no tool access, no exceptions. Debugger diagnoses failures and hands Orchestrator a ranked list of fixes, but it never touches a tool either.
That division matters more than it sounds. It means Orchestrator never needs to understand why something failed — it just executes Debugger’s top recommendation. And it means adding new tools later only touches one specialist’s code, not the whole system.
The Shared Message Envelope
Every agent speaks in the same format — a locked-down AgentMessage with agent, engagement_id, task_id, status, and result. Think of it like a hospital where every department files the same shape of chart, even though a surgeon’s notes and a radiologist’s notes contain completely different specifics.
Debugger’s result includes a ranked list of SuggestedFix objects — action, params, and a confidence level — so Orchestrator can just take the top-ranked suggestion without needing to reason about the failure itself.
Building Against Stubs First
Orchestrator got built and tested against fake stand-in agents before the real specialists existed. This let me prove the routing logic worked — correctly dispatching tasks by assigned_to field — before wiring in anything that actually touches a network. When the real Vuln Discovery agent was ready, swapping it in was a one-line change to a routing dictionary. Nothing else in Orchestrator had to change.
Real Bugs, Real Fixes
Testing against a live Metasploitable target surfaced a real parameter mismatch: my Attacker agent was passing the target IP as a search keyword to searchsploit, which expects a service name and version, not an IP. Searchsploit correctly returned “No Results” — not a crash, just bad input.
That failure became the first real test case for Debugger. Fed the exact failure message, Debugger correctly diagnosed “keyword likely doesn’t match a real exploit entry” and recommended switching tools with high confidence — reasoning about a bug I’d just fixed by hand an hour earlier.
What’s Next
The five agents exist and each works independently. The next phase is wiring them into one continuous engagement loop — Planner’s output feeding Orchestrator, Orchestrator dispatching to the real specialists, Vuln Discovery’s findings flowing into Attacker’s input, and Debugger catching failures along the way. That’s the integration work ahead.
Repo: github.com/XenoCoreGiger31/GEMMA-by-GOOGLE
Top comments (0)