Skip to main content

Create and Manage Hooks via Portal

What you'll build

Two governance hooks using the portal UI: a Stop hook that enforces data formatting (markdown tables with bold headers), and a PostToolUse hook that blocks dangerous shell commands. You'll learn hooks at both the agent level (applies to everything) and the custom agent level (applies to one specific custom agent). Time: ~10 minutes.

Prerequisites

  • An Azure SRE Agent in Running state
  • Contributor role or higher on the SRE Agent resource
Already using the REST API?

Hooks you previously created via the REST API tutorial appear automatically in the portal UI. You can manage them visually without reconfiguring anything.


Where hooks live in the portal

Hooks operate at two levels. This is a key architectural concept:

LevelLocation in portalScopeUse when
Agent levelBuilder → HooksApplies to the entire agent — all threads and all custom agentsYou want agent-wide policies like "audit every tool call" or "block dangerous commands everywhere"
Custom agent levelAgent Canvas → Custom agent → Manage HooksApplies only when that specific custom agent runsYou want hooks tailored to one custom agent, like "validate this custom agent's output format"
Both levels can coexist

If an agent-level hook and a custom-agent-level hook both match the same event, both run. Agent-level hooks fire first, then custom-agent-level hooks.


Part 1: Agent-level hooks (Builder → Hooks)

Agent-level hooks apply to the entire agent — every thread, every custom agent. They have activation modes that control when they're active.

Step 1: Open the Hooks page

  1. Navigate to sre.azure.com and select your agent
  2. In the sidebar, expand Builder
  3. Click Hooks

Checkpoint: You see the "Hooks" heading with a description, a Create hook button, and an empty data grid (or a list of existing hooks).

Step 2: Create a Stop hook

A Stop hook fires when the agent is about to return a final response. Use it to validate response quality and enforce formatting rules.

  1. Click Create hook
  2. Fill in the form fields:
FieldValue
Namerequire-table-format
Event typeStop
Activation modeAlways
DescriptionEnsures responses present structured data as markdown tables with bold headers
  1. Under Hook Definition, keep Hook type set to Prompt
  2. Keep Model set to Reasoning Fast (default)
  3. In the Prompt editor on the right, enter:
Check the agent response below.

$ARGUMENTS

Does the response present any structured data (lists of items, comparisons, metrics) as a markdown table with **bold** column headers?
If no structured data is present, approve.
If structured data IS present as a table with bold headers: {"ok": true}
If structured data is present but NOT formatted as a table: {"ok": false, "reason": "Reformat the structured data as a markdown table with **bold** column headers."}
  1. Leave Timeout (sec) at 30, Fail mode at Allow, and Max rejections at 3
  2. Click Save

Checkpoint: The dialog closes with a success notification. The hook appears in the data grid with Event type "Stop" and Activation "Always."

How the Stop hook works

The $ARGUMENTS placeholder injects the hook context (including the agent's final response) into the prompt. The LLM evaluates whether the response meets your criteria and returns {"ok": true} to approve or {"ok": false, "reason": "..."} to reject. After 3 rejections (the default), the agent is forced to stop.

Step 3: Test the Stop hook

  1. Navigate to Chat in the sidebar
  2. Type "Compare the pros and cons of Python vs Go for building microservices" and press Send
  3. Watch the agent's response:
    • The agent initially responds with a plain text comparison
    • The Stop hook evaluates and rejects because the data isn't in a table
    • The agent reformats its response as a markdown table with bold headers

Checkpoint: The final response presents the comparison as a formatted table like:

LanguageProsCons
PythonRapid development, rich ecosystemSlower execution, GIL limitations
GoFast compilation, built-in concurrencySmaller ecosystem, verbose error handling

Step 4: Create a PostToolUse hook

A PostToolUse hook fires after a tool completes execution. Use it to audit tool usage, block dangerous commands, or inject additional context.

  1. Go back to Builder → Hooks
  2. Click Create hook
  3. Fill in the form:
FieldValue
Nameblock-dangerous-commands
Event typePost Tool Use
Activation modeAlways
DescriptionBlocks rm -rf, sudo, and chmod 777 in shell commands
Hook typeCommand
Tool matcherBash|ExecuteShellCommand
  1. Select Python as the script language
  2. In the Script editor, enter:
#!/usr/bin/env python3
import sys, json, re

context = json.load(sys.stdin)
command = context.get('tool_input', {}).get('command', '')

dangerous = [r'\brm\s+-rf\b', r'\bsudo\b', r'\bchmod\s+777\b']
for pattern in dangerous:
if re.search(pattern, command):
print(json.dumps({"decision": "block", "reason": f"Blocked: {pattern}"}))
sys.exit(0)

print(json.dumps({"decision": "allow"}))
  1. Set Fail mode to Block (if the script crashes, the tool result is blocked)
  2. Click Save

Checkpoint: Both hooks appear in the Hooks data grid.

Tool matcher syntax

The Tool matcher field uses regex. Bash|ExecuteShellCommand matches tools named exactly "Bash" or "ExecuteShellCommand" (the pattern is anchored as ^(Bash|ExecuteShellCommand)$). Use * to match all tools.

Step 5: Test the PostToolUse hook

  1. Go to Chat
  2. Ask the agent to run a safe command: "Run echo hello" — the hook allows this
  3. Ask the agent to run a dangerous command: "Run rm -rf /tmp/test" — the hook blocks this

Checkpoint: The safe command executes normally. The dangerous command is blocked, and the agent receives a message explaining why.

Step 6: Edit and delete agent-level hooks

Edit: Click the edit icon on any hook row in the data grid, modify the fields, and click Save.

Delete: Select the checkbox next to hooks you want to remove, click Delete in the toolbar, and confirm.

Checkpoint: Changes are reflected immediately in the data grid.


Part 2: Custom-agent-level hooks (Agent Canvas)

Custom-agent-level hooks are configured directly in a custom agent's definition. They apply only when that specific custom agent runs — not to the main agent or other custom agents.

Step 7: Open the custom agent hooks panel

  1. In the sidebar, expand Builder and click Agent Canvas
  2. Click on an existing custom agent to edit it — or click Create custom agent to start a new one
  3. In the custom agent form, scroll down to the Hooks section
  4. Click Manage Hooks

Checkpoint: A side panel opens with Stop and Post Tool Use sections. If no hooks are configured, you see empty states with guidance text.

Step 8: Add a hook to a custom agent

Let's add a Stop hook that ensures this custom agent always responds in a structured format:

  1. In the Manage Hooks panel, click the Add hook button at the bottom of the panel
  2. In the dialog that opens, fill in the hook form:
FieldValue
Event typeStop
Hook typePrompt
PromptCheck the response below. $ARGUMENTS Does it include a clear summary section at the end? If yes: {"ok": true} If no: {"ok": false, "reason": "Add a Summary section at the end of your response."}
Timeout (sec)30
Fail modeAllow
Max rejections3
  1. Click Save on the hook
  2. Click Create (or Save) on the custom agent to save the full configuration

Checkpoint: The hook appears in the Manage Hooks panel under the Stop section. The custom agent form shows "Manage Hooks (1)" on the button.

Testing custom-agent-level hooks

To test this hook, go to Agent Canvas → select the Test playground view → choose your custom agent from the dropdown → type a question. The hook only runs when this specific custom agent is invoked.


Part 3: Manage hooks per thread

Agent-level hooks with Always activation are active in every conversation by default. Hooks with On Demand activation must be manually activated per thread.

Step 9: Toggle hooks in a conversation

  1. Open a Chat thread
  2. Click the + button in the chat footer
  3. Select Manage Hooks
  4. Toggle hooks on or off for the current thread

Always hooks can be temporarily deactivated. On Demand hooks can be activated when needed. Required system hooks are locked and cannot be toggled.

Checkpoint: Hook changes take effect immediately in the current thread.


What you learned

  • Hooks operate at two levels: Builder → Hooks (agent level) and Agent Canvas → custom agent → Manage Hooks (custom agent level)
  • How to create Stop hooks that validate responses before delivery
  • How to create PostToolUse hooks that audit and control tool usage
  • The difference between Prompt hooks (LLM evaluation) and Command hooks (scripts)
  • How activation modes (Always vs On Demand) control global hook behavior per thread
  • How to edit, delete, and manage hooks across both surfaces

Troubleshooting

IssueSolution
Hooks page not visible in sidebarThe Hooks page appears under Builder. Verify your agent is in Running state. If the option still doesn't appear, contact support.
"Hook name is required"Enter a name using only letters, numbers, hyphens, and underscores.
"Name must contain only letters, numbers, hyphens, and underscores"Remove special characters from the hook name.
"Hook name cannot start with system__"The system__ prefix is reserved for system hooks. Choose a different name.
"Tool matcher is required for PostToolUse hooks"PostToolUse hooks need a regex matcher. Use * to match all tools.
Hook doesn't fireFor agent-level hooks, check the activation mode — On Demand hooks must be activated per thread. For custom-agent-level hooks, verify the custom agent is being invoked.
Stop hook approves everythingEnsure the prompt returns {"ok": false, "reason": "..."} when rejecting. A rejection without a reason is treated as approval.
Script errors blocking actionsSet Fail mode to Allow for graceful degradation during development. Switch to Block in production.
ResourceWhat you'll learn
Agent Hooks →Full hook reference, context schema, response formats, and limits
Configure Hooks via API →Create hooks using the REST API v2 and YAML
Run Modes →How hooks complement run mode safety controls
Was this page helpful?