Skip to main content

Configuración de hooks

Busque información sobre cómo configurar hooks para su uso con CLI de GitHub Copilot y Agente de codificación de Copilot.

En este artículo de referencia se describen los tipos de enlace disponibles con ejemplos, incluidos sus formatos de entrada y salida, procedimientos recomendados de script y patrones avanzados para el registro, el cumplimiento de la seguridad y las integraciones externas. Para obtener información general sobre cómo crear enlaces, consulte Uso de enlaces con agentes de Copilot de GitHub.

Tipos de enlace

Gancho de inicio de sesión

Se ejecuta cuando se inicia una nueva sesión del agente o al reanudar una sesión existente.

          **JSON de entrada:**
JSON
{
  "timestamp": 1704614400000,
  "cwd": "/path/to/project",
  "source": "new",
  "initialPrompt": "Create a new feature"
}
          **Campos:**

* timestamp: marca de tiempo de Unix en milisegundos * cwd: Directorio de trabajo actual * source "new" : (nueva sesión), "resume" (sesión reanudada) o"startup" * initialPrompt: mensaje inicial del usuario (si se proporciona)

          **Salida:** Omitido (sin valor devuelto procesado)

          **Enlace de ejemplo:**
JSON
{
  "type": "command",
  "bash": "./scripts/session-start.sh",
  "powershell": "./scripts/session-start.ps1",
  "cwd": "scripts",
  "timeoutSec": 30
}
          **Script de ejemplo (Bash):**
Shell
#!/bin/bash
INPUT=$(cat)
SOURCE=$(echo "$INPUT" | jq -r '.source')
TIMESTAMP=$(echo "$INPUT" | jq -r '.timestamp')

echo "Session started from $SOURCE at $TIMESTAMP" >> session.log

Gancho de final de sesión

Se ejecuta cuando la sesión del agente finaliza o se termina.

          **JSON de entrada:**
JSON
{
  "timestamp": 1704618000000,
  "cwd": "/path/to/project",
  "reason": "complete"
}
          **Campos:**

* timestamp: marca de tiempo de Unix en milisegundos * cwd: Directorio de trabajo actual * reason: uno de "complete", "error", "abort", "timeout"o "user_exit"

          **Salida:** Omitido

          **Script de ejemplo:**
Shell
#!/bin/bash
INPUT=$(cat)
REASON=$(echo "$INPUT" | jq -r '.reason')

echo "Session ended: $REASON" >> session.log
# Cleanup temporary files
rm -rf /tmp/session-*

Enlace enviado del mensaje de usuario

Se ejecuta cuando el usuario envía un mensaje al agente.

          **JSON de entrada:**
JSON
{
  "timestamp": 1704614500000,
  "cwd": "/path/to/project",
  "prompt": "Fix the authentication bug"
}
          **Campos:**

* timestamp: marca de tiempo de Unix en milisegundos * cwd: Directorio de trabajo actual * prompt: el texto exacto que envió el usuario.

          **Salida:** Se omite (la modificación de mensajes no se admite actualmente en los enlaces de cliente)

          **Script de ejemplo:**
Shell
#!/bin/bash
INPUT=$(cat)
PROMPT=$(echo "$INPUT" | jq -r '.prompt')
TIMESTAMP=$(echo "$INPUT" | jq -r '.timestamp')

# Log to a structured file
echo "$(date -d @$((TIMESTAMP/1000))): $PROMPT" >> prompts.log

Gancho previo al uso de la herramienta

Se ejecuta antes de que el agente use cualquier herramienta (como bash, edit, view). Este es el enlace más eficaz, ya que puede aprobar o denegar ejecuciones de herramientas.

          **JSON de entrada:**
JSON
{
  "timestamp": 1704614600000,
  "cwd": "/path/to/project",
  "toolName": "bash",
  "toolArgs": "{\"command\":\"rm -rf dist\",\"description\":\"Clean build directory\"}"
}
          **Campos:**

* timestamp: marca de tiempo de Unix en milisegundos * cwd: Directorio de trabajo actual * toolName: nombre de la herramienta que se invoca (por ejemplo, "bash", "edit", "view", "create") * toolArgs: cadena JSON que contiene los argumentos de la herramienta.

          **JSON de salida (opcional):**
JSON
{
  "permissionDecision": "deny",
  "permissionDecisionReason": "Destructive operations require approval"
}
          **Campos de salida:**

* permissionDecision: O bien "allow", "deny" o "ask" (solo "deny" se procesa actualmente) * permissionDecisionReason: explicación legible de la decisión

          **Enlace de ejemplo para bloquear comandos peligrosos:**
Shell
#!/bin/bash
INPUT=$(cat)
TOOL_NAME=$(echo "$INPUT" | jq -r '.toolName')
TOOL_ARGS=$(echo "$INPUT" | jq -r '.toolArgs')

# Log the tool use
echo "$(date): Tool=$TOOL_NAME Args=$TOOL_ARGS" >> tool-usage.log

# Check for dangerous patterns
if echo "$TOOL_ARGS" | grep -qE "rm -rf /|format|DROP TABLE"; then
  echo '{"permissionDecision":"deny","permissionDecisionReason":"Dangerous command detected"}'
  exit 0
fi

# Allow by default (or omit output to allow)
echo '{"permissionDecision":"allow"}'
          **Enlace de ejemplo para aplicar permisos de archivo:**
Shell
#!/bin/bash
INPUT=$(cat)
TOOL_NAME=$(echo "$INPUT" | jq -r '.toolName')

# Only allow editing specific directories
if [ "$TOOL_NAME" = "edit" ]; then
  PATH_ARG=$(echo "$INPUT" | jq -r '.toolArgs' | jq -r '.path')
  
  if [[ ! "$PATH_ARG" =~ ^(src/|test/) ]]; then
    echo '{"permissionDecision":"deny","permissionDecisionReason":"Can only edit files in src/ or test/ directories"}'
    exit 0
  fi
fi

# Allow all other tools

Gancho de uso posterior a la herramienta

Se ejecuta después de que una herramienta complete la ejecución (ya sea correcta o con errores).

          **JSON de entrada de ejemplo:**
JSON
{
  "timestamp": 1704614700000,
  "cwd": "/path/to/project",
  "toolName": "bash",
  "toolArgs": "{\"command\":\"npm test\"}",
  "toolResult": {
    "resultType": "success",
    "textResultForLlm": "All tests passed (15/15)"
  }
}
          **Campos:**

* timestamp: marca de tiempo de Unix en milisegundos * cwd: Directorio de trabajo actual * toolName: nombre de la herramienta que se ejecutó * toolArgs: cadena JSON que contiene los argumentos de la herramienta. * toolResult: objeto Resultado que contiene: * resultType: "success", "failure" o "denied" * textResultForLlm: el texto del resultado que se muestra al agente.

          **Salida:** Se omite (actualmente no se admite la modificación de resultados)

          **Script de ejemplo que registra las estadísticas de ejecución de herramientas en un archivo CSV:**

Este script registra las estadísticas de ejecución de herramientas en un archivo CSV y envía una alerta de correo electrónico cuando se produce un error en una herramienta.

Shell
#!/bin/bash
INPUT=$(cat)
TOOL_NAME=$(echo "$INPUT" | jq -r '.toolName')
RESULT_TYPE=$(echo "$INPUT" | jq -r '.toolResult.resultType')

# Track statistics
echo "$(date),${TOOL_NAME},${RESULT_TYPE}" >> tool-stats.csv

# Alert on failures
if [ "$RESULT_TYPE" = "failure" ]; then
  RESULT_TEXT=$(echo "$INPUT" | jq -r '.toolResult.textResultForLlm')
  echo "FAILURE: $TOOL_NAME - $RESULT_TEXT" | mail -s "Agent Tool Failed" admin@example.com
fi

Error en el gancho

Se ejecuta cuando se produce un error durante la ejecución del agente.

          **JSON de entrada de ejemplo:**
JSON
{
  "timestamp": 1704614800000,
  "cwd": "/path/to/project",
  "error": {
    "message": "Network timeout",
    "name": "TimeoutError",
    "stack": "TimeoutError: Network timeout\n    at ..."
  }
}
          **Campos:**

* timestamp: marca de tiempo de Unix en milisegundos * cwd: Directorio de trabajo actual * error: objeto de error que contiene: * message: mensaje de error * name: tipo de error/nombre * stack: seguimiento de pila (si está disponible)

          **Salida:** Se omite (actualmente no se admite la modificación del control de errores)

          **Script de ejemplo que extrae los detalles del error en un archivo de registro:**
Shell
#!/bin/bash
INPUT=$(cat)
ERROR_MSG=$(echo "$INPUT" | jq -r '.error.message')
ERROR_NAME=$(echo "$INPUT" | jq -r '.error.name')

echo "$(date): [$ERROR_NAME] $ERROR_MSG" >> errors.log

Mejores prácticas de script

Lectura de la entrada

Este script de ejemplo lee la entrada JSON de stdin en una variable y, a continuación, usa jq para extraer los timestamp campos y cwd .

          **Bash:**
Shell
#!/bin/bash
# Read JSON from stdin
INPUT=$(cat)

# Parse with jq
TIMESTAMP=$(echo "$INPUT" | jq -r '.timestamp')
CWD=$(echo "$INPUT" | jq -r '.cwd')
          **PowerShell**:
PowerShell
# Read JSON from stdin
$input = [Console]::In.ReadToEnd() | ConvertFrom-Json

# Access properties
$timestamp = $input.timestamp
$cwd = $input.cwd

Salida de JSON

En este script de ejemplo se muestra cómo generar JSON válido desde el script de enlace. Use jq -c en Bash para la salida compacta de una sola línea o ConvertTo-Json -Compress en PowerShell.

          **Bash:**
Shell
#!/bin/bash
# Use jq to compact the JSON output to a single line
echo '{"permissionDecision":"deny","permissionDecisionReason":"Security policy violation"}' | jq -c

# Or construct with variables
REASON="Too dangerous"
jq -n --arg reason "$REASON" '{permissionDecision: "deny", permissionDecisionReason: $reason}'
          **PowerShell**:
PowerShell
# Use ConvertTo-Json to compact the JSON output to a single line
$output = @{
    permissionDecision = "deny"
    permissionDecisionReason = "Security policy violation"
}
$output | ConvertTo-Json -Compress

Control de errores

En este ejemplo de script se muestra cómo controlar errores en scripts de enlace.

          **Bash:**
Shell
#!/bin/bash
set -e  # Exit on error

INPUT=$(cat)
# ... process input ...

# Exit with 0 for success
exit 0
          **PowerShell**:
PowerShell
$ErrorActionPreference = "Stop"

try {
    $input = [Console]::In.ReadToEnd() | ConvertFrom-Json
    # ... process input ...
    exit 0
} catch {
    Write-Error $_.Exception.Message
    exit 1
}

Manejo de tiempos de espera

Los hooks tienen un tiempo de espera predeterminado de 30 segundos. Para operaciones más largas, aumente timeoutSec:

JSON
{
  "type": "command",
  "bash": "./scripts/slow-validation.sh",
  "timeoutSec": 120
}

Patrones avanzados

Varios ganchos del mismo tipo

Puede definir varios ganchos para el mismo evento. Se ejecutan en orden:

JSON
{
  "version": 1,
  "hooks": {
    "preToolUse": [
      {
        "type": "command",
        "bash": "./scripts/security-check.sh",
        "comment": "Security validation - runs first"
      },
      {
        "type": "command", 
        "bash": "./scripts/audit-log.sh",
        "comment": "Audit logging - runs second"
      },
      {
        "type": "command",
        "bash": "./scripts/metrics.sh",
        "comment": "Metrics collection - runs third"
      }
    ]
  }
}

Lógica condicional en scripts

          **Ejemplo: Solo bloquear herramientas específicas**
Shell
#!/bin/bash
INPUT=$(cat)
TOOL_NAME=$(echo "$INPUT" | jq -r '.toolName')

# Only validate bash commands
if [ "$TOOL_NAME" != "bash" ]; then
  exit 0  # Allow all non-bash tools
fi

# Check bash command for dangerous patterns
COMMAND=$(echo "$INPUT" | jq -r '.toolArgs' | jq -r '.command')
if echo "$COMMAND" | grep -qE "rm -rf|sudo|mkfs"; then
  echo '{"permissionDecision":"deny","permissionDecisionReason":"Dangerous system command"}'
fi

Registro estructurado

          **Ejemplo: formato de líneas JSON**
Shell
#!/bin/bash
INPUT=$(cat)
TIMESTAMP=$(echo "$INPUT" | jq -r '.timestamp')
TOOL_NAME=$(echo "$INPUT" | jq -r '.toolName')
RESULT_TYPE=$(echo "$INPUT" | jq -r '.toolResult.resultType')

# Output structured log entry
jq -n \
  --arg ts "$TIMESTAMP" \
  --arg tool "$TOOL_NAME" \
  --arg result "$RESULT_TYPE" \
  '{timestamp: $ts, tool: $tool, result: $result}' >> logs/audit.jsonl

Integración con sistemas externos

          **Ejemplo: Envío de alertas a Slack**
Shell
#!/bin/bash
INPUT=$(cat)
ERROR_MSG=$(echo "$INPUT" | jq -r '.error.message')

WEBHOOK_URL="https://hooks.slack.com/services/YOUR/WEBHOOK/URL"

curl -X POST "$WEBHOOK_URL" \
  -H 'Content-Type: application/json' \
  -d "{\"text\":\"Agent Error: $ERROR_MSG\"}"

Ejemplos de casos de uso

Registro de auditoría de cumplimiento

Registre todas las acciones del agente para los requisitos de cumplimiento mediante scripts de registro:

JSON
{
  "version": 1,
  "hooks": {
    "sessionStart": [{"type": "command", "bash": "./audit/log-session-start.sh"}],
    "userPromptSubmitted": [{"type": "command", "bash": "./audit/log-prompt.sh"}],
    "preToolUse": [{"type": "command", "bash": "./audit/log-tool-use.sh"}],
    "postToolUse": [{"type": "command", "bash": "./audit/log-tool-result.sh"}],
    "sessionEnd": [{"type": "command", "bash": "./audit/log-session-end.sh"}]
  }
}

Seguimiento de costos

Seguimiento del uso de herramientas para la asignación de costos:

Shell
#!/bin/bash
INPUT=$(cat)
TOOL_NAME=$(echo "$INPUT" | jq -r '.toolName')
TIMESTAMP=$(echo "$INPUT" | jq -r '.timestamp')
USER=${USER:-unknown}

echo "$TIMESTAMP,$USER,$TOOL_NAME" >> /var/log/copilot/usage.csv

Aplicación de la calidad del código

Impedir confirmaciones que infringen los estándares de código:

Shell
#!/bin/bash
INPUT=$(cat)
TOOL_NAME=$(echo "$INPUT" | jq -r '.toolName')

if [ "$TOOL_NAME" = "edit" ] || [ "$TOOL_NAME" = "create" ]; then
  # Run linter before allowing edits
  npm run lint-staged
  if [ $? -ne 0 ]; then
    echo '{"permissionDecision":"deny","permissionDecisionReason":"Code does not pass linting"}'
  fi
fi

Sistema de notificaciones

Enviar notificaciones sobre eventos importantes:

Shell
#!/bin/bash
INPUT=$(cat)
PROMPT=$(echo "$INPUT" | jq -r '.prompt')

# Notify on production-related prompts
if echo "$PROMPT" | grep -iq "production"; then
  echo "ALERT: Production-related prompt: $PROMPT" | mail -s "Agent Alert" team@example.com
fi