Orchestrates the full Flow B research workflow on top of the shared SQLite schema. Owns the while cycles < max_cycles loop that plans tasks, scope/risk-gates them, executes via swarm or ExecutorAgent, observes, judges hypothesis outcomes, updates memory/graph/evidence, validates findings, and generates reports. Supports fresh and resumed (mission_id) runs.
Initialize and wire all Flow B managers from a mission config + workspace root + tool executor (agent_loop.py:70__init__): DatabaseManager, MissionController, ScopeGate, RiskController, EvidenceStore, ToolRouter, MemoryManager (+ SemanticMemoryManager), ExperienceStore, TargetGraph, TaskQueue, HypothesisRepository, OutcomeJudge, PlannerAgent, ExecutorAgent, ObserverAgent, FindingVerifier, ReportGenerator, SwarmOrchestrator.
Implement resume: when mission_id is passed, ensure_schema + load_mission + reset_stale_running (agent_loop.py:223) + SwarmOrchestrator.load_state for the blackboard (agent_loop.py:293).
Deep recon → attack chaining via AutonomousOrchestrator
Private helpers used across the loop: _save_observation, _update_memory_from_observation, _update_graph_from_observation, _cross_mission_recall, _record_outcome_and_lesson, _distill_episode_summary (agent_loop.py:1343, agent_loop.py:1447).
flowchart TD
A[__init__ -> create/load mission\n+ wire 15+ managers\n+ reset stale running on resume] --> B[run max_cycles loop]
B --> C{can_proceed? budget}
C -->|no| Z[generate summary + distill lesson -> return stats]
C -->|yes| D[get_next_task]
D -->|None| E[plan: memory+graph+hypotheses -> PlannerAgent.plan -> create_task + dedup]
E -->|0 created & minima met| Z
E -->|tasks created| B
D -->|task| F[check_scope -> risk assess -> human approval?]
F -->|blocked/approval| G[block or needs_approval -> continue]
F -->|pass| H{use_swarm?}
H -->|yes| I[SwarmOrchestrator.route -> merge new_tasks/memory/graph/findings]
H -->|no| J[ExecutorAgent.execute via ToolRouter]
I --> K[Observer.observe]
J --> K
K --> L[save_observation + memory/graph updates]
L --> M[OutcomeJudge.judge + HypothesisRepository.persist_assessment\n+ record experience]
M --> N{exec success?}
N -->|yes| O[queue.complete + _record_task_phase]
N -->|no| P[queue.failed + mark_dead_end + maybe plan_retry_with_modifications]
O --> Q[create findings from observation.possible_findings]
P --> Q
Q --> R[validate open candidates -> mark_report_ready]
R --> S[reprioritize + periodic progress + reflection every N]
S --> B
Every executed task runs through ScopeGate then RiskController (via ToolRouter or explicit checks); there is no direct tool_executor call in the loop.
Hypothesis status never overwrites ExecutionResult.success; task status stays operational (complete/failed/blocked), hypothesis state lives separately in hypotheses + outcome_assessments.
Confirmed / refuted / exhausted are terminal: get_next_task filters them out and PlannerAgent skips them.
On resume, stale running → pending and prior swarm_state.json blackboard are restored before the first cycle.
Scope + risk gates are defense-in-depth even inside the swarm path: SwarmOrchestrator still routes through ToolRouter with ScopeGate/RiskController checks.
Human approval is mandatory for high risk unless risk_profile == "high_authorized_testing".
Forbidden actions (scope_gate._HARD_FORBIDDEN_ACTIONS) and destructive patterns (risk_controller._DESTRUCTIVE_PATTERNS) block regardless of other state.