Analyzing PentestAgent
Source: GH05TCREW/pentestagent @
6bf6c42
How It Works
PentestAgent is a Python-based autonomous penetration testing framework that uses AI agents to conduct security assessments. The system operates in three modes: TUI (interactive terminal UI), crew (multi-agent orchestration), and tools (direct command execution). At its core, a BaseAgent class drives a loop: LLM generates tool calls → tools execute → results feed back to LLM until task completion.
The architecture supports both single-agent and multi-agent modes. In single-agent mode, PentestAgentAgent handles the full pentesting lifecycle with plan-driven execution. In crew mode, CrewOrchestrator spawns worker agents via WorkerPool to parallelize tasks.
Architecture
┌─────────────────────────────────────────────────────────────────────┐
│ CLI / TUI Interface │
│ textual (rich terminal UI) + argparse for command modes │
└────────────────────────────────────┬────────────────────────────────┘
│
┌────────────────────────────────────▼────────────────────────────────┐
│ Agent Layer │
│ ┌────────────────────┐ ┌──────────────────────────────────────┐ │
│ │ BaseAgent │ │ CrewOrchestrator │ │
│ │ - State Machine │ │ - WorkerPool for parallel agents │ │
│ │ - Tool Execution │ │ - ShadowGraph for strategic insights│ │
│ │ - Plan Management │ │ - Crew tools for agent spawning │ │
│ │ - RAG Integration │ └──────────────────────────────────────┘ │
│ └────────────────────┘ │
│ ┌────────────────────┐ ┌──────────────────────────────────────┐ │
│ │ PentestAgent │ │ WorkerAgent │ │
│ │ (specialized) │ │ (spawned for parallel tasks) │ │
│ └────────────────────┘ └──────────────────────────────────────┘ │
└────────────────────────────────────┬────────────────────────────────┘
│
┌────────────────────────────────────▼────────────────────────────────┐
│ LLM Abstraction │
│ LiteLLM wrapper with: │
│ - Provider-agnostic interface (OpenAI, Anthropic, Ollama, etc.) │
│ - Token management via ConversationMemory │
│ - Rate limit handling with exponential backoff │
│ - Anthropic-specific message sanitization │
└────────────────────────────────────┬────────────────────────────────┘
│
┌────────────────────────────────────▼────────────────────────────────┐
│ Tool System │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Tool │ │ MCP Server │ │ RAG │ │
│ │ Registry │ │ Integration │ │ Optimizer │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ Tool Categories: terminal, recon, exploitation, reporting │
└────────────────────────────────────┬────────────────────────────────┘
│
┌────────────────────────────────────▼────────────────────────────────┐
│ Knowledge Layer │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Notes │ │ ShadowGraph │ │ RAG Engine │ │
│ │ System │ │ (NetworkX) │ │ (knowledge) │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────────────────┘
Key Packages
| Package | Role |
|---|---|
agents/base_agent.py | Core agent loop with plan execution, tool calling, state management |
agents/crew/orchestrator.py | Multi-agent orchestration with worker spawning |
llm/llm.py | LiteLLM wrapper with token management and retry logic |
tools/registry.py | Tool registration, schema validation, execution |
mcp/server/mcp_core.py | Model Context Protocol server for external tool integration |
knowledge/graph.py | ShadowGraph for strategic insights from notes |
interface/tui.py | Textual-based terminal UI |
The Spine
Entry Point Flow
- User launches via CLI:
pentestagent tui,pentestagent run, orpentestagent tools - Runtime initialized with workspace, workspace manager, and environment detection
- Agent created with LLM, tools, and optional RAG engine
- Loop executes:
- LLM generates tool calls based on system prompt + conversation history
- Tools execute with scope validation and target checking
- Results appended to conversation history
- Plan tracked and updated (auto-generate, replan on failure)
- Finish tool signals task completion with summary generation
State Machine
IDLE → THINKING → EXECUTING → (WAITING_INPUT) → COMPLETE
↓
ERROR → (replan) → THINKING
The AgentStateManager handles transitions with callbacks for UI updates.
Key Patterns
Plan-Driven Execution
Agents use a TaskPlan with PlanStep objects. Plans auto-generate on first iteration via function calling, then execute step-by-step. On failure, tactical replanning generates a new plan (v2, v3, etc.) or declares the task infeasible.
Tool Execution with Fallback
The _find_tool() method first searches registered tools, then falls back to the terminal tool for unknown commands. This allows LLMs to emit semantic tool names that get translated to shell commands automatically.
RAG Tool Optimizer
Tools can be marked as is_rag_optimizer in metadata. When executed, they return suggested_tools that expand the agent’s available toolset dynamically based on query context.
Multi-Agent via Crew Tools
The CrewOrchestrator exposes crew tools (spawn, delegate, finish) that the LLM uses to manage worker agents. Workers run in the same process but maintain separate conversation histories and state.
Shadow Graph Insights
The ShadowGraph derives a knowledge graph from agent notes, extracting hosts, credentials, services, and vulnerabilities. Strategic insights like “unused credentials” and “attack paths” are computed via NetworkX algorithms.
Non-Obvious Details
Terminal Tool Translation
When non-terminal tools are called, their arguments get automatically translated to shell commands. For example, a nmap tool call with {target: "192.168.1.1", ports: "22,80"} becomes nmap --target 192.168.1.1 --ports 22,80 executed via the terminal tool.
MCP Server Implementation
The MCP server in mcp/server/mcp_core.py is transport-agnostic. It implements the JSON-RPC router separately from transport (stdio vs HTTP), allowing the same core logic to work in different deployment scenarios.
Token Tracker Integration
The LLM wrapper integrates with a token_tracker module to record usage statistics. This happens via a best-effort sync helper to avoid event-loop coupling issues.
Conversation Memory with Summarization
The ConversationMemory class uses a configurable max token limit. When approaching the limit, older messages get summarized via an internal LLM call rather than simple truncation.
Notes as Primary Data Store
Agent notes serve as the source of truth for the knowledge graph. The ShadowGraph is a derived view that updates incrementally only for new notes.
Assessment
Strengths
- Clean separation of concerns: LLM abstraction, tool registry, agent logic, and UI are well-separated
- Flexible LLM support: LiteLLM integration provides access to 10+ providers with standardized interface
- Multi-agent orchestration: Crew pattern allows parallel task execution with worker pooling
- RAG integration: Knowledge retrieval augments agent prompts with relevant pentest documentation
- Textual TUI: Rich terminal interface with real-time agent feedback
Weaknesses
- No container sandboxing: Unlike PentAGI, tool execution runs directly on the host, risking accidental system damage
- Limited observability: No distributed tracing or structured logging for production deployments
- Python GIL constraints: Async concurrency helps but CPU-bound tasks still block
- Single-workspace focus: No support for concurrent multi-target assessments
Notable Patterns
- Plan-first execution: Forces explicit task decomposition before tool use
- Tactical replanning: Graceful recovery from failures without restarting from scratch
- Knowledge graph derivation: ShadowGraph pattern avoids dual-maintenance of notes and graph
Related
- analyzing-pentagi — Go-based pentesting agent with Docker sandboxing
- analyzing-hermes-agent — Python agent framework with terminal UI
- analyzing-defenseclaw — Security-focused agent with MCP integration