Agent Factory
The AuroraAgentFactory in aurorasoc/agents/factory.py is the central builder for all 13 specialist AI agents. It encapsulates the consistent creation pattern while allowing each agent type to have specialized tools, prompts, and memory configurations.
Factory Pattern
Internal _create_agent Method
Every factory method delegates to a shared private method:
def _create_agent(
self,
agent_type: AgentType,
tools: List[Tool],
memory_preset: str = "default"
) -> RequirementAgent:
# 1. Get specialized system prompt
system_prompt = AGENT_PROMPTS[agent_type]
# 2. Create ThinkTool (forced at step 1)
think_tool = ThinkTool()
# 3. Create tiered memory with preset
memory = TieredAgentMemory.from_preset(memory_preset)
# 4. Build agent with middleware
agent = RequirementAgent(
llm=self._get_llm(),
system_prompt=system_prompt,
tools=[think_tool] + tools,
memory=memory,
middleware=[GlobalTrajectoryMiddleware()]
)
return agent
Why ThinkTool at Step 1?
ThinkTool forces the agent to reason before acting. Without it, agents tend to jump directly to tool calls without planning. By making ThinkTool the first tool and forcing it at step 1, we ensure:
- The agent analyzes the input before taking action
- Reasoning is visible in the trajectory log for auditability
- Tool selection is deliberate, not reflexive
Agent-Tool Mapping
Each agent type receives specific tools matching its domain:
| Agent | Tools | Memory Preset |
|---|---|---|
| Security Analyst | SearchLogs, CorrelateEvents, ExtractIOC, MitreMap | analyst |
| Threat Hunter | HuntLOLBins, BaselineDeviation, UserRiskScore, SearchLogs | hunter |
| Malware Analyst | RunYARAScan, SandboxAnalysis | analyst |
| Incident Responder | ExecutePlaybook, RequestHumanApproval, CreateCase, UpdateCase | responder |
| Network Security | AnalyzeFlows, DetectDNSTunneling, BlockIP | default |
| Web Security | (General reasoning tools) | default |
| Cloud Security | (General reasoning tools) | default |
| CPS Security | QueryCPSSensor, VerifyAttestation, RevokeCertificate, CorrelatePhysicalCyber, QueryOTProtocol, IsolateNetworkSegment | cps |
| Threat Intel | LookupIOC, EnrichIOC, ShareIOC | intel |
| Endpoint Behavior | IsolateEndpoint, ScanEndpoint, HuntLOLBins, BaselineDeviation, UserRiskScore | hunter |
| Forensic Analyst | CollectEvidence, TimelineReconstruction | analyst |
| Report Generator | GenerateReport | default |
| Network Analyzer | AnalyzeFlows, ReviewPCAP (read-only) | default |
| Orchestrator | 13 HandoffTools | orchestrator |
Dynamic Agent Deployment
The factory's build_full_team() method reads the ENABLED_AGENTS environment variable at startup to determine which specialist agents to instantiate. This lets you run a lightweight subset without changing code.
# aurorasoc/agents/factory.py
def build_full_team(self) -> dict[str, RequirementAgent]:
enabled = settings.get_enabled_agents() # frozenset[str] of PascalCase names
agents = {}
for name, factory_method in AGENT_FACTORY_MAP.items():
if name in enabled or enabled == {"all"}:
agents[name] = factory_method(self)
return agents
get_enabled_agents() parses ENABLED_AGENTS from .env:
# aurorasoc/config/settings.py
class Settings(BaseSettings):
ENABLED_AGENTS: str = "all"
def get_enabled_agents(self) -> frozenset[str]:
val = self.ENABLED_AGENTS.strip()
if val.lower() == "all":
return frozenset({"all"})
return frozenset(name.strip() for name in val.split(",") if name.strip())
Examples:
# Start all 13 specialist agents (default)
ENABLED_AGENTS=all
# Minimal triage-only fleet
ENABLED_AGENTS=SecurityAnalyst,ThreatHunter,IncidentResponder
# Intel + reporting only
ENABLED_AGENTS=ThreatIntel,ReportGenerator,ForensicAnalyst
The API's agent registry endpoint (GET /api/v1/agents) reflects the live set of running agents, so dashboards and orchestrator routing always match the actual deployment. Read-only fleet visibility now lives in aurorasoc/api/routers/agent_registry.py and aurorasoc/api/routers/agent_fleet_read.py, fleet-control routes now live in aurorasoc/api/routers/agent_fleet_management.py, site inventory plus topology routes now live in aurorasoc/api/routers/sites.py, shared write-path request models now live in aurorasoc/api/schemas/fleet.py and aurorasoc/api/schemas/sites.py, scaling-policy serialization plus validation now live in aurorasoc/api/fleet_scaling.py, replica inspection plus restart control plus autoscaler-status helpers now live in aurorasoc/api/fleet_runtime.py, and manual dispatch plus assignment queue helpers now live in aurorasoc/api/fleet_dispatch.py. aurorasoc/api/main.py now keeps only the compatibility wrappers that preserve the current symbols while the backend is being modularized.
Creating a New Agent Type
AuroraSOC now treats the shared agent catalogs as the source of truth for the live fleet:
AGENT_SPECSinaurorasoc/agents/factory.pydefines the live specialist set.AGENT_MCP_BINDINGSinaurorasoc/agents/mcp_agent_loader.pydefines the authorized MCP domains for each live agent.- Internal catalogs use PascalCase names such as
SecurityAnalystandEndpointBehavior. - Boundary payloads use snake_case names such as
security_analystandendpoint_behavior. - Consolidated legacy roles normalize to the live fleet:
EndpointSecurityandUEBAAnalystmap toEndpointBehavior,ComplianceAnalystmaps toSecurityAnalyst, andVulnerabilityManagermaps toThreatIntel.
To add a new agent specialization:
1. Add to the Live Agent Catalogs
# aurorasoc/agents/factory.py
AGENT_SPECS["MyNewAgent"] = AgentSpec(
role="My New Agent",
instructions=MY_NEW_AGENT_PROMPT,
memory_template=ANALYST_MEMORY,
)
# aurorasoc/agents/mcp_agent_loader.py
AGENT_MCP_BINDINGS["MyNewAgent"] = ["siem", "document"]
2. Write System Prompt
# aurorasoc/agents/prompts.py
MY_NEW_AGENT_PROMPT = """
You are the My New Agent for AuroraSOC.
## Responsibilities
- Describe what this agent does
- List its specific expertise
## Methodology
1. Step-by-step approach this agent follows
2. Tools it should use and when
3. Output format expectations
"""
3. Add Factory Method
No per-agent factory method is needed. AuroraAgentFactory.create_agent() reads
from AGENT_SPECS, loads MCP tools from AGENT_MCP_BINDINGS, and builds the
agent dynamically.
4. Create Server Entry
# docker-compose.yml (or runtime env)
AGENT_NAME=MyNewAgent
AGENT_PORT=9017
AGENT_TAGS=my-domain,security
# runtime entry point
python -m aurorasoc.agents.generic_server
5. Update A2ASettings
# aurorasoc/config/settings.py
class A2ASettings(BaseSettings):
# ... existing ports ...
my_new_agent_port: int = 9016
6. Add to Orchestrator
The Orchestrator receives handoff coverage when the agent is added to the live
catalogs. AuroraSOC startup now validates AGENT_SPECS and
AGENT_MCP_BINDINGS together, so catalog drift fails fast instead of surfacing
later in dispatch or the dashboard.