小提示
偏好入口介面嗎? 你現在可以直接在入口網站建立和管理鉤子,無需使用 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
若要尋找此識別碼:
- 打開 sre.azure.com 並選擇你的代理人。
- 在左側邊欄,選擇 建構工具>代理畫布。
- 打開瀏覽器的 開發者工具 (F12 或右鍵 > Inspect)。
- 到 網路 標籤,依「api」篩選,尋找指向 URL 結尾
.azuresre.ai的請求。 - 基礎網址是
/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:
在平台上找到你的代理程式,然後選擇 Builder>Agent Canvas。
選擇測試遊樂場單選按鈕。
選擇 子代理人/工具 下拉選單,找到 my_hooked_agent,然後選擇 「套用」。
輸入
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 -rf、 sudo,以及 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 -rf和sudo這類危險指令。
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)。 |