0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【ADK2.0】実践③ Google ADKでAIエージェントに承認処理を挟む(Human-in-the-Loop)

0
Last updated at Posted at 2026-08-28

はじめに

本記事は、ADK2.0の新機能を、実際に手を動かして検証した結果をまとめています。

前回までで、「AIブログ執筆エージェント」の「下書き→3人のレビュアーが並列チェック→NGなら差し戻し→OKなら仕上げ」という一連のワークフローができあがりました。

今回は、この仕上がった記事を公開する前に人間(編集者)の承認を挟むステップを追加してみます。

※薄いグレーが前回まで(1〜2本目)、濃いグレーが今回追加する部分

過去の記事はこちら↓

記事 内容
【ADK2.0】実践① Google ADKで構築するグラフ構造のAIエージェント 下書き生成→文字数チェック(グラフワークフローの基本)
【ADK2.0】実践② Google ADKで複数レビュアーを並列実行(Fan-out / Fan-in) 並列レビュー+差し戻しループ

1. なぜHuman-in-the-Loopが必要か

全て自動化したくなる一方で、

  • 記事の公開
  • 送金処理
  • データベースへの破壊的な操作

といった、後戻りしにくい・影響範囲が大きい処理は、AIだけに任せきりにするのは不安が残ります。

こうした人間の判断を挟むステップ(Human-in-the-Loop, HITL)自体は、ADK 1.xでも実現は可能でした。ただし、いずれの方法も"確実性"という点で曖昧さが残っていました。

1.xでのHITL

ADK 1.xでHITLを組む場合、大きく2つのやり方があるかと思います。

  • プロンプトで「承認を得てから進めて」と指示
    • 一番手軽ですが、あくまでLLMの解釈・判断に委ねる形
    • 聞き方次第で承認を飛ばして進めてしまうことがある
  • LongRunningFunctionToolの使用
    • 承認待ちの処理をツールとして実装する、より作り込んだ方法
    • ただしこちらも「承認ツールを呼ぶかどうか」自体はLLMの判断次第
    • 再開時のID管理や状態の保存・復元を自分で実装する必要あり

どちらの方法も、「承認を必ず通過する」という保証をコード側で持てず、最終的にはLLMの振る舞いに依存してしまう、という曖昧さが共通しています。

参考:

ADK 2.0でのHITL

ADK 2.0のRequestInputは、LLMの判断や解釈に頼らない、グラフのノードレベルでの一時停止・再開の仕組みです。
承認ノードを経由するかどうかはグラフ構造によって決定的に決まるため、プロンプトの書き方やLLMの気まぐれで承認がスキップされる、という曖昧さがなくなります。

2. RequestInputの基本

ADK 2.0では、RequestInputというクラスを使ってワークフローを一時停止し、人間の入力を待つことができます。公式ドキュメントには、以下のようなシンプルな例が載っていました。

from google.adk.events import RequestInput
 
def step1(node_input):
    """人間の入力を求め、一時停止する"""
    yield RequestInput(message="Enter a number:")
 
def step2(node_input):
    """人間の回答(node_input)を受け取って処理する"""
    return node_input * 2
 
root_agent = Workflow(
    name="root_agent",
    edges=[("START", step1, step2)],
)

状態管理も書かず、関数からRequestInputをyieldするだけで成立します。step1が一時停止した後、人間が回答するとstep1が裏側で再実行され、その回答が自動的にstep2へのnode_inputとして渡される、という一連の流れをフレームワーク側が面倒を見てくれます。

参考:Human input for agent workflows(公式ドキュメント)

3. 承認ノードを追加する

finalize_agentの後に、編集長の承認を求めるget_editor_approvalノードを追加します。承認(Yes)なら公開処理へ、却下(No)ならrevise_agentに差し戻します。

from google.adk import Agent
from google.adk import Workflow
from google.adk import Event
from google.adk.events import RequestInput

# draft_agent, grammar_reviewer, fact_reviewer, seo_reviewer,
# join_node, judge, revise_agent は前回までと同じものを使用

# (前回記事から更新)最終仕上げエージェント
finalize_agent = Agent(
    name="finalize_agent",
    model="gemini-3.6-flash",
    instruction="""以下の下書きに、タイトルと簡単な導入文を追加して、
    ブログ記事として仕上げてください。

    下書き:
    {draft}""",
    output_schema=str,
    output_key="final_article",  # 完成した記事をstate["final_article"]に保存する
)

# 編集長に承認を求めるノード
def get_editor_approval(node_input: str):
    """仕上がった記事を提示し、編集長の承認を待つ"""
    yield RequestInput(
        message=f"以下の記事を公開してよいですか?(Yes/No)\n\n{node_input}"
    )

def check_approval(node_input: str):
    """承認結果を見て、公開するか差し戻すかを判定する"""
    if node_input.strip().lower() == "yes":
        return Event(route=["APPROVED"])
    return Event(route=["REJECTED"])
    
def publish_node(ctx, node_input: Any):
    return f"記事を公開しました。\n\n{ctx.state['final_article']}"

root_agent = Workflow(
    name="blog_writer_workflow",
    edges=[
        # ===================================================
        # 前回記事までに作成したワークフローを埋め込む(そのまま)
        # ===================================================
        
        # --- 今回追加した部分 ---
        (finalize_agent, get_editor_approval, check_approval),
        (check_approval, {
            "APPROVED": publish_node,   # 承認されたら公開
            "REJECTED": revise_agent,   # 却下されたら2本目の修正ループに合流
        }),
    ],
)

get_editor_approvalRequestInputをyieldした時点でワークフローは一時停止し、人間が「Yes」または「No」を返すのを待ちます。
回答が返ってくると、その内容がcheck_approvalへのnode_inputとして渡され、そこから処理が再開される、という流れです。

4. 一時停止・再開の挙動を確認する

実際にワークフローを実行すると、get_editor_approvalのところで処理が止まり、承認待ちの状態になりました。adk web上では、入力フォームが表示されるようになります。

image.png

ここで「No」を返すとrevise_agentに差し戻され、2本目で作ったレビューのループにもう一度入っていく様子も確認できました。

image.png

「Yes」を返すと、そのまま最終記事を出力してくれます。

image.png

5. 触ってみた所感

特別な仕組みをほとんど必要とせず、承認フローを実装することができました。
1.x時代と比べると、LLMの解釈に左右されず承認ステップが必ず通る、という確実性も相まって、2.0ではかなり実践的なワークフローを構築できると感じました。


まとめ

ADK 2.0のHuman-in-the-Loop(HITL)について、「ブログ執筆エージェント」の公開フローを題材に検証してみました。

  • ADK 1.xでは「プロンプトで指示する」「LongRunningFunctionToolを使う」のどちらも、最終的にLLMの判断に依存する曖昧さが残っていた
  • ADK 2.0ではRequestInputをyieldするだけでワークフローを一時停止でき、グラフ構造として承認ステップを確実に通せる
  • 承認結果に応じて、公開ノードと差し戻し(既存のループ)に振り分けられる

次回は、ユーザーとチャットするコーディネーターが、裏でこのワークフロー全体をタスクとして動かす、Chat/Task/SingleTurnモードを試してみます。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?