Repository navigation
Agents
PentestAI has 6 agents, each for a different phase of penetration testing. All agents are skill-mode aware.
Each agent behaves differently based on PENTESTAI_MODE:
| Behaviour | Junior | Mid | Advanced |
|---|---|---|---|
| Verbose output | ✅ reasoning at every step | ✅ | ❌ findings only |
| Phase gates | ✅ approval before transition | ❌ | ❌ |
| RAG enrichment | ✅ CVE context | ✅ | ❌ |
| AutoPlanner | ✅ auto-generate plan | ❌ asks first | ❌ asks first |
| Scanner payloads | ✅ show them | ✅ | ❌ raw |
| Max ReAct iterations | 15 | 12 | 20 |
File: agents/recon.py — ReconAgent, WebAgent, AutoPlanner
Orchestrates nmap, HTTP probing, gobuster, nikto, sqlmap, and AI analysis.
target → scope check → nmap → HTTP probe → AI analysis → findings
↘ nikto → gobuster → sqlmap (if a form exists)
recon # recon against the primary target
recon 10.10.11.100 # recon against a specific target
recon deep # broader port scan
auto "find web vulns" # AI-planned with an objectivefrom agents.recon import ReconAgent
agent = ReconAgent(session, scope, llm_router, ToolRegistry())
agent.run("10.10.11.162")AutoPlanner — in junior/mid mode, generates an attack plan automatically. In advanced mode, asks for confirmation first.
File: agents/react.py — core autonomous agent with a ReAct loop.
-
REACT_SYSTEM(4400+ chars) — CVE mappings, attack phase guidance, decision rules. Contains: CVE-2007-2447 (Samba), CVE-2017-0144 (EternalBlue), CVE-2011-2523 (vsftpd), Log4j, MS08-067, etc. -
GENERATION_SYSTEM— exact command syntax generation -
PARSING_SYSTEM— LLM-based finding extraction from tool output -
SUMMARIZATION_SYSTEM— context window compression
recon → enumeration → foothold → exploitation → post_exploit → done
Transitions are automatic based on findings and LLM output. Dead-end detection after N iterations without progress.
| Level | Behaviour |
|---|---|
guided |
Ask for confirmation on every action |
semi_auto |
Ask only for High/Critical actions |
autonomous |
Run everything without confirmation (advanced mode default) |
react # run against the primary target
react 10.10.11.100 # specific target
react 10.10.11.100 "get root" # with an objective
autonomy guided|semi|auto # change levelfrom agents.react import ReActAgent, AutonomyLevel
agent = ReActAgent(
session, scope, llm_router, registry,
autonomy=AutonomyLevel.SEMI_AUTO,
skill_mode=SkillMode.ADVANCED, # optional, default from settings
)
nodes = agent.run("10.10.11.162", objective="find credentials")agent._verbose # False in advanced: silent except for findings
agent._rag_enabled # False in advanced: skips RAG
agent._phase_gates # False in advanced: does not ask before transitions
agent._scanner_explain # False in advanced: raw scanner outputFile: agents/killchain.py — executes a 6-phase kill chain.
| Phase | Pre-condition (junior/mid) | Advanced |
|---|---|---|
| RECON | — | — |
| ENUMERATION | Services exist from RECON | Skip gate |
| WEB_TESTING | An HTTP service exists | Skip gate |
| EXPLOITATION | Findings exist from enumeration | Skip gate |
| POST_EXPLOIT | A shell/RCE exists | Skip gate |
| REPORTING | — | — |
chain # full kill chain against the primary target
chain 10.10.11.100 # specific targetPhase gates — Junior mode displays a summary and asks for approval before each phase transition. Advanced mode skips all gates. Non-interactive environments (CI/test) proceed automatically.
File: agents/bizlogic.py
Tests vulnerabilities that require an understanding of business context: IDOR, price manipulation, privilege escalation via API.
bizlogic http://target.comFile: agents/poc.py
Captures HTTP request/response as evidence, generates reproduction steps, creates curl commands.
poc # generate PoC for all findingsFile: agents/backend.py
The control plane talks to a backend, not directly to a specific agent loop.
Every backend receives an AgentRunRequest and returns an AgentRunResult
(nodes, session, tokens, duration, stop reason, error, loop/recon signals).
from agents.backend import AgentRunRequest, NativeReActBackend
backend = NativeReActBackend(session, scope, llm, registry)
result = backend.run(AgentRunRequest(
target="https://app.example.test",
objective="prove an access-control flaw",
max_iterations=20,
))Current backends:
| Backend | Status |
|---|---|
native-react |
shipped |
strix |
shipped (CLI + run artifacts; host runner; findings imported as candidates) |
router |
shipped (native 40% budget, then Strix on the remaining time) |
| CLI agent adapter | planned |
| Shannon adapter | conditional (AGPL / white-box) |
The evaluator (scripts/bench_agent.py) records backend, model_id, and
harness_version in every result, so model and engine comparisons are
reproducible. bench_matrix --runner host is required for Strix because its
sandbox needs its own Docker access; the default docker runner is for the
native backend inside the PentestAI container.
File: agents/benchmark.py
Runs the agent against a built-in benchmark profile (HTB-style) for CLI demos; the profiles are simulations, not live targets. Real benchmarking uses scripts/bench_agent.py against the XBOW sample — see BENCHMARK.md.
benchmark lame # HTB Lame simulation
benchmark jerry # HTB Jerry simulationVisible only in junior/mid mode. Hidden in advanced mode.
All agents go through a PermissionGate that checks the EngagementBrief before every action:
action request → scope check → brief check → autonomy gate → execute
If the brief contains no_brute_force=True, the actions hydra/kerberoast/cred_spray are blocked before execution — regardless of autonomy level.
brief set # setup wizard at the start of the engagement
brief no-brute-force # add a constraint
brief production <ip> # mark an IP as prodFile: agents/orchestrator.py
Runs four sub-agents in parallel with a shared session context.
| Sub-agent | Tools used | Skip condition |
|---|---|---|
ReconSubAgent |
nmap, http, subdomain, cert_scan | — (always runs) |
WebSubAgent |
gobuster, waf_detect, SSTI/XXE/SSRF/path_traversal, nikto | No HTTP service |
InfraSubAgent |
cert_scan, ad_enum, kerberoast, privesc | No port 445/389/88/3389 |
ReportSubAgent |
ReportGenerator (HTML + Word) | — (always runs last) |
Phase 1: ReconSubAgent → sequential (all agents need its results)
Phase 2: WebSubAgent → parallel
InfraSubAgent → parallel (runs concurrently with Web)
Phase 3: ReportSubAgent → sequential (needs all findings)
In junior/mid mode: there is a phase gate approval before Phase 2 and Phase 3. In advanced mode: fully autonomous, no interruptions.
orch = AgentOrchestrator(session, scope, llm, registry,
skill_mode=SkillMode.ADVANCED)
orch._verbose # False — silent except for findings
orch._phase_gates # False — no approval gatesorchestrate # target from the active session
orchestrate 10.10.10.3 # specific target
orchestrate 10.10.10.3 --seq # sequential (not parallel)from agents.orchestrator import AgentOrchestrator
orch = AgentOrchestrator(session, scope, llm, registry)
result = orch.run("10.10.10.3", parallel=True)
print(result.summary()) # total findings, services, duration
print(result.succeeded) # sub-agents that succeeded