Agents are the core intelligence layer of Strix. Each agent is an AI-powered security expert that can reason about applications, execute tests, and discover vulnerabilities autonomously.
The root agent is created when you start a scan. It:
Receives the initial scan configuration (targets, instructions)
Coordinates the overall testing strategy
Creates specialized sub-agents for complex tasks
Aggregates findings into the final report
# From strix/agents/StrixAgent/strix_agent.pyclass StrixAgent(BaseAgent): max_iterations = 300 def __init__(self, config: dict[str, Any]): # Root agents get the "root_agent" skill by default default_skills = [] state = config.get("state") if state is None or state.parent_id is None: default_skills = ["root_agent"] self.default_llm_config = LLMConfig(skills=default_skills) super().__init__(config)
Root agents automatically load the root_agent skill, which contains high-level testing strategies and coordination patterns.
Sub-agents are created by the root agent (or other sub-agents) for specialized tasks:
# Creating a sub-agent for authentication testingcreate_agent( task="Test JWT authentication mechanisms and token validation", name="JWT Authentication Specialist", skills="authentication_jwt,business_logic", inherit_messages=False # Fresh context for focused testing)
Sub-agents:
Have specialized skills for their domain
Operate independently with their own conversation context
Share the sandbox workspace and proxy history
Report findings back to their parent agent
Sub-agents are not continuations of their parent. They receive a specific task and work independently, even if they inherit conversation history for background context.
# From strix/agents/base_agent.pyasync def agent_loop(self, task: str) -> dict[str, Any]: # Initialize sandbox and add task to messages await self._initialize_sandbox_and_state(task) while True: # Check for messages from other agents or user self._check_agent_messages(self.state) # Handle waiting state (paused or awaiting input) if self.state.is_waiting_for_input(): await self._wait_for_input() continue # Check if task is complete if self.state.should_stop(): return self.state.final_result or {} # Increment iteration counter self.state.increment_iteration() # Send conversation to LLM and process response should_finish = await self._process_iteration(tracer) if should_finish: return self.state.final_result or {}
Messages are delivered as structured XML in the conversation:
<inter_agent_message> <delivery_notice> <important>You have received a message from another agent.</important> </delivery_notice> <sender> <agent_name>API Testing Agent</agent_name> <agent_id>agent_abc123</agent_id> </sender> <message_metadata> <type>information</type> <priority>high</priority> </message_metadata> <content> Discovered admin API at /api/v2/admin with weak authentication. Endpoint returns full user database when accessed with X-Admin: true header. </content></inter_agent_message>