Tutorial: Configuración de enlaces de agente (API) en el agente de Azure SRE

Sugerencia

¿Prefiere la interfaz de usuario del portal? Ahora puede crear y administrar enlaces directamente en el portal sin usar la API REST. El portal proporciona un formulario visual y un editor de código. No se necesitan comandos curl.

En este tutorial, crearás un agente personalizado con un gancho Stop que obligará al agente a añadir un marcador de finalización a cada respuesta. Configure el enlace a través de la API REST y, a continuación, pruébelo en el área de juegos del portal.

Tiempo estimado: 15 minutos

Nota:

Enlaces de nivel de agente frente a custom-agent-level: En este tutorial se crean enlaces en un agente personalizado (enlaces de nivel de agente personalizado). Estos ganchos solo se activan cuando se ejecuta ese agente personalizado específico.

Para crear enlaces de nivel de agente que se aplican a todo el agente (todos los subprocesos, todos los agentes personalizados), use Builder>Hooks en el portal.

Level Cómo crear Ámbito
Nivel de agente Portal: enlaces de > del generador Se aplica a todos los hilos y agentes personalizados
Nivel de agente personalizado API REST (este tutorial) o Portal: Lienzo del agente > Agente personalizado > Administrar enlaces Solo se aplica a un agente personalizado

En este tutorial aprenderá a:

  • Creación de un agente personalizado con un enlace stop mediante la API REST
  • Prueba del comportamiento del enlace en el área de juegos del portal
  • Agregar un enlace PostToolUse para el uso de la herramienta de auditoría
  • Bloqueo de comandos peligrosos con un enlace de directiva

Prerrequisitos

  • Un agente de SRE de Azure en estado en ejecución
  • curl para llamar a la API REST
  • La CLI de Azure inició sesión (az login) para obtener un token de acceso

Descripción del formato de la API de enlace

En este tutorial se usa la API REST v2 para crear enlaces en un agente personalizado. La pestaña editor de YAML del portal muestra el formato v1 y no muestra enlaces configurados a través de la API, pero los enlaces siguen activos. Puede verificarlos en la página Hooks>Constructor o en la zona de pruebas.

Sugerencia

Cuándo usar la API frente al portal:

  • Portal (Enlaces > del generador): mejor para enlaces de nivel de agente en formato visual. No se necesita código.
  • API (este tutorial): ideal para hooks de nivel de agente personalizado, canalizaciones de CI/CD o gestión mediante programación.

Búsqueda de la dirección URL de la API del agente

La dirección URL base de la API del agente sigue este patrón:

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

Para encontrarlo:

  1. Abra sre.azure.com y seleccione el agente.
  2. En la barra lateral izquierda, seleccione Generador>Lienzo de agente.
  3. Abra las Herramientas de desarrollo del explorador (F12 o haga clic con el botón derecho en > Inspeccionar).
  4. Vaya a la pestaña Red , filtre por "api" y busque solicitudes a una dirección URL que termine en .azuresre.ai.
  5. La dirección URL base está compuesta por todo lo anterior a /api/....

Como alternativa, compruebe el src atributo en la pestaña Elementos . Busque un <iframe> cuyo src inicio comience por https://{agent-name}--.

Obtención de un token de acceso

Ejecute el comando siguiente para obtener un token de acceso para la API del agente de SRE:

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

Creación de un agente personalizado con un enlace de detención

Este paso crea un agente personalizado llamado my_hooked_agent con un enlace Stop que comprueba si la respuesta termina con === RESPONSE COMPLETE ===. Si falta el marcador, el enlace rechaza la respuesta e indica al agente que agregue el 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

Recibirá HTTP 202 Aceptado con la configuración completa del agente en el cuerpo de la respuesta.

En el ejemplo siguiente se muestra la misma configuración en formato YAML v2 para referencia:

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

Funcionamiento del gancho de parada

El gancho Detener evalúa la respuesta del agente antes de devolverla al usuario:

  • Reemplaza $ARGUMENTS con el JSON del contexto de gancho, que incluye la respuesta final del agente.
  • El LLM evalúa la solicitud y devuelve {"ok": true} o {"ok": false, "reason": "..."}.
  • Si se rechaza, el agente continúa trabajando después de insertar el motivo como mensaje de usuario.
  • Después de tres rechazos (valor predeterminado), el agente se detiene.

Probar el enlace en el portal

Siga estos pasos para probar el enlace Stop:

  1. Vaya a su agente en el portal y seleccione Generador>Lienzo de agente.

  2. Seleccione el botón de opción Área de juegos de pruebas.

  3. Seleccione el desplegable Subagent/Tool, busque my_hooked_agent y seleccione Aplicar.

    Área de juegos de prueba con el agente conectado seleccionado.

  4. Escriba en el chat What is 2+2? y seleccione Enviar.

Observe lo que sucede:

  • El agente responde primero con 4.
  • El enlace Detener evalúa y rechaza la respuesta (sin marcador de finalización).
  • Aparece un paso de proceso de pensamiento en el que el agente continúa.
  • Aparece la respuesta final: 4 === RESPONSE COMPLETE ===.

El resultado del gancho de interrupción muestra que el agente agrega el marcador RESPONSE COMPLETE tras el rechazo inicial.

El gancho funcionó. Obligó al agente a agregar el marcador antes de detenerse.

Agregar un enlace PostToolUse para la auditoría

Agregue un enlace PostToolUse que registre todas las herramientas que usa el agente. Actualice el mismo agente mediante el envío de una nueva solicitud PUT con ambos enlaces:

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 este hook se ejecuta para cada llamada de herramienta. El script registra el nombre de la herramienta e inserta un [AUDIT] mensaje en la conversación.

Para probar el enlace, pregunte al agente una pregunta que desencadena una herramienta (por ejemplo, "Ejecutar echo hello").

Bloquear comandos peligrosos

Agregue un segundo enlace PostToolUse que bloquee rm -rf, sudoy 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"}))

Diferencias clave del enlace de auditoría:

  • matcher: "Bash|ExecuteShellCommand" solo se ejecuta para las herramientas de shell (el patrón está anclado como ^(Bash|ExecuteShellCommand)$).
  • failMode: block bloquea el resultado de la herramienta si el propio script falla (modo estricto).
  • Devuelve "block" con un motivo cuando se encuentra un patrón peligroso.

Formatos de respuesta del enlace

Los ganchos de solicitud y los ganchos de comandos usan diferentes formatos de respuesta.

Enlaces de solicitudes

Los ganchos de solicitud devuelven un JSON sencillo:

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

Ganchos de comando

Los enlaces de comandos devuelven JSON expandido:

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

Los enlaces de comandos también pueden usar códigos de salida en lugar de JSON:

Código de salida Comportamiento
0 sin salida Permitir
0 con JSON Análisis del código JSON
2 Bloquear (stderr se convierte en el motivo)
Otros Vuelve a failMode

Precaución

Un rechazo sin motivo se trata como aprobación. Incluya siempre reason cuando se rechaza.

Verificar

Después de configurar y probar los enlaces, confirme las condiciones siguientes:

  • Los enlaces de nivel de agente personalizado se configuran mediante la API REST v2. Solo se aplican a ese agente personalizado.
  • Los ganchos de nivel de agente se crean en Builder > Hooks. Se aplican en todo el agente.
  • El gancho de interrupción hace que el agente agregue el marcador === RESPONSE COMPLETE === antes de detenerse.
  • El enlace de auditoría PostToolUse registra los mensajes [AUDIT] de las llamadas a herramientas.
  • El enlace de directiva bloquea comandos peligrosos como rm -rf y sudo.

Solución de problemas

En la tabla siguiente se enumeran los problemas y soluciones comunes para los enlaces de agente.

Problema Solución
Enlaces no visibles en la pestaña YAML del portal Esperado: la pestaña YAML solo muestra la versión 1. Los enlaces de nivel de agente personalizados creados a través de la API están activos y son visibles en Generador>Enlaces o en el área de juegos.
Unsupported kind: ExtendedAgent Utilice el extremo v2: PUT /api/v2/extendedAgent/agents/{name}.
Handoffs cannot be null Agregue "handoffs": [] a la carga JSON.
El enlace no tiene efecto Incluir un campo reason al rechazar. Sin él, el rechazo se trata como aprobación.
El agente entra en un bucle infinito Inferior maxRejections (valor predeterminado: 3, intervalo: 1-25).

Paso siguiente