Tutorial: Configurar ganchos de agente (API) no Agente SRE do Azure

Dica

Prefere a interface do usuário do portal? Agora você pode criar e gerenciar ganchos diretamente no portal sem usar a API REST. O portal fornece um formulário visual e um editor de código. Nenhum curl comando é necessário.

Neste tutorial, você criará um agente personalizado com um stop hook que força o agente a adicionar um marcador de conclusão a cada resposta. Configure o gancho por meio da API REST e teste-o no playground do portal.

Tempo estimado: 15 minutos

Observação

Ganchos no nível do agente versus no nível do agente personalizado: Este tutorial cria ganchos em um agente personalizado (ganchos de nível de agente personalizado). Esses ganchos só são acionados quando esse agente personalizado específico é executado.

Para criar ganchos no nível do agente que se aplicam a todo o agente (todas as threads, todos os agentes personalizados), use Construtor>Ganchos no portal.

Nível Como criar Scope
Nível do agente Portal: Construtor > Ganchos Aplica-se a todas as threads e agentes personalizados
Nível de agente personalizado API REST (este tutorial) ou Portal: Canvas do Agente > Agente personalizado > Gerenciar Ganchos Aplica-se apenas a um agente personalizado

Neste tutorial, você aprenderá como:

  • Criar um agente personalizado com um gancho de parada usando a API REST
  • Testar o comportamento do gancho no playground de teste do portal
  • Adicionar um gancho do PostToolUse para o uso da ferramenta de auditoria
  • Bloquear comandos perigosos com um gancho de política

Pré-requisitos

  • Um agente SRE do Azure em estado de execução
  • curl para chamar a API REST
  • CLI do Azure conectou-se (az login) para obter um token de acesso

Entender o formato da API de hook

Este tutorial usa a API REST v2 para criar ganchos em um agente personalizado. A guia do editor YAML do portal mostra o formato v1 e não exibe ganchos configurados usando a API, mas os ganchos ainda estão ativos. Você pode verificá-los na página de Construtor>Ganchos ou no Playground de teste.

Dica

Quando usar a API versus o portal:

  • Portal (Construtor > Ganchos): ideal para ganchos no nível do agente em formato visual. Nenhum código é necessário.
  • API (este tutorial): melhor para ganchos de nível de agente personalizado, pipelines de CI/CD ou gerenciamento programático.

Localizar a URL da API do agente

A URL base da API do agente segue este padrão:

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

Para encontrar esse elemento:

  1. Abra sre.azure.com e selecione seu agente.
  2. Na barra lateral esquerda, selecione Construtor>Tela do Agente.
  3. Abra as Ferramentas de Desenvolvedor do navegador (F12 ou clique com o botão direito do mouse em > Inspecionar).
  4. Vá para a guia Rede , filtre por "api" e procure solicitações para uma URL que termina em .azuresre.ai.
  5. A URL base é tudo antes de /api/....

Como alternativa, verifique o src atributo na guia Elementos. Procure um <iframe> cujo src começa com https://{agent-name}--.

Obter um token de acesso

Execute o seguinte comando para obter um token de acesso para a API do Agente SRE:

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

Criar um agente personalizado com um gancho de parada

Esta etapa cria um agente personalizado chamado my_hooked_agent com um gancho de parada que verifica se a resposta termina com === RESPONSE COMPLETE ===. Se o marcador estiver ausente, o gancho rejeitará a resposta e instrui o agente a adicionar o marcador.

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

Você recebe HTTP 202 Aceito com a configuração completa do agente no corpo da resposta.

O exemplo a seguir mostra a mesma configuração no formato YAML v2 para referência:

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

Como funciona o gancho de parada

O gancho de parada avalia a resposta do agente antes de retornar ao usuário:

  • Substitui $ARGUMENTS pelo JSON do contexto de hook, que inclui a resposta final do agente.
  • O LLM avalia o prompt e retorna {"ok": true} ou {"ok": false, "reason": "..."}.
  • Se rejeitado, o agente continuará funcionando depois que o motivo for injetado como uma mensagem de usuário.
  • Após três rejeições (o padrão), o agente para.

Testar o gancho no portal

Siga estas etapas para testar o gancho de parada:

  1. Acesse seu agente no portal e selecione Construtor>Tela do Agente.

  2. Selecione o botão de rádio Test playground.

  3. Selecione o menu suspenso Subagent/Ferramenta, encontre my_hooked_agent e selecione Aplicar.

    Teste o playground com o agente conectado selecionado.

  4. Digite What is 2+2? no chat e selecione Enviar.

Assista ao que acontece:

  • O agente responde primeiro com 4.
  • O gancho stop avalia e rejeita a resposta (sem marcador de conclusão).
  • Uma etapa do processo de pensamento é exibida, indicando onde o agente continua.
  • A resposta final é exibida: 4 === RESPONSE COMPLETE ==== .

O resultado do stop hook indica que o agente adiciona o marcador RESPONSE COMPLETE depois da rejeição inicial.

O gancho funcionou. Forçou o agente a adicionar o marcador antes de parar.

Adicionar um gancho de PostToolUse para auditoria

Adicione um gancho PostToolUse que registra todas as ferramentas que o agente usa. Atualize o mesmo agente enviando uma nova PUT solicitação com ambos os ganchos:

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: "*" significa que esse gancho é executado para cada chamada de ferramenta. O script registra o nome da ferramenta e injeta uma [AUDIT] mensagem na conversa.

Para testar o gancho, faça uma pergunta ao agente que dispara uma ferramenta (por exemplo, "Executar echo hello").

Bloquear comandos perigosos

Adicione um segundo gancho PostToolUse que bloqueia rm -rf, sudo e 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"}))

Principais diferenças em relação ao gancho de auditoria:

  • matcher: "Bash|ExecuteShellCommand" só é executado para ferramentas de shell (o padrão é ancorado como ^(Bash|ExecuteShellCommand)$).
  • failMode: block bloqueia o resultado da ferramenta se o script em si falhar (modo estrito).
  • Retorna "block" com um motivo quando um padrão perigoso é encontrado.

Formatos de resposta do gancho

Ganchos de prompt e ganchos de comando usam formatos de resposta diferentes.

Ganchos de prompt

Hooks de comando retornam JSON simples:

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

Ganchos de comando

Os ganchos de comando retornam JSON expandido:

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

Os ganchos de comando também podem usar códigos de saída em vez de JSON:

Código de saída Comportamento
0 sem saída Permitir
0 com JSON Processar o JSON
2 Bloquear (stderr se torna o motivo)
Outras Retorna para failMode

Cuidado

Uma rejeição sem motivo é tratada como aprovação. Sempre inclua reason ao rejeitar.

Verificar

Depois de configurar e testar os ganchos, confirme as seguintes condições:

  • Você configura ganchos no nível do agente personalizado usando a API REST v2. Elas se aplicam somente a esse agente personalizado.
  • Você cria ganchos no nível do agente em Construtor > Ganchos. Eles se aplicam a todo o agente.
  • O gancho de parada faz com que o agente adicione o marcador === RESPONSE COMPLETE === antes de parar.
  • O gancho de auditoria do PostToolUse registra mensagens [AUDIT] para chamadas de ferramenta.
  • O gancho de política bloqueia comandos perigosos como rm -rf e sudo.

Solução de problemas

A tabela a seguir apresenta problemas comuns e soluções para ganchos de agentes.

Problema Solução
Ganchos não visíveis na guia YAML do portal Esperado - a aba YAML mostra apenas v1. Os ganchos personalizados no nível do agente criados por meio da API são ativos e estão visíveis no Construtor>Ganchos ou no playground.
Unsupported kind: ExtendedAgent Use o ponto de extremidade v2: PUT /api/v2/extendedAgent/agents/{name}.
Handoffs cannot be null Adicione "handoffs": [] ao payload JSON.
Gancho não tem efeito Inclua um reason campo ao rejeitar. Sem ela, a rejeição é tratada como aprovação.
O agente entra em um loop eterno Inferior maxRejections (padrão: 3, intervalo: 1 a 25).

Próxima etapa