Tutoriel : Configurer des hooks d’agent (API) dans Azure SRE Agent

Conseil / Astuce

Préférez l’interface utilisateur du portail ? Vous pouvez maintenant créer et gérer des hooks directement dans le portail sans utiliser l’API REST. Le portail fournit un formulaire visuel et un éditeur de code. Il n’est requis aucune curl commande.

Dans ce tutoriel, vous créez un agent personnalisé avec un crochet Stop qui force l’agent à ajouter un marqueur d’achèvement à chaque réponse. Vous configurez le hook via l’API REST, puis testez-le dans le terrain de jeu du portail.

Durée estimée : 15 minutes

Note

Hooks au niveau de l’agent et hooks au niveau d’un agent personnalisé : ce tutoriel crée des hooks sur un agent personnalisé (hooks au niveau d’un agent personnalisé). Ces points d'accroche ne se déclenchent que lorsque cet agent personnalisé spécifique fonctionne.

Pour créer des hooks au niveau de l’agent qui s’appliquent à l’ensemble de l’agent (tous les threads, tous les agents personnalisés), utilisez leshooks> dans le portail.

Niveau Guide pratique pour créer Étendue
Niveau de l’agent Portail : Builder > Hooks S’applique à tous les threads et agents personnalisés
Niveau d’agent personnalisé API REST (ce tutoriel) ou portail : Canevas de l'agent > Agent personnalisé > Gérer les hooks S’applique uniquement à un seul agent personnalisé

Dans ce tutoriel, vous allez apprendre à :

  • Créer un agent personnalisé avec un crochet Stop à l’aide de l’API REST
  • Tester le comportement du hook dans l'espace de test du portail
  • Ajouter un hook PostToolUse pour l’audit de l’utilisation des outils
  • Bloquer les commandes dangereuses avec un hook de stratégie

Prerequisites

  • Agent Azure SRE en cours d’exécution
  • curl pour appeler l’API REST
  • Azure CLI connecté (az login) pour obtenir un jeton d’accès

Comprendre le format de l’API de raccordement

Ce tutoriel utilise l’API REST v2 pour créer des hooks sur un agent personnalisé. L'onglet éditeur YAML du portail affiche le format v1. Il n'affiche pas les hooks configurés via l'API, mais ceux-ci sont toujours actifs. Vous pouvez les vérifier dans la page Builder>Hooks ou le terrain de jeu de test.

Conseil / Astuce

Quand utiliser l’API et le portail :

  • Portail (Builder > Hooks) : idéal pour les hooks au niveau de l’agent sous forme visuelle. Aucun code n’est nécessaire.
  • API (ce tutoriel) : Idéal pour les hooks de niveau agent personnalisé, les pipelines CI/CD ou la gestion programmatique.

Rechercher l’URL de l’API de votre agent

L’URL de base de l’API de votre agent suit ce modèle :

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

Pour le trouver :

  1. Ouvrez sre.azure.com et sélectionnez votre agent.
  2. Dans la barre latérale gauche, sélectionnez Constructeur>Canevas de l’agent.
  3. Ouvrez les outils de développement de votre navigateur (F12 ou cliquez avec le bouton droit sur > Inspecter).
  4. Accédez à l’onglet Réseau , filtrez par « api » et recherchez les requêtes vers une URL se terminant par .azuresre.ai.
  5. L’URL de base est tout avant /api/....

Vous pouvez également vérifier l’attribut src sous l’onglet Éléments . Recherchez un <iframe> élément dont src commence https://{agent-name}--par .

Obtenir un jeton d’accès

Exécutez la commande suivante pour obtenir un jeton d’accès pour l’API de l’agent SRE :

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

Créer un agent personnalisé avec un hook Stop

Cette étape crée un agent personnalisé appelé my_hooked_agent avec un crochet d’arrêt qui vérifie si la réponse se termine par === RESPONSE COMPLETE ===. Si le marqueur est manquant, le crochet rejette la réponse et indique à l’agent d’ajouter le marqueur.

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

Vous recevez HTTP 202 Accepté avec la configuration complète de l’agent dans le corps de la réponse.

L’exemple suivant montre la même configuration au format YAML v2 pour référence :

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

Fonctionnement du crochet Stop

Le crochet d’arrêt évalue la réponse de l’agent avant de revenir à l’utilisateur :

  • Remplace $ARGUMENTS par le JSON de contexte de hook, qui inclut la réponse finale de l’agent.
  • Le LLM évalue l’invite et retourne {"ok": true} ou {"ok": false, "reason": "..."}.
  • S’il est rejeté, l’agent continue de fonctionner après l’injection de la raison en tant que message utilisateur.
  • Après trois rejets (valeur par défaut), l’agent s’arrête.

Tester le crochet dans le portail

Procédez comme suit pour tester le crochet Stop :

  1. Accédez à votre agent dans le portail et sélectionnez Builder>Canevas de l’agent.

  2. Sélectionnez le bouton radio Test playground .

  3. Sélectionnez la liste déroulante Subagent/Tool, recherchezmy_hooked_agent, puis sélectionnez Appliquer.

    Testez le terrain de jeu avec l’agent rattaché sélectionné.

  4. Tapez What is 2+2? dans le chat, puis sélectionnez Envoyer.

Regardez ce qui se passe :

  • L’agent répond d’abord avec 4.
  • Le crochet Stop évalue et rejette la réponse (aucun marqueur d’achèvement).
  • Une étape Processus de réflexion s’affiche là où l’agent poursuit.
  • La réponse finale s’affiche : 4 === RESPONSE COMPLETE ===.

Résultat du hook Arrêt montrant que l’agent ajoute le marqueur RESPONSE COMPLETE après le rejet initial.

Le crochet a fonctionné. Il a forcé l’agent à ajouter le marqueur avant d’arrêter.

Ajouter un hook PostToolUse pour l’audit

Ajoutez un hook PostToolUse qui journalise chaque outil utilisé par l’agent. Mettez à jour le même agent en envoyant une nouvelle PUT requête avec les deux hooks :

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: "*" signifie que ce hook s’exécute pour chaque appel d’outil. Le script enregistre le nom de l’outil et injecte un [AUDIT] message dans la conversation.

Pour tester le hook, posez à l’agent une question qui déclenche un outil (par exemple, « Exécuter echo hello»).

Bloquer les commandes dangereuses

Ajoutez un deuxième hook PostToolUse qui bloque rm -rf, sudoet 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"}))

Principales différences par rapport au crochet d’audit :

  • matcher: "Bash|ExecuteShellCommand" s’exécute uniquement pour les outils shell (le modèle est ancré en tant que ^(Bash|ExecuteShellCommand)$).
  • failMode: block bloque le résultat de l’outil si le script lui-même se bloque (mode strict).
  • Retourne "block" avec une raison lorsqu’un modèle dangereux est trouvé.

Formats de réponse de hook

Les hooks de prompt et de commande utilisent différents formats de réponse.

Crochets d’invite

Les hooks d’invite retournent un JSON simple :

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

Crochets de commande

Les hooks de commande retournent le JSON étendu :

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

Les crochets de commande peuvent également utiliser des codes de sortie au lieu de JSON :

Code de sortie Comportement
0 sans sortie Permettre
0 avec JSON Analyser le json
2 Bloquer (stderr devient la raison)
Autres Revient à failMode

Avertissement

Un rejet sans raison est traité comme une approbation. Toujours inclure reason lors du rejet.

Vérifier

Après avoir configuré et testé les hooks, confirmez les conditions suivantes :

  • Vous configurez des hooks de niveau agent personnalisé à l’aide de l’API REST v2. Ils s’appliquent uniquement à cet agent personnalisé.
  • Vous créez des hooks au niveau de l’agent dans Builder > Hooks. Ces hooks s’appliquent à l’intégralité de l’agent.
  • Le crochet d’arrêt amène l’agent à ajouter le marqueur === RESPONSE COMPLETE === avant de s’arrêter.
  • Le hook d’audit PostToolUse enregistre les messages [AUDIT] liés aux appels d’outils.
  • Le hook de stratégie bloque les commandes dangereuses comme rm -rf et sudo.

Résolution des problèmes

Le tableau suivant répertorie les problèmes courants et les solutions pour les hooks d’agent.

Problème Solution
Hooks non visibles dans l’onglet YAML du portail On s'attend à ce que l'onglet YAML affiche uniquement la version 1. Les hooks de niveau agent personnalisés créés via l’API sont actifs et visibles dans Builder>Hooks ou le playground.
Unsupported kind: ExtendedAgent Utilisez le point de terminaison v2 : PUT /api/v2/extendedAgent/agents/{name}.
Handoffs cannot be null Ajoutez "handoffs": [] à la charge utile JSON.
Hook n’a aucun effet Incluez un reason champ lors du rejet. Sans cela, le rejet est traité comme une approbation.
L’agent boucle indéfiniment Limite inférieure maxRejections (valeur par défaut : 3, plage : 1 à 25).

Étape suivante