그래프 워크플로우 (초고 검토)
단일 Agent 루프를 넘어선 모든 것 — 병렬 검토자, 적대적 검사, 다단계 파이프라인 — 에 대해서는 코딩 Agent를 adk-graph StateGraph로 오케스트레이션합니다. 이것이 ultracode 명령어와 coding_graph 예제가 작동하는 방식입니다.
"ultra" 패턴
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)
- implement / revise는 완전한
CodingAgent입니다 (읽기/쓰기/bash). - 각 reviewer는 코드를 검사하고
VERDICT: approve또는VERDICT: changes와 함께 노트를 반환하는 읽기 전용LlmAgent입니다. - synthesize는 판결을 집계하고
revise또는finalize로 라우팅하며, 라운드 상한 + 그래프 재귀 한도에 의해 제한됩니다.
adk-graph에서의 팬아웃 / 팬인
두 가지 adk-graph 기능이 이를 올바르게 만듭니다:
- 병렬 팬아웃 — 하나의 업스트림 노드에서 도달 가능한 여러 노드가 동일한 슈퍼 스텝에서 동시에 실행됩니다.
- 팬인 배리어 —
add_deferred_node_fn로 선언된 노드는 모든 업스트림 경로가 완료된 후에만 (업스트림당 한 번이 아니라) 정확히 한 번 실행됩니다.
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(그리고 사용자 정의 노드의 경우mark_deferred)는 팬인을 핵심StateGraph빌더로 가져옵니다 — 이전에는 상위 레벨GraphAgentBuilder만이 지연된 노드를 선언할 수 있었습니다. 이것이 없으면 여러 업스트림 엣지를 가진 애그리게이터는 첫 번째 브랜치가 완료되는 즉시 실행되었을 것입니다.
각 노드는 Agent를 실행하고 그 결과를 그래프 상태에 쓰는 async 클로저입니다. 조건부 엣지는 루프를 돌거나 완료하기 위해 decision를 읽습니다. 전체 실행 가능한 구현은 coding_graph 예제와 일반적인 API에 대한 Graph Agents 참조에서 확인할 수 있습니다.
그래프와 하네스 중 언제 사용할 것인가
- 단일 Agent, 선형/반복 작업 →
CodingAgent(code/goal명령어)만 사용합니다. - 병렬 전문가, 다단계 검토, 적대적 반박, 스웜 →
adk-graph워크플로우 (ultracode명령어)를 사용합니다.
다음: 예제 →