8月17日、Sidが「Build an AI Agent That Critiques and Rewrites Itself (Google ADK, Hands-On)」と題した記事を公開した。LLMに何かを書かせると、最初の出力がそのまま答えになる。人間のライターなら書いて読み返して直すところを、通常のAIエージェントは一発勝負だ。この記事ではその問題に対し、「書く」ノードと「批評する」ノードをループさせる自己修正エージェントを構築するアプローチを、Google ADKのグラフワークフローを用いてPython約80行で実現する方法を解説している。
ループを支えるのはADK Graph Workflow Runtime
エンジンとして使うのはGoogle Agent Development Kit(ADK)のGraph Workflow Runtimeだ。エージェントの処理フローをノードとエッジのグラフとして定義できる機能で、条件分岐やループを命令的にコーディングする必要がなくなる。
なお、記事では旧来のSequentialAgentやLoopAgentとの対比でこのグラフランタイムが推奨されているが、deprecationの明示的な言及については元記事の表現に幅があるため、グラフランタイムが現時点で推奨されるアプローチとして紹介されていると理解するのが正確だ。グラフ構造で「承認されなければライターに差し戻す」という後退エッジを自然に表現できるのが肝で、ループ制御のロジックをグラフの配線として宣言的に記述できる点が旧来の方式との違いである。
構成は3ノード+1ループ
START --> writer --> critic --(revise)--> writer (フィードバックつきでループ)
|
+----(approve)---> publish
- Writer: タスクを受け取りドラフトを生成。ループバック時は前のドラフトとフィードバックを受け取り、改稿する
- Critic: ドラフトを1〜10で採点し、1行のフィードバックを出力。合格か打ち切り条件を満たせば
approve、そうでなければreviseをルーティング - Publish: 承認されたドラフトを返す終端ノード
鍵1:批評家に構造化レスポンスを返させる
フリーテキストを正規表現でパースするとデモが壊れる。そこでPydanticのモデルを使い、Geminiにスコア(int)とフィードバック(str)を持つJSONを返させる。
from pydantic import BaseModel
from google.genai import Client, types
client = Client() # GOOGLE_API_KEYを読む
MODEL = "gemini-2.5-flash"
class Verdict(BaseModel):
score: int
feedback: str
SDKがパース済みのVerdictオブジェクトを返すため、ループ側は整数スコアで分岐できる。文字列処理が一切不要になる。
鍵2:MAX_ROUNDSガードは必須
Criticノードのコアはこの部分だ。なお、以下のコードは元記事のコードを基に構成しているが、要約・整形を含む場合がある。正確なコードは元記事および公開リポジトリで確認していただきたい:
QUALITY_BAR = 8 # 10点満点でこれ以上なら合格
MAX_ROUNDS = 3 # 最大リライト回数
@node
async def critic(ctx, node_input=None):
task, draft, attempt = node_input["task"], node_input["draft"], node_input["attempt"]
resp = client.models.generate_content(
model=MODEL,
contents=f"TASK: {task}\n\nDRAFT:\n{draft}",
config=types.GenerateContentConfig(
system_instruction=(
"You are a demanding editor. Score the draft 1-10 on how well it "
"does the TASK, and give one line of concrete feedback. Be strict."
),
response_mime_type="application/json",
response_schema=Verdict,
),
)
verdict = resp.parsed
if verdict.score >= QUALITY_BAR or attempt >= MAX_ROUNDS:
yield Event(author="critic", output={"task": task, "draft": draft}, route="approve")
else:
yield Event(
author="critic",
output={"task": task, "draft": draft, "feedback": verdict.feedback, "attempt": attempt + 1},
route="revise",
)
attempt >= MAX_ROUNDSの条件が「自己修正エージェントで最も重要な安全策」と記事では強調されている。これがないと、厳しい批評家と頑固なライターが無限ループする。
ループの配線はルーティングマップ1行
グラフの定義全体がこれだけだ:
from google.adk import Workflow
from google.adk.workflow import START
agent = Workflow(
name="self_correcting_agent",
edges=[
(START, writer),
(writer, critic),
(critic, {"revise": writer, "approve": publish}),
],
)
最後のエッジの読み方は「criticから、"revise"ならwriterへ戻る、"approve"ならpublishへ進む」。自己修正ループの本体がこの1行に収まっている。
実行例:ラウンドを重ねるごとに改善される
記事中の実行例では、10歳の子どもにデータベースのインデックスを4行で説明するタスクを与えている。以下は元記事の出力ログを意訳したものであり、実際の英語出力とは表現が異なる:
WRITER (round 1): ぎこちない最初の試み
CRITIC: score=5/10 feedback=3行目が抽象的すぎる。具体例を使うこと
WRITER (round 2): 図書館のメタファーを使って改善
CRITIC: score=7/10 feedback=良いが4行目が長い。削れ
WRITER (round 3): すっきりした4行
CRITIC: score=9/10 -> approve
元記事では英語の出力ログが掲載されており、ラウンドごとにドラフトが具体的・簡潔になっていく様子が示されている。正確な出力例は元記事で確認できる。
セットアップは1分
pip install google-adk google-genai
export GOOGLE_API_KEY=your_ai_studio_key
Google AI Studioの無料枠で動く。Google Cloudプロジェクトや課金設定は不要だ。
発展的な使い方
記事では以下の拡張案が挙げられている:
QUALITY_BARを9に上げて批評を厳しくする- 批評家にトーン・事実確認・文字数などのルーブリック(評価基準チェックリスト)を与える
- ライターにWebサーチやDBツールを持たせ、実際の情報で改稿させる
- 批評家を2ノードに増やし、両者が承認した場合のみ通過させる(グラフランタイムはファンアウト・ファンインをサポート)
これらの拡張はいずれも、グラフのエッジ定義を書き換えるだけで対応できる点が重要だ。「批評家を2人にする」「評価軸を増やす」といった変更が、ループ制御のロジック本体を触らずに実現できるのは、処理フローを宣言的なグラフとして分離していることの直接的な恩恵である。自己修正の仕組みをプロトタイプとして手早く作り、その後に品質基準だけを段階的に引き上げるという開発スタイルが自然に取れる。
完全なスクリプトはGitHubで公開されている。
詳細はBuild an AI Agent That Critiques and Rewrites Itself (Google ADK, Hands-On)を参照していただきたい。