I just finished a major refactor of HALO, my open source AI-powered security agent.
The biggest change wasn’t adding another feature. It was simplifying the architecture.
Instead of scattering tool definitions across multiple files, HALO now uses a single transport-agnostic execution engine. Both the HTTP tool server and the MCP server consume the same registry, eliminating duplicated logic and reducing maintenance.
Some of the improvements include:
- A centralized tool registry with 29 integrated security tools.
- Automatic binary resolution, even when environment variables or shell profiles haven’t been loaded.
- Consistent JSON responses across every tool.
- Automatic privilege escalation for commands that require elevated permissions.
- Stronger error handling with standardized recovery suggestions.
- Runtime validation that prevents the MCP registry and execution dispatcher from drifting out of sync.
- Better sandbox validation to detect silent failures and false-success conditions when running custom Python proof-of-concepts.
One of my favorite additions is the tool resolver. Rather than assuming every environment has a perfect $PATH, HALO now searches common binary locations before giving up. It sounds simple, but it makes the agent far more portable across different Linux environments and fresh installations.
This release also continues moving HALO toward being a true Model Context Protocol (MCP) implementation instead of just exposing HTTP endpoints.
The goal is straightforward: build an AI security agent that is modular, predictable, and reliable enough to orchestrate dozens of security tools without each component needing custom glue code.
If you’re building AI agents, MCP servers, or automation for cybersecurity, I’d love to hear how you’re handling tool discovery, execution, and error normalization. I’m always interested in seeing different architectural approaches.
Top comments (2)
I think the next step after a few more following tool upgrades, will be a full AI web GUI and complete ship to the public as an Agentic OS set up.
A single registry is a strong place to make the security contract executable, not just keep names and schemas synchronized. I’d require every entry to declare its effective OS identity, network/filesystem scope, side-effect class, timeout/output budget, and whether approval is required. Then both HTTP and MCP adapters can enforce the same policy before dispatch.
Two details deserve extra caution in a security agent: automatic privilege escalation and searching “common binary locations.” Escalation should be an explicit, short-lived capability with a human/policy gate—not a recovery behavior. Binary discovery should resolve only allowlisted canonical paths, reject writable-parent paths, and record the executable digest/version; otherwise portability can become PATH/binary-hijack risk. For each run, log the registry version, tool ID, normalized arguments, selected binary digest, effective uid/capabilities, policy decision, exit status, and bounded output hash. That makes false success and privilege drift testable across both transports.