Skip to content
BreachPilot

Exploit Agent — Loop (tools/exploit_agent/runner/_impl.py)

Main async loop (run_exploit_agent at tools/exploit_agent/runner/_impl.py:301, ~2.2K LOC file). Called from tools/exploit_session.py (CLI/API service) and the swarm bridge. Imported into the package by tools/exploit_agent/runner/loop.py (a plain from ._impl import ...); tools/exploit_agent/loop.py is a deprecated re-export shim.

Verified symbols

SymbolKindLocationNotes
run_exploit_agentasync def_impl.py:301Entry point; all args keyword-only
_PhaseTrackerclasstools/exploit_agent/phase_tracker.py:9PHASE_ORDER + MIN_ACTIONS + can_terminate
_InMemoryExperienceStoreclass_impl.py:196Fallback when DB unreachable
CheckpointContextdataclass_impl.py:99kind = access|no_path
CheckpointOutcomedataclass_impl.py:117action + objective_text
CheckpointHookProtocol_impl.py:138Mid-run operator gate
_resolve_attacker_osdef_impl.py:148autoplatform.system() mapping
_resolve_allowed_targetsdef_impl.py:252Unions exploit.allowed_targets
_load_attack_memory_settingsdef_impl.py:282memory.attack_memory_*
_debug_enabled / _debug_printdef_impl.py:182/186AI_NMAP_DEBUG env
_emit + _EVENT_TYPEdef/const_impl.py:68/59WebUI event stream

Init sequence (pre-round-loop, _impl.py after line 301)

  1. Bind policy._target_ip / _locked_ip / _allowed_targets (immutable target lock).
  2. Resolve attacker_os via _resolve_attacker_os.
  3. Build profile = _build_context_profile(model).
  4. Wire ExperienceStore / SemanticMemoryManager / ExploitMutator (adaptive exploits).
  5. SessionManager.resume_or_new (+ persist_messages propagation).
  6. AttackMemoryStore via _load_attack_memory_settings.
  7. AttackPlanner plan load/create.
  8. Preflight env probe render_env_context.
  9. build_opsec_briefing / build_domain_briefing / build_parallel_agents_briefing / build_capability_guidance.
  10. build_exploit_system_prompt(...) (+ research-assistant briefing).
  11. Seed messages (resume or fresh).
  12. Auto research consultation on startup CVEs.

Round loop (for _round in range(max_rounds) at _impl.py:889)

messages = _refresh_attack_memory_message(...)
messages = _refresh_reasoning_advisory_message(...)
if time budget: _stream_model(...) ; break
if not policy.can_proceed: _stream_model(...) ; break
if _should_compact_context(...): _build_compacted_messages(...)
response = await _call_model_with_retry(..., _round_tools())
tool_calls, invalid = _filter_and_validate_tool_calls(...)
if not tool_calls:
    can_term, reason = phase_tracker.can_terminate()
    if enforcement on and not can_term:
        goal_complete (compromise/cred-dump) may still break
        else inject finish-early warning and continue
    checkpoint_hook may fire (no_path) and continue/finish/cancel
    break
for tc in tool_calls:
    approved = await policy.approve_action(...)
    result = await session.call_tool(name, args)
    messages.append({"role":"tool", "content": sanitize_output(...)})
    _action_result = normalize_action_result(...)
    outcome_tracker.record_compromise/cred_dump(...)
    if outcome_judgment_flow_a: await judge_flow_a(...)
    await policy.record(...)
    record_exploit_success/failure(...)
    if reflection_every: await _llm_reflect_inline(...)
    if should_consult_peers: await _consult_peers_inline(...)
    _maybe_reselect_skills(...)
    phase_tracker.record_action(...)

Phase tracking

_PhaseTracker.PHASE_ORDER = recon → service_enumeration → vulnerability_research → validation → reporting (tools/exploit_agent/phase_tracker.py:16). MIN_ACTIONS enforces recon ≥2, service_enumeration ≥ max(1, detected services), vulnerability_research ≥ max(1, identified versions), reporting ≥1. can_terminate() → (bool, reason) at phase_tracker.py:42; remaining_requirements() lists what is missing.

Budgets

max_rounds = policy.settings.effective_max_rounds (tools/exploit_agent/policy.py); max_duration = attack_max_duration_minutes*60 if attack_mode else 0. num_ctx only threaded to Ollama when long_session_enabled.

Config keys

KeyUsage
exploit.attacker_os_resolve_attacker_os branch
exploit.allowed_targets_resolve_allowed_targets
memory.attack_memory_*_load_attack_memory_settings
memory.semantic_enabled / embedding_modelSemantic memory wiring
memory.experience_min_samples / time_decay_daysExperienceStore gating
long_session.enabled / persist_messagesCheckpoint + num_ctx
nmap.*Not in loop; passed via recon
swarm.parallel_enabledParallel briefing
agent.capability_discovery_enabledCapability-guidance prompt block

Tests

FileVerifiedWhat it covers
tests/test_agent_loop.pyyesHappy path, budgets, blocked replan, approval, checkpoint hook (access/no_path)
tests/test_long_session.pyyesnum_ctx, persist, max_rounds override
tests/test_reasoning_loop.pyyes_parse_reasoning_block + advisory refresh
tests/test_ultrathink.pyyes[REASONING] capture + sanitization
tests/test_context_compaction.pyyes_should_compact_context / _build_compacted_messages
source: repo docs (build sync)Edit this page on GitHub →