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 ein VERDICT: approve oder VERDICT: changes mit Notizen zurückgibt.
  • synthetisieren aggregiert die Urteile und leitet sie an revise oder finalize weiter, 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_fn deklariert 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 (und mark_deferred für benutzerdefinierte Knoten) bringt Fan-in zum Kern-StateGraph-Builder — zuvor konnte nur der höherstufige GraphAgentBuilder einen 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 (die code / goal Befehle).
  • Parallele Spezialisten, mehrstufige Überprüfung, kontradiktorische Widerlegung, Schwärme → ein adk-graph Workflow (der ultracode Befehl).

Weiter: Beispiele →