教程:在 Azure SRE Agent 中配置代理掛鉤(API)

小提示

偏好入口介面嗎? 你現在可以直接在入口網站建立和管理鉤子,無需使用 REST API。 入口網站提供視覺化表單與程式碼編輯器。 不需要任何curl指令。

在這個教學中,你會建立一個自訂代理,並附上一個 Stop 鉤子,強制代理人在每個回應後加上完成標記。 您透過 REST API 配置掛鉤,然後在入口網站的測試區測試。

預計時間:15分鐘

備註

代理級與自訂代理級鉤子: 本教學是在 自訂代理 上建立鉤子(自訂代理級鉤子)。 這些鉤子只有在特定的自訂代理程式執行時才會觸發。

要建立適用於整個代理(所有執行緒、所有自訂代理)的 代理級鉤 子,請在入口網站中使用 Builder>Hooks

等級 如何建立 Scope
代理層級 入口網站:生產器 > 勾點 適用於所有執行緒和自訂代理
自訂代理層級 REST API (本教學課程) 或入口網站:Agent Canvas > 自訂 Agent > 管理勾點 僅適用於一個專屬代理程式

在本教學課程中,您將瞭解如何:

  • 用 REST API 建立一個帶有 Stop hook 的自訂代理
  • 在入口網站的測試操場中測試掛勾行為
  • 新增一個 PostToolUse 的掛鉤來審核工具使用
  • 用策略鉤子阻擋危險指令

先決條件

  • 一個 Azure SRE 代理在 運行 狀態
  • curl 來呼叫 REST API
  • Azure CLI 登入 (az login) 以取得存取權杖

了解 hook API 格式

這個教學使用 REST API v2 來建立自訂代理的掛鉤。 入口網站的 YAML 編輯器標籤顯示 v1 格式,並未顯示透過 API 設定的掛鉤,但掛鉤仍然有效。 你可以在 Builder>Hooks 頁面或 測試遊樂場中驗證。

小提示

什麼時候該用 API 還是用入口網站:

  • 入口網站 (生產器 > 勾點):最適合以視覺化方式設定 Agent 層級勾點。 不需要任何程序代碼。
  • API (本教學):最適合自訂代理層級的鉤子、CI/CD 管線或程式管理。

找出你代理人的 API URL

您的代理的 API 基礎網址遵循以下模式:

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

若要尋找此識別碼:

  1. 打開 sre.azure.com 並選擇你的代理人。
  2. 在左側邊欄,選擇 建構工具>代理畫布
  3. 打開瀏覽器的 開發者工具 (F12 或右鍵 > Inspect)。
  4. 網路 標籤,依「api」篩選,尋找指向 URL 結尾 .azuresre.ai的請求。
  5. 基礎網址是 /api/... 之前的所有內容。

或者,請檢查元素索引標籤中的 src 屬性。尋找 https://{agent-name}-- 開頭為 src<iframe>

取得存取令牌

執行以下指令以取得 SRE 代理 API 的存取權杖:

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

建立一個帶有終止鉤的自訂代理

此步驟建立一個自訂代理 my_hooked_agent ,並以 Stop hook 檢查回應是否以 === 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 已接受 ,回應主體中包含完整的代理設定。

以下範例展示了相同的 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

停止鉤的運作原理

停止掛鉤會評估代理的回應,然後才返回給使用者:

  • $ARGUMENTS 替換為 hook context JSON,其中包含代理人的最終回應。
  • LLM 評估提示詞並返回 {"ok": true}{"ok": false, "reason": "..."}
  • 若被拒絕,代理在以使用者訊息注入原因後仍會繼續運作。
  • 在三次拒絕(預設情況下)後,代理人就會停止。

測試傳送門裡的鉤子

請依照以下步驟測試 Stop Hook:

  1. 在平台上找到你的代理程式,然後選擇 Builder>Agent Canvas

  2. 選擇測試遊樂場單選按鈕。

  3. 選擇 子代理人/工具 下拉選單,找到 my_hooked_agent,然後選擇 「套用」。

    選擇勾住的 Agent 測試遊樂場。

  4. 輸入 What is 2+2? 聊天視窗並選擇 發送

請看接下來會發生什麼:

  • 代理人先回應 4
  • 停止鉤子會評估並拒絕回應(無完成標記)。
  • 出現一個思考過程步驟,Agent 繼續進行。
  • 最後的回應出現: 4 === 回應完成 ===

停止掛鉤結果顯示代理在初次拒絕後加入回應完成標記。

這個鉤子奏效了。 這迫使特工在停止前加上標記。

新增 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」)。

阻擋危險指令

新增第二個 PostToolUse 鉤子,阻擋 rm -rfsudo,以及 chmod 777

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" 僅用於 shell 工具(模式錨固為 ^(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

下表列出代理鉤子常見的問題與解決方案。

Problem 解決方案
Portal YAML 分頁中看不到的鉤子 預期中,YAML 分頁只顯示 v1。 透過 API 建立的自訂代理層級鉤子會在Builder>Hooks或遊樂場中啟用並可見。
Unsupported kind: ExtendedAgent 使用 v2 端點: PUT /api/v2/extendedAgent/agents/{name}
Handoffs cannot be null 請將 "handoffs": [] 添加到 JSON 有效載荷中。
鉤子沒有效果 拒絕時請標註欄位 reason 。 沒有它,拒絕就被視為認可。
Agent 無限迴圈 較低 maxRejections (預設:3,範圍:1-25)。

下一個步驟