コンテンツにスキップ

ADKツールの実行確認を取得する

ADKでサポートPython v1.14.0TypeScript v0.2.0Go v0.3.0実験的

一部のエージェントワークフローでは、意思決定、検証、セキュリティ、または一般的な監視のために確認が必要です。このような場合、ワークフローを続行する前に、人間または監視システムから応答を取得する必要があります。Agent Development Kit(ADK)のツール確認機能を使用すると、ADKツールは実行を一時停止し、ユーザーまたは他のシステムと対話して確認したり、続行する前に構造化データを収集したりできます。ADKツールでツール確認を使用するには、次の方法があります。

  • ブール値の確認: require_confirmationパラメータを使用してFunctionToolを設定できます。このオプションは、はいまたはいいえの確認応答のためにツールを一時停止します。
  • 高度な確認: 構造化データ応答が必要なシナリオでは、確認を説明するテキストプロンプトと期待される応答でFunctionToolを設定できます。

試験運用版

ツール確認機能は試験運用版であり、いくつかの既知の制限があります。 フィードバックをお待ちしております!

リクエストがユーザーにどのように伝達されるかを設定でき、システムはADKサーバーのREST APIを介して送信されたリモート応答を使用することもできます。ADK Webユーザーインターフェイスで確認機能を使用する場合、エージェントワークフローは図1に示すように、ユーザーに入力を要求するダイアログボックスを表示します。

ツール確認のためのデフォルトのユーザーインターフェイスのスクリーンショット

図1. 高度なツール応答実装を使用した確認応答要求ダイアログボックスの例。

次のセクションでは、確認シナリオでこの機能を使用する方法について説明します。完全なコードサンプルについては、human_tool_confirmationの例を参照してください。エージェントワークフローに人間の入力を組み込む追加の方法があります。詳細については、ヒューマンインザループエージェントパターンを参照してください。

ブール値の確認

ツールがユーザーから単純なはいまたはいいえのみを必要とする場合は、FunctionToolクラスをラッパーとして使用して確認ステップを追加できます。たとえば、reimburseというツールがある場合、次の例に示すように、FunctionToolクラスでラップし、require_confirmationパラメータをTrueに設定することで確認ステップを有効にできます。

# agent.pyから
root_agent = Agent(
   ...
   tools=[
        # ツール呼び出しにユーザーの確認を要求するには、require_confirmationをTrueに設定します。
        FunctionTool(reimburse, require_confirmation=True),
    ],
...

この実装方法は最小限のコードで済みますが、ユーザーまたは確認システムからの単純な承認に限定されます。このアプローチの完全な例については、human_tool_confirmationのコードサンプルを参照してください。

確認関数の要求

入力値をブール値の応答を返す関数に置き換えることで、require_confirmation応答の動作を変更できます。次の例は、確認が必要かどうかを判断するための関数を示しています。

async def confirmation_threshold(
    amount: int, tool_context: ToolContext
) -> bool:
  """金額が1000を超える場合はtrueを返します。"""
  return amount > 1000

この関数は、require_confirmationパラメータのパラメータ値として設定できます。

root_agent = Agent(
   ...
   tools=[
        # ユーザーの確認を要求するには、require_confirmationをTrueに設定します
        FunctionTool(reimburse, require_confirmation=confirmation_threshold),
    ],
...

この実装の完全な例については、human_tool_confirmationのコードサンプルを参照してください。

高度な確認

ツールの確認にユーザーへの詳細な説明やより複雑な応答が必要な場合は、tool_confirmation実装を使用します。このアプローチは、ToolContextオブジェクトを拡張して、ユーザーへのリクエストのテキスト説明を追加し、より複雑な応答データを可能にします。この方法でツールの確認を実装する場合、ツールの実行を一時停止し、特定の情報を要求してから、提供されたデータでツールを再開できます。

この確認フローには、システムが人間の応答に対する入力リクエストを組み立てて送信するリクエストステージと、システムが返されたデータを受信して処理する応答ステージがあります。

確認の定義

高度な確認でツールを作成する場合は、ToolContextオブジェクトを含む関数を作成します。次に、tool_confirmationオブジェクト、hintおよびpayloadパラメータを持つtool_context.request_confirmation()メソッドを使用して確認を定義します。これらのプロパティは次のように使用されます。

  • hint: ユーザーに必要なものを説明する説明的なメッセージ。
  • payload: 返されると予想されるデータの構造。このデータ型はAnyであり、辞書やpydanticモデルなど、JSON形式の文字列にシリアル化できる必要があります。

次のコードは、従業員の休暇申請を処理するツールの実装例を示しています。

def request_time_off(days: int, tool_context: ToolContext):
  """従業員の休暇を申請します。"""
  ...
  tool_confirmation = tool_context.tool_confirmation
  if not tool_confirmation:
    tool_context.request_confirmation(
        hint=(
            '期待されるToolConfirmationペイロードを持つFunctionResponseで応答することにより、'
            'ツール呼び出しrequest_time_off()を承認または拒否してください。'
        ),
        payload={
            'approved_days': 0,
        },
    )
    # ツールが確認応答を待っていることを示す中間ステータスを返します。
    return {'status': 'マネージャーの承認が必要です。'}

  approved_days = tool_confirmation.payload['approved_days']
  approved_days = min(approved_days, days)
  if approved_days == 0:
    return {'status': '休暇申請は拒否されました。', 'approved_days': 0}
  return {
      'status': 'ok',
      'approved_days': approved_days,
  }

このアプローチの完全な例については、human_tool_confirmationのコードサンプルを参照してください。確認が取得される間、エージェントワークフローツールの実行が一時停止されることに注意してください。確認が受信された後、tool_confirmation.payloadオブジェクトで確認応答にアクセスし、ワークフローの実行を続行できます。

REST APIによるリモート確認

エージェントワークフローの人間による確認のためのアクティブなユーザーインターフェイスがない場合は、コマンドラインインターフェイスを介して確認を処理するか、電子メールやチャットアプリケーションなどの別のチャネルを介してルーティングできます。ツール呼び出しを確認するには、ユーザーまたは呼び出し元のアプリケーションがツール確認データを含むFunctionResponseイベントを送信する必要があります。

リクエストは、ADK APIサーバーの/runまたは/run_sseエンドポイント、またはADKランナーに直接送信できます。次の例では、curlコマンドを使用して確認を/run_sseエンドポイントに送信します。

 curl -X POST http://localhost:8000/run_sse \
 -H "Content-Type: application/json" \
 -d 
'{ 
    "app_name": "human_tool_confirmation",
    "user_id": "user",
    "session_id": "7828f575-2402-489f-8079-74ea95b6a300",
    "new_message": {
        "parts": [
            {
                "function_response": {
                    "id": "adk-13b84a8c-c95c-4d66-b006-d72b30447e35",
                    "name": "adk_request_confirmation",
                    "response": {
                        "confirmed": true
                    }
                }
            }
        ],
        "role": "user"
    }
}'

確認のためのRESTベースの応答は、次の要件を満たす必要があります。

  • function_responseidは、RequestConfirmation FunctionCallイベントのfunction_call_idと一致する必要があります。
  • nameadk_request_confirmationである必要があります。
  • responseオブジェクトには、確認ステータスとツールで必要な追加のペイロードデータが含まれます。

注:再開機能による確認

ADKエージェントワークフローが 再開機能で構成されている場合は、確認 応答とともに呼び出しID(invocation_id)パラメーターも指定する必要があります。 指定する呼び出しIDは、確認リクエストを生成した呼び出しと同じでなければなりません。 そうしないと、システムは確認応答で新しい呼び出しを開始します。 エージェントが再開機能を使用する場合は、応答に含めることができるように、 確認リクエストとともに呼び出しIDをパラメーターとして含めることを検討してください。 再開機能の使用方法の詳細については、 停止したエージェントの再開を参照してください。

既知の制限

ツール確認機能には、次の制限があります。

次のステップ

エージェントワークフロー用のADKツールの構築の詳細については、関数ツールを参照してください。

TypeScript の確認例の補足

英語原文に含まれている TypeScript のツール確認例を以下にも掲載します。

Boolean 確認

/**
 * A reimbursement tool with dynamic confirmation logic.
 */
export const reimburseTool = new FunctionTool({
  name: 'reimburse',
  description: 'Reimburse an amount. Large amounts (>1000) require manager approval.',
  parameters: z.object({
    amount: z.coerce.number().describe('The amount to reimburse.'),
  }),
  execute: async ({amount}, toolContext) => {
    // 1. Check if we already have a confirmed response.
    if (toolContext?.toolConfirmation?.confirmed) {
      const isLarge = amount > 1000;
      return {
        status: 'SUCCESS',
        message: isLarge 
          ? `Large reimbursement of ${amount} approved by manager and processed.`
          : `Reimbursement of ${amount} has been successfully processed.`,
      };
    }

    // 2. Request a tool confirmation.
    const isLarge = amount > 1000;
    toolContext?.requestConfirmation({
      hint: isLarge 
        ? `The amount ${amount} exceeds the $1000 limit and requires manager approval.`
        : `Do you want to reimburse ${amount}?`,
      payload: {amount},
    });

    // 3. Return a status that tells the agent we are waiting.
    // Note: The model won't see this until the turn resumes after confirmation.
    return {
      status: isLarge ? 'AWAITING_MANAGER_APPROVAL' : 'AWAITING_CONFIRMATION',
      message: 'This request requires approval to proceed.',
    };
  },
});

export const rootAgent = new LlmAgent({
  name: 'Finance_Assistant',
  model: 'gemini-flash-latest',
  instruction: `You are a Finance Assistant. 
  - You MUST use the 'reimburse' tool for ALL reimbursement requests.
  - MANDATORY: Every tool call MUST be accompanied by a text response in the same message.
  - THRESHOLD LOGIC:
    - For amounts <= 1000: Say "I am initiating the reimbursement request for [amount]. Please confirm it to proceed."
    - For amounts > 1000: Say "I am initiating the reimbursement request for [amount]. Since this exceeds $1000, manager approval is required. Please confirm the request to submit it for review."
  - EXAMPLES:
    User: "Reimburse me $45"
    Model: "I am initiating the reimbursement request for 45. Please confirm it to proceed." [Tool Call: reimburse(amount=45)]

    User: "Reimburse me $2500"
    Model: "I am initiating the reimbursement request for 2500. Since this exceeds $1000, manager approval is required. Please confirm the request to submit it for review." [Tool Call: reimburse(amount=2500)]
  - If the user provides a currency symbol (like $), ignore it and pass only the number to the tool.
  - In the Web UI, the user will see a 'Confirm' button. In the terminal, the user should simulate a confirmation response.`,
  tools: [reimburseTool],
});

動的確認

/* 
  Note: In TypeScript, dynamic threshold logic is implemented 
  directly within the tool's 'execute' function as shown above.
*/

高度な確認

/**
 * A tool that requests time off for an employee.
 * It uses the Advanced Confirmation pattern to request manager approval.
 */
export const requestTimeOffTool = new FunctionTool({
  name: 'request_time_off',
  description: 'Request days off for the employee.',
  parameters: z.object({
    days: z.number().describe('The number of days requested.'),
  }),
  execute: async ({days}, toolContext) => {
    const confirmation = toolContext?.toolConfirmation;

    if (!confirmation) {
      // Step 1: Request confirmation with a payload
      toolContext?.requestConfirmation({
        hint:
          'Please approve or reject the tool call request_time_off() by ' +
          'responding with a FunctionResponse with an expected ' +
          'ToolConfirmation payload.',
        payload: {
          approved_days: 0,
        },
      });

      // Return a descriptive status to the agent
      return {
        status: 'PENDING_MANAGER_APPROVAL',
        message: `A request for ${days} days is pending manager approval.`,
      };
    }

    // Step 2: Process the confirmation response
    if (!confirmation.confirmed) {
      return {
        status: 'CANCELLED',
        message: 'The request was cancelled by the user.',
      };
    }

    let approvedDays = (confirmation.payload as any)['approved_days'] as number;
    approvedDays = Math.min(approvedDays, days);

    if (approvedDays === 0) {
      return {
        status: 'REJECTED',
        message: 'The time off request was rejected by the manager.',
        approved_days: 0,
      };
    }

    return {
      status: 'SUCCESS',
      message: `The request for ${days} days was approved (Total approved: ${approvedDays}).`,
      approved_days: approvedDays,
    };
  },
});

export const rootAgent = new LlmAgent({
  name: 'HR_Assistant',
  model: 'gemini-flash-latest',
  instruction: `You are an HR Assistant. 
  1. Use the 'request_time_off' tool to help employees with leave requests.
  2. MANDATORY: Every tool call MUST be accompanied by a text response in the same message.
  3. EXAMPLE:
     User: "I want 5 days off"
     Model: "I am initiating your leave request for 5 days. Management approval is required, so please confirm this request." [Tool Call: request_time_off(days=5)]
  4. In the terminal, if they want to 'confirm', tell them to simulate a confirmation response. 
  5. Once confirmed, the system will automatically provide the result of the approval.`,
  tools: [requestTimeOffTool],
});