The primary architectural standard for this framework is now graph engineering: one
explicit, declarative engagement graph defines the topology, state channels, reducers,
conditional routers, bounded loops, and memory boundaries for every runtime. The source of
truth is graph/redteam.graph.json, validated against
schemas/graph.schema.json by
tools/graph/validate-graph.mjs.
Why graph engineering¶
The graph makes orchestration inspectable instead of implicit prompt choreography:
Determinism — node order, routers, fan-out, and fan-in are declared in JSON and checked by the validator before execution.
Resumability — parallel specialist work is backed by the durable JSONL task manifest in
tools/orchestration/manifest.mjs, so interrupted fan-out can be resumed and reduced deterministically.Explicit state and reducers — each shared channel declares how writes merge, including append-only fan-in and finding-level dedupe.
Bounded self-improvement — reflection is a loop with explicit exit criteria (
max_revisions: 2,quality_threshold: 0.85), not an open-ended conversation.Reviewable safety boundaries — the graph declares where memory may be read or written, while read-only enforcement remains outside the self-improvement surface.
Canonical topology¶
The topology is:
START -> validate_scope— the subscription, scope, engagement mode, and read-only role posture are validated before any Azure access.memory_load— prior methodology memory is loaded as read-only context.preflight_inventory— the Inventory & Scope agent performs sequential permission checks and resource enumeration.plan_specialists -> run_specialist— a LangGraph-style Send fan-out maps over the in-scope read-only roster and dispatches one specialist worker per domain in parallel.collect_raw— raw specialist outputs fan back in through a deterministicmerge_findingsreduce.evaluate— the evaluator-optimizer loop head runs deterministic checks plus a critic score over candidate findings.route_after_evaluate— ifrevision < max_revisionsand quality is belowquality_threshold, the graph reflects back toplan_specialists; otherwise it proceeds.judge— an Agent-as-a-Judge gate re-checks candidate findings using targeted read-only evidence queries and suppresses false positives into methodology memory.authorize_active/route_active— a human-in-the-loop interrupt gates the optional active lanes. Read-only or rejected runs route straight to correlation.correlate -> report— confirmed findings are correlated into RBAC and attack paths, then rendered into deliverables.reflexion_debrief -> END— the run records an inert episode. Stable lessons are promoted only after matching evidence from at least two distinct runs for the same agent.
State channels and reducers¶
The graph state follows a LangGraph-style channel model. Concurrent writes are safe because each channel declares its reducer in the graph contract.
| Channel | Type | Reducer | Role |
|---|---|---|---|
scope | object | last | Validated subscription, mode, domain, exclusion, and read-only role context. |
memory | object | last | Methodology memory loaded from prior runs. |
inventory_ref | string | last | Path to the preflight resource inventory. |
raw_findings | array | append | Per-specialist JSONL outputs accumulated by Send fan-in. |
candidate_findings | array | merge_findings | Deterministically deduped findings before critique and judge. |
critique | object | last | Evaluator quality score and notes that drive reflection. |
revision | number | last | Bounded reflection iteration counter. |
confirmed_findings | array | merge_findings | Findings promoted by the false-positive judge. |
attack_paths | array | append | Cross-domain authorization and attack-path chains. |
report_refs | array | append | Rendered deliverable paths. |
approved | boolean/null | last | Human decision at the gated active-lane interrupt. |
Self-improving loops¶
The graph deliberately borrows from prior art in self-improving agents while excluding unsafe runtime self-modification:
Self-Refine — each specialist performs a bounded refinement pass on its own draft findings before writing raw output.
Evaluator-optimizer —
evaluatecombines deterministicrun-checksoutput with a critic score and stages a bounded, inert parameter candidate;route_after_evaluateroutes back to targeted specialist planning only while the loop is undermax_revisionsand belowquality_threshold.Agent-as-a-Judge —
judgere-verifies candidate findings with 1-3 targeted read-only Azure queries, promotes confirmed / needs-review findings, and writes false-positive suppressions to methodology memory.Reflexion / ExpeL-style debrief —
reflexion_debriefrecords run-attributed experiences. Stateless consolidation promotes only stable signatures reproduced in at least two distinct runs, and never pools evidence between agents.
AEF-compatible learning contract¶
The loop adapts the safe reflection-and-memory architecture from the read-only aef-core
snapshot at commit 48ee1ef7cd9f2cc91762f4b4c08150d954d443ec. The source checkout is not a
runtime dependency and was not modified. AEF’s disabled runtime code-evolution path is deliberately
excluded. The imported contract contributes four controls: inert candidates, independent run
attribution, per-agent consolidation, and auditable promotion or rollback.
Memory firewall: the immutable boundary¶
The one immutable boundary is the read-only enforcement system. Learning may write only
memory/methodology/; it may not modify the guard core, egress allowlist, cluster allowlist,
read-only role requirements, or anything under guardrails/**. The graph schema describes this
as a memory-write target, and tools/graph/validate-graph.mjs enforces structural and
referential integrity, including the memory firewall.
Unsafe runtime self-modification is intentionally excluded: no runtime code execution, no tool creation, and no self-rewriting of the guard. Methodology memory can change how agents investigate and critique; it cannot change what they are allowed to do.
One graph, two engines¶
The same graph/redteam.graph.json drives two execution models:
Dependency-free Node runner —
tools/graph/run-graph.mjsexecutes the graph inside the GitHub Copilot CLI, Claude Code, OpenAI Codex CLI, and Cursor runtimes. The core stays zero-dependency and uses the durable JSONL checkpointer intools/orchestration/manifest.mjs.First-class LangGraph target —
integrations/langgraph/compiles the same JSON graph into a PythonStateGraph, using LangGraph concepts such asSend, reducers, checkpointers, interrupts, and Store-style memory while reusing the same read-only guard through a subprocess bridge. Its dependencies are isolated from the Node core.
Prior art and ecosystem¶
This architecture is inspired by:
LangGraph for
StateGraph,Send, reducers, checkpointers, interrupts, and Store-style memory.Reflexion, Self-Refine, Agent-as-a-Judge patterns, ExpeL, and evaluator-optimizer loops for iterative improvement.
The broader awesome-LangGraph ecosystem of graph-based agent systems.
The framework adapts those ideas to a red-team setting by keeping the learning surface narrow and the enforcement surface deterministic, fail-closed, and shared by every runtime.