次の方法で共有


チュートリアル: Azure SRE エージェントでエージェント フック (API) を構成する

ヒント

ポータル UI を使用しますか? REST API を使用せずに、ポータルでフックを直接作成および管理できるようになりました。 ポータルには、ビジュアル フォームとコード エディターが用意されています。 curlコマンドは必要ありません。

このチュートリアルでは、Stop フックを使用してカスタム エージェントを作成します。このフックにより、エージェントがすべての応答に完了マーカーを強制的に追加します。 REST API を使用してフックを構成し、ポータルのプレイグラウンドでテストします。

推定時間: 15 分

エージェント レベルとカスタム エージェント レベルのフック: このチュートリアルでは、 カスタム エージェント (カスタム エージェント レベルのフック) にフックを作成します。 これらのフックは、その特定のカスタム エージェントが実行されている場合にのみ発生します。

エージェント全体 (すべてのスレッド、すべてのカスタム エージェント) に適用されるエージェント レベルのフック を作成するには、ポータルで Builder>Hooks を使用します。

レベル 作成する方法 Scope
エージェント レベル ポータル: ビルダー > フック すべてのスレッドとカスタム エージェントに適用されます
カスタム エージェント レベル REST API (このチュートリアル) またはポータル: Agent Canvas > カスタム エージェント > フックの管理 1 つのカスタム エージェントにのみ適用されます

このチュートリアルでは、以下の内容を学習します。

  • REST API を使用して Stop フックを使用してカスタム エージェントを作成する
  • ポータルのテストプレイグラウンドでフック動作をテストします
  • 監査ツールの使用のための PostToolUse フックを追加する
  • ポリシー フックを使用して危険なコマンドをブロックする

前提条件

  • 実行中の状態の Azure SRE エージェント
  • curl を使用して REST API を呼び出す
  • Azure CLI がログイン (az login) してアクセス トークンを取得する

フック API 形式を理解する

このチュートリアルでは、 REST API v2 を使用して、カスタム エージェントにフックを作成します。 ポータルの YAML エディター タブには v1 形式が表示され、API を介して構成されたフックは表示されませんが、フックはまだアクティブです。 これらを確認するには、 Builder>Hooks ページまたは テスト プレイグラウンドを使用します。

ヒント

API とポータルを使用する場合:

  • ポータル (Builder > Hooks): ビジュアル形式のエージェント レベルのフックに最適です。 コードは必要ありません。
  • API (このチュートリアル): カスタム エージェント レベルのフック、CI/CD パイプライン、またはプログラムによる管理に最適です。

エージェントの API URL を見つける

エージェントの API ベース URL は、次のパターンに従います。

https://{agent-name}--{hash}.{hash}.{region}.azuresre.ai

検索するには:

  1. sre.azure.com を開き、エージェントを選択します。
  2. 左側のサイドバーで、 Builder>Agent Canvas を選択します。
  3. ブラウザーの 開発者ツール を開きます (F12キーを押すか、>を右クリックして検証します)。
  4. [ネットワーク] タブに移動し、"api" でフィルター処理し、.azuresre.aiで終わる URL への要求を探します。
  5. ベース URL は、 /api/...前のすべてです。

または、[src] タブで属性を確認します。<iframe>srcで始まるhttps://{agent-name}--を探します。

アクセス トークンを取得する

次のコマンドを実行して、SRE エージェント API のアクセス トークンを取得します。

TOKEN=$(az account get-access-token \
  --resource <RESOURCE_ID> \
  --query accessToken -o tsv)

Stop フックを使用してカスタム エージェントを作成する

この手順では、応答が my_hooked_agent で終了するかどうかを確認する Stop フックを使用して、=== RESPONSE COMPLETE === というカスタム エージェントを作成します。 マーカーがない場合、フックは応答を拒否し、マーカーを追加するようエージェントに指示します。

AGENT_URL="https://your-agent--xxxxxxxx.yyyyyyyy.region.azuresre.ai"

curl -X PUT "${AGENT_URL}/api/v2/extendedAgent/agents/my_hooked_agent" \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Content-Type: application/json" \
  -d @- << 'EOF'
{
  "name": "my_hooked_agent",
  "properties": {
    "instructions": "You are a helpful assistant. Be concise.",
    "handoffDescription": "",
    "handoffs": [],
    "enableVanillaMode": true,
    "hooks": {
      "Stop": [
        {
          "type": "prompt",
          "prompt": "Check the agent response below.\n\n$ARGUMENTS\n\nDoes it end with === RESPONSE COMPLETE ===?\nIf yes: {\"ok\": true}\nIf no: {\"ok\": false, \"reason\": \"Add === RESPONSE COMPLETE === at the end.\"}",
          "timeout": 30
        }
      ]
    }
  }
}
EOF

応答本文に完全なエージェント構成が含まれた状態で HTTP 202 Accepted を受け取ります。

次の例は、参照用の v2 YAML 形式の同じ構成を示しています。

api_version: azuresre.ai/v2
kind: ExtendedAgent
metadata:
  name: my_hooked_agent
spec:
  instructions: |
    You are a helpful assistant. Be concise.
  handoffDescription: ""
  enableVanillaMode: true
  hooks:
    Stop:
      - type: prompt
        prompt: |
          Check the agent response below.

          $ARGUMENTS

          Does it end with === RESPONSE COMPLETE ===?
          If yes: {"ok": true}
          If no: {"ok": false, "reason": "Add === RESPONSE COMPLETE === at the end."}
        timeout: 30

ストップフックのしくみ

Stop フックは、ユーザーに戻る前にエージェントの応答を評価します。

  • $ARGUMENTSをフック コンテキスト JSON に置き換えます。これには、エージェントの最終的な応答が含まれます。
  • LLM はプロンプトを評価し、 {"ok": true} または {"ok": false, "reason": "..."}を返します。
  • 拒否された場合、エージェントは、理由がユーザー メッセージとして挿入された後も引き続き動作します。
  • 3 回の拒否 (既定値) の後、エージェントは停止します。

ポータルでフックをテストする

停止フックをテストするには、次の手順に従います。

  1. ポータルでエージェントに移動し、 Builder>Agent Canvas を選択します。

  2. [ テスト プレイグラウンド ] ラジオ ボタンを選択します。

  3. [サブエージェント/ツール] ドロップダウンを選択し、my_hooked_agentを見つけて、[適用] を選択します。

    フックされたエージェントが選択された状態で、プレイグラウンドをテストします。

  4. チャットに「 What is 2+2? 」と入力し、[送信] を選択 します

何が起こるかを見る:

  • エージェントは最初に 4 で応答 します
  • Stop フックは応答を評価して拒否します (完了マーカーなし)。
  • エージェントが処理を継続する箇所に、思考プロセス手順が表示されます。
  • 最後の応答が表示されます: 4 === RESPONSE COMPLETE ===

エージェントが最初の拒否後に RESPONSE COMPLETE マーカーを追加したことを示すフックの結果を停止します。

フックが機能しました。 停止する前に、エージェントにマーカーの追加を強制しました。

監査用の PostToolUse フックを追加する

エージェントが使用するすべてのツールをログに記録する PostToolUse フックを追加します。 両方のフックを使用して新しい PUT 要求を送信して、同じエージェントを更新します。

curl -X PUT "${AGENT_URL}/api/v2/extendedAgent/agents/my_hooked_agent" \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Content-Type: application/json" \
  -d @- << 'EOF'
{
  "name": "my_hooked_agent",
  "properties": {
    "instructions": "You are a helpful assistant. Be concise.",
    "handoffDescription": "",
    "handoffs": [],
    "enableVanillaMode": true,
    "hooks": {
      "Stop": [
        {
          "type": "prompt",
          "prompt": "Check the agent response below.\n\n$ARGUMENTS\n\nDoes it end with === RESPONSE COMPLETE ===?\nIf yes: {\"ok\": true}\nIf no: {\"ok\": false, \"reason\": \"Add === RESPONSE COMPLETE === at the end.\"}",
          "timeout": 30
        }
      ],
      "PostToolUse": [
        {
          "type": "command",
          "matcher": "*",
          "timeout": 30,
          "failMode": "allow",
          "script": "#!/usr/bin/env python3\nimport sys, json\ncontext = json.load(sys.stdin)\ntool = context.get('tool_name', 'unknown')\nprint(json.dumps({'decision': 'allow', 'hookSpecificOutput': {'additionalContext': f'[AUDIT] {tool} executed.'}}))"
        }
      ]
    }
  }
}
EOF

matcher: "*" は、このフックがすべてのツール呼び出しに対して実行されます。 このスクリプトは、ツール名をログに記録し、会話に [AUDIT] メッセージを挿入します。

フックをテストするには、ツールをトリガーする質問 (" echo hello実行" など) をエージェントに依頼します。

危険なコマンドをブロックする

rm -rfsudo、およびchmod 777をブロックする 2 つ目の PostToolUse フックを追加します。

PostToolUse:
  # Audit hook (runs for all tools)
  - type: command
    matcher: "*"
    timeout: 30
    failMode: allow
    script: |
      #!/usr/bin/env python3
      import sys, json
      context = json.load(sys.stdin)
      tool = context.get('tool_name', 'unknown')
      print(json.dumps({"decision": "allow",
        "hookSpecificOutput": {"additionalContext": f"[AUDIT] {tool} executed."}}))

  # Policy hook (only for shell tools)
  - type: command
    matcher: "Bash|ExecuteShellCommand"
    timeout: 30
    failMode: block
    script: |
      #!/usr/bin/env python3
      import sys, json, re
      context = json.load(sys.stdin)
      command = context.get('tool_input', {}).get('command', '')
      for pattern in [r'\brm\s+-rf\b', r'\bsudo\b', r'\bchmod\s+777\b']:
          if re.search(pattern, command):
              print(json.dumps({"decision": "block", "reason": f"Blocked: {pattern}"}))
              sys.exit(0)
      print(json.dumps({"decision": "allow"}))

監査フックとの主な違い:

  • matcher: "Bash|ExecuteShellCommand" シェル ツールに対してのみ実行されます (パターンは ^(Bash|ExecuteShellCommand)$として固定されます)。
  • failMode: block は、スクリプト自体がクラッシュした場合にツールの結果をブロックします (厳密モード)。
  • 危険なパターンが見つかった理由で "block" を返します。

フック応答形式

プロンプト フックとコマンド フックでは、さまざまな応答形式が使用されます。

プロンプト フック

プロンプト フックは単純な JSON を返します。

{"ok": true}
{"ok": false, "reason": "Please fix X."}

コマンド フック

コマンド フックは、展開された JSON を返します。

{"decision": "allow"}
{"decision": "block", "reason": "Dangerous command."}
{"decision": "allow", "hookSpecificOutput": {"additionalContext": "Audit note."}}

コマンド フックでは、JSON の代わりに終了コードを使用することもできます。

終了コード 行動
0 出力なし 許可する
0 JSON を使用する JSON を解析する
2 ブロック (stderr が原因になります)
その他 failModeにフォールバックします

注意事項

理由のない却下は承認として扱われます。 拒否するときは、常に reason を含めます。

確かめる

フックを構成してテストした後、次の条件を確認します。

  • カスタム エージェント レベルのフックは、REST API v2 を使用して構成します。 これらは、そのカスタム エージェントにのみ適用されます。
  • エージェント レベルのフックは、Builder > Hooks で作成します。 エージェント全体に適用されます。
  • 停止フックにより、エージェントは停止する前に === RESPONSE COMPLETE === マーカーを追加します。
  • PostToolUse監査フックは、ツール呼び出し時にメッセージを[AUDIT]に記録します。
  • ポリシー フックは、 rm -rfsudoなどの危険なコマンドをブロックします。

Troubleshooting

次の表に、エージェント フックに関する一般的な問題と解決策を示します。

問題 ソリューション
ポータルの [YAML] タブにフックが表示されない 予期される - [YAML] タブには v1 のみが表示されます。 API を介して作成されたカスタム エージェント レベルのフックはアクティブであり、 Builder>Hooks またはプレイグラウンドに表示されます。
Unsupported kind: ExtendedAgent v2 エンドポイント ( PUT /api/v2/extendedAgent/agents/{name}) を使用します。
Handoffs cannot be null JSON ペイロードに "handoffs": [] を追加します。
フックは効果がありません 拒否時に reason フィールドを含めます。 これを行わないと、拒否は承認として扱われます。
エージェントが無限にループする 下位 maxRejections (既定値: 3、範囲: 1 ~ 25)。

次のステップ