Graph-Workflows (ultra-review)
Für alles, was über eine einzelne Agent-Schleife hinausgeht – parallele Prüfer, gegnerische Überprüfungen, mehrstufige Pipelines – orchestrieren Sie Coding Agents als ein adk-graph StateGraph. So funktionieren der ultracode Befehl und das coding_graph Beispiel.
Das "ultra"-Muster
START → implement ──┬─▶ review:correctness ─┐
├─▶ review:edge-cases ─┤ (parallel, real agents)
└─▶ review:style ─┤
▼
synthesize ← deferred fan-in (runs once)
│
decision ──────────┤
┌── "revise" ◀──────────┘
▼ └──▶ "finalize" → END
revise ─▶ (back to the reviewers)
- implementieren / überarbeiten sind vollständige
CodingAgents (read/write/bash). - jeder Prüfer ist ein schreibgeschützter
LlmAgent, der den Code inspiziert und einVERDICT: approveoderVERDICT: changesmit Notizen zurückgibt. - synthetisieren aggregiert die Urteile und leitet sie an
reviseoderfinalizeweiter, begrenzt durch eine Rundenobergrenze + das Graph-Rekursionslimit.
Fan-out / Fan-in in adk-graph
Zwei adk-graph Fähigkeiten machen dies korrekt:
- Paralleles Fan-out — mehrere Knoten, die von einem Upstream-Knoten aus erreichbar sind, laufen gleichzeitig im selben Super-Schritt.
- Fan-in-Barriere — ein Knoten, der mit
add_deferred_node_fndeklariert ist, läuft genau einmal, erst nachdem alle seine Upstream-Pfade abgeschlossen sind (nicht einmal pro Upstream).
use adk_graph::graph::StateGraph;
use adk_graph::{DeferredNodeConfig, MergeStrategy};
use adk_graph::edge::{START, END};
let graph = StateGraph::with_channels(&["task", "round", "decision", "notes",
"rev_correctness", "rev_edge-cases", "rev_style"])
.add_node_fn("implement", /* coding agent */)
.add_node_fn("review_correctness", /* read-only reviewer */)
.add_node_fn("review_edge-cases", /* … */)
.add_node_fn("review_style", /* … */)
// fan-in: runs once, after all three reviewers finish
.add_deferred_node_fn("synthesize", /* aggregate verdicts */,
DeferredNodeConfig { merge_strategy: MergeStrategy::Collect, fan_in_timeout: None })
.add_node_fn("revise", /* coding agent applies notes */)
.add_node_fn("finalize", /* done */)
.add_edge(START, "implement")
.add_edge("implement", "review_correctness")
.add_edge("implement", "review_edge-cases")
.add_edge("implement", "review_style")
.add_edge("revise", "review_correctness") // loop fans out again
.add_edge("revise", "review_edge-cases")
.add_edge("revise", "review_style")
.add_edge("review_correctness", "synthesize") // fan-in
.add_edge("review_edge-cases", "synthesize")
.add_edge("review_style", "synthesize")
.add_conditional_edges("synthesize",
|s| s.get("decision").and_then(|v| v.as_str()).unwrap_or("finalize").to_string(),
[("revise", "revise"), ("finalize", "finalize")])
.add_edge("finalize", END)
.compile()?
.with_recursion_limit(16);
add_deferred_node_fn(undmark_deferredfür benutzerdefinierte Knoten) bringt Fan-in zum Kern-StateGraph-Builder — zuvor konnte nur der höherstufigeGraphAgentBuildereinen verzögerten Knoten deklarieren. Ohne dies würde ein Aggregator mit mehreren Upstream-Kanten feuern, sobald der erste Zweig abgeschlossen ist.
Jeder Knoten ist eine async-Closure, die einen Agenten ausführt und ihr Ergebnis in den
Graph-Zustand schreibt; die bedingte Kante liest decision, um zu loopen oder zu beenden. Die vollständige,
ausführbare Implementierung finden Sie im coding_graph Beispiel
und in der Graph Agents-Referenz für das allgemeine API.
Wann man einen Graph vs. das Harness verwendet
- Einzelner Agent, lineare/iterative Arbeit → einfach ein
CodingAgent(diecode/goalBefehle). - Parallele Spezialisten, mehrstufige Überprüfung, kontradiktorische Widerlegung, Schwärme →
ein
adk-graphWorkflow (derultracodeBefehl).
Weiter: Beispiele →