LuaN1aoAgent decouples penetration testing thinking into three independent yet collaborative cognitive roles: the Planner, the Executor, and the Reflector. Together they form a complete cognitive loop — planning, execution, and reflection — that prevents the “split personality” problem common in single-agent systems.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/SanMuzZzZz/LuaN1aoAgent/llms.txt
Use this file to discover all available pages before exploring further.
Overview
Each role in the P-E-R framework focuses exclusively on its core responsibility. They share state through theGraphManager and communicate asynchronously via the EventBroker. This division of labor means no single LLM call must simultaneously reason about strategy, tool invocation, and audit.
Planner
Strategic Brain. Decomposes goals into DAG task graphs and emits structured graph editing instructions.
Executor
Tactical Engine. Executes individual subtasks via MCP tool calls, manages context, and discovers new evidence.
Reflector
Audit and Learn. Reviews execution logs, validates findings, generates attack intelligence, and controls termination.
The Planner
ThePlanner class in core/planner.py is the strategic brain of the agent. It never directly invokes tools; instead, it emits graph operation instructions that tell the GraphManager how to evolve the task graph.
Graph Operation Outputs
The Planner’s output is always agraph_operations list. Each item is one of:
| Command | Effect |
|---|---|
ADD_NODE | Creates a new subtask in the DAG with description, dependencies, priority, and completion criteria |
UPDATE_NODE | Modifies a subtask’s metadata or status |
DEPRECATE_NODE | Marks a subtask as abandoned (e.g., a dead-end attack path) |
DELETE_NODE | Removes a subtask entirely |
Adaptive Step Allocation
Each subtask node carries an optionalmax_steps field. The Planner uses this to allocate extra execution budget for complex tasks (e.g., blind SQL injection data extraction, multi-stage WAF bypass).
Parallel Scheduling
The Planner identifies parallelizable tasks by analyzing DAG topology — subtasks with no mutual dependency are scheduled to run concurrently. This is purely structural: the Planner does not need to enumerate independent paths explicitly; theGraphManager’s topological traversal handles it.
Dynamic Replanning
In addition to the initial plan, the Planner performs dynamic replanning after each Reflector cycle:failed_tasks_summary and injects it into the prompt with high priority:
Branch Regeneration
For catastrophically failed branches,regenerate_branch_plan creates an entirely new subgraph to replace the dead branch. It cleans up dependencies pointing into the dead branch and re-anchors new nodes to healthy predecessors:
The Executor
Therun_executor_cycle function in core/executor.py implements the core tool-invocation loop for a single subtask. It runs until the subtask completes, stalls, or exhausts its step budget.
Tool Invocation and Parallel Execution
Each LLM turn may return multipleEXECUTE_NOW operations. These are dispatched in parallel using asyncio.gather:
query_causal_graph) bypass MCP entirely for zero-latency lookups:
Context Compression
To prevent token overflow on long-running subtasks, the Executor applies a three-tier compression strategy:
When compression fires, older messages are summarized via
llm.summarize_conversation, and the system message plus recent messages are preserved:
Hypothesis Persistence
Outputs from theformulate_hypotheses tool are persisted across context compression by writing them directly into the subtask node:
Shared Bulletin Board (Parallel Discovery Sharing)
When multiple subtasks run in parallel, high-value findings are shared in real-time viaGraphManager.shared_findings:
ConfirmedVulnerability nodes (unconditionally) and KeyFact nodes with confidence ≥ 0.5 are broadcast to the bulletin board.
First-Step Guidance
On step 0, if the causal graph contains noConfirmedVulnerability nodes, the Executor injects a soft prompt to encourage the agent to call formulate_hypotheses before exploring:
Fault Tolerance and Termination
The Executor handles three termination conditions:| Condition | Status |
|---|---|
LLM signals is_subtask_complete: true | completed |
Step count reaches effective_max_steps | completed (soft limit) |
EXECUTOR_NO_ARTIFACTS_PATIENCE steps with no new staged_causal_nodes | terminates with no_new_artifacts |
_execute_with_retry.
The Reflector
TheReflector class in core/reflector.py acts as the audit and learning layer. It runs after each Executor cycle and performs both per-subtask reflection and a final global reflection if the mission succeeds.
Per-Subtask Reflection
Thereflect method reviews the execution log, validates staged causal nodes, and emits structured intelligence:
Failure Pattern Analysis (L1–L4)
The Reflector callsgraph_manager.analyze_failure_patterns() to detect three structural problem classes in the causal graph:
Contradiction Clusters
Contradiction Clusters
A hypothesis has multiple pieces of contradicting evidence (e.g., one scan says port 3306 open, another says filtered). Requires the Planner to design a discriminating probe task.
Stalled Hypotheses
Stalled Hypotheses
A hypothesis has been in
PENDING or SUPPORTED state for longer than a time window with no new supporting or contradicting evidence. Indicates the exploration has stalled.Competing Hypotheses
Competing Hypotheses
A single piece of evidence supports or contradicts multiple hypotheses simultaneously, creating explanation ambiguity. Requires abductive reasoning to identify the best explanation.
Veto Power
The Reflector can explicitly reject staged causal nodes that do not meet its validation criteria:Intelligence Generation
On success,reflect_global produces a structured STE (Strategy-Tactic-Example) insight:
strategic_principle— a one-sentence attack principletactical_playbook— an ordered list of abstract tactical stepsapplicability— tags for future reuse matching
Termination Control
The Reflector is the authoritative judge of whether a task is complete. It calls_evaluate_success_with_llm to make a binary verdict based on natural-language completion criteria:
P-E-R Collaboration Flow
The full cycle, from goal input to termination, follows this sequence:EventBroker
All three components communicate via the globalEventBroker singleton defined in core/events.py. It implements a pub-sub model with per-op_id queues:
| Event | Emitter | Meaning |
|---|---|---|
planning.initial.completed | Planner | Initial graph operations generated |
planning.dynamic.completed | Planner | Dynamic replanning operations generated |
execution.step.completed | Executor | A tool call finished |
execution.halt | Executor | External halt signal detected |
reflection.completed | Reflector | Subtask audit finished |
graph.changed | GraphManager | Any node or edge mutation |
Comparison: P-E-R vs. Single-Agent Systems
| Concern | Traditional Single Agent | P-E-R Architecture |
|---|---|---|
| Strategy and execution | Mixed in one LLM call | Separated into Planner and Executor |
| Reasoning continuity | Lost between tool calls | PlannerContext + ReflectorContext maintain sliding-window history |
| Failure learning | Retry blindly | Reflector analyzes failure patterns; Planner uses them for replanning |
| Hallucination risk | High — no ground truth | Causal graph enforces evidence-first reasoning |
| Parallel execution | None | DAG topology enables automatic parallel scheduling |
| Audit and veto | None | Reflector validates and can veto every proposed causal node |