Para usar webhooks de GitHub y activar agentes de programación con IA, apunta un webhook del repositorio a un endpoint de recepción propio, verifica el encabezado X-Hub-Signature-256 con el cuerpo sin procesar (raw body), responde con un 202 dentro de la ventana de 10 segundos de GitHub y envía el evento a una cola. Luego, un worker filtra el evento, lo asocia a un hilo (repositorio más número de PR) e inicia o alimenta al agente.
En el resto de esta guía se muestra cada paso en código y cómo hacer que tu agente de programación pruebe el endpoint con Apidog CLI.
Por qué activar agentes de programación con IA mediante webhooks de GitHub en lugar de polling
Un disparador por webhook es una llamada HTTP que GitHub realiza a tu servidor en cuanto ocurre algo en un repositorio: un comentario, una revisión o un flujo de trabajo que finaliza. Tu agente permanece inactivo hasta que llega una entrega, por lo que consume cero tokens y cero llamadas a la API mientras no pasa nada, y reacciona en cuestión de segundos en vez de esperar a la siguiente consulta.
Hacer polling cada minuto agota los límites de peticiones (rate limits) con respuestas vacías y, aun así, genera retrasos de hasta un minuto. La explicación detallada se encuentra en webhooks vs polling.
El equipo de DeepSeek Harness planteó el mismo argumento en su artículo «Exploring Super-agent Design», publicado el 1 de noviembre de 2026. Ellos llaman a estas entradas «Triggers» (disparadores): el agente observa los eventos y permanece en reposo el resto del tiempo. El artículo describe una arquitectura y un plugin prototipo, no una funcionalidad final de DeepSeek. Analizamos el diseño completo en cómo construir un superagente; en este post desarrollaremos únicamente la capa de activación, aplicable a cualquier agente de programación.
Qué eventos de webhook de GitHub deberían activar un agente
Suscríbete únicamente a los eventos en los que una persona esperaría que un compañero de equipo actúe. Cada evento adicional es una entrega que tendrás que verificar, almacenar y filtrar.
| Evento | Acción a monitorizar | Qué hace el agente |
|---|---|---|
issue_comment | created | Responde a un comentario en una issue o en la conversación de un PR, por ejemplo «@bot arregla la prueba que falla» |
pull_request_review_comment | created | Responde a un comentario en una línea específica del diff |
pull_request | opened, synchronize | Revisa un nuevo PR o vuelve a revisarlo tras un push |
workflow_run | completed con conclusion: failure | Lee los logs del fallo y propone una solución |
check_run | completed con una conclusión de fallo | Igual que el anterior, para verificaciones reportadas por apps |
Dos detalles de la referencia de eventos de webhook de GitHub te ahorrarán tiempo de depuración. En primer lugar, issue_comment se dispara tanto para comentarios en issues como en pull requests; un comentario en un PR incluye un objeto issue.pull_request, que es la forma de distinguirlos. En segundo lugar, workflow_run con la acción completed se dispara tanto si la ejecución concluyó con éxito como si falló, por lo que debes comprobar workflow_run.conclusion tú mismo.
Los payloads tienen un límite de 25 MB; GitHub nunca envía nada de mayor tamaño.
Verifica la firma X-Hub-Signature-256 en el cuerpo sin procesar (raw body)
Cuando configuras un secreto en el webhook, GitHub firma cada entrega con HMAC SHA-256 del cuerpo sin procesar de la solicitud y envía el digest hexadecimal como X-Hub-Signature-256: sha256=<digest>. Tu endpoint recalcula el digest y compara ambos valores en tiempo constante.
Tres reglas de la guía de GitHub sobre validación de entregas de webhooks:
- Aplica el hash sobre los bytes sin procesar, no sobre un objeto JSON reserializado. Parsear y volver a serializar modifica los espacios en blanco y anula la coincidencia.
- Compara con una función de tiempo constante como
crypto.timingSafeEqualde Node, nunca con==. - Usa
X-Hub-Signature-256. El encabezado anteriorX-Hub-Signatureutiliza SHA-1 y existe solo por retrocompatibilidad.
Aquí tienes el servicio de recepción en Node con Express:
import express from "express"; import crypto from "node:crypto"; const app = express(); const [REDACTED CREDENTIAL]; const seen = new Set(); // use Redis or a DB table in production function validSignature(raw, header) { if (!header) return false; const expected = "sha256=" + crypto.createHmac("sha256", SECRET).update(raw).digest("hex"); const a = Buffer.from(expected); const b = Buffer.from(header); return a.length === b.length && crypto.timingSafeEqual(a, b); } app.post("/triggers/github", express.raw({ type: "application/json" }), (req, res) => { if (!validSignature(req.body, req.get("X-Hub-Signature-256"))) { return res.status(401).json({ error: "bad signature" }); } const deliveryId = req.get("X-GitHub-Delivery"); if (seen.has(deliveryId)) { return res.status(200).json({ duplicate: true, trigger_id: deliveryId }); } seen.add(deliveryId); const event = req.get("X-GitHub-Event"); const payload = JSON.parse(req.body); const prNumber = payload.pull_request?.number ?? payload.issue?.number; const threadId = `${payload.repository.full_name}#${prNumber}`; queue.push({ deliveryId, event, threadId, payload }); // your queue client res.status(202).json({ trigger_id: deliveryId, thread_id: threadId }); }); app.listen(3000); El manejador ejecuta cuatro tareas ligeras y nada que cause lentitud. Para conocer los esquemas de firma entre diferentes proveedores, consulta verificación de firmas de webhooks.
Responde con 2xx en menos de 10 segundos y encola el trabajo del agente
Las buenas prácticas para webhooks de GitHub establecen que tu servidor debe responder con un código 2xx en un plazo de 10 segundos. Si tarda más, GitHub interrumpe la conexión y registra la entrega como fallida.
La ejecución de un agente toma minutos, por lo que nunca puede ocurrir dentro de la propia solicitud. Envía el evento a una cola (Redis, SQS, una tabla de Postgres o cualquier sistema duradero) y responde con un 202 Accepted de inmediato. Un proceso worker independiente extraerá los eventos de la cola, aplicará los filtros e iniciará el agente.
Los fallos no deben pasarse por alto: GitHub no reintenta automáticamente las entregas fallidas. Puedes reenviarlas de forma manual o a través de la API durante un máximo de 3 días; por tanto, un manejador lento perderá silenciosamente el disparador de ese comentario a menos que alguien lo detecte.
Filtra en dos etapas: ruta rápida en código y ruta lenta con el modelo
La gran mayoría de las entregas nunca deberían alcanzar a un modelo. El artículo de DeepSeek divide el filtrado en una ruta rápida programada en código y una ruta lenta en la que un LLM aplica directivas redactadas como prompts. Esa separación mantiene los costes asociados al trabajo real y no al ruido del repositorio.
Ruta rápida (código, se ejecuta en microsegundos):
- Lista de repositorios permitidos (allowlist): solo los repositorios que hayas habilitado expresamente.
- Reglas de remitente: ignora la cuenta de bot del propio agente, o crearás un bucle infinito en el que se responderá a sí mismo.
- Modo de mención: inicia una ejecución únicamente cuando el comentario contenga
@your-bot. El artículo menciona tres modos que conviene adoptar: responder solo a solicitudes explícitas, tratarlo como candidato para la ruta lenta o ignorarlo.
Ruta lenta (LLM, evalúa lo que supera la ruta anterior):
Proporciona al modelo el texto del comentario junto con un prompt breve de validación, por ejemplo: «¿Es esto una solicitud para modificar código en esta PR? Responde sí o no y aporta el motivo en una sola línea». Solo una respuesta afirmativa activa el agente. Esto permite descartar comentarios como «gracias @bot, se ve bien», que cumplen la regla de la mención pero no requieren ninguna acción.
function fastPath({ event, payload }) { if (payload.sender?.type === "Bot") return "ignore"; if (!ALLOWED_REPOS.has(payload.repository.full_name)) return "ignore"; if (event === "workflow_run") return payload.workflow_run.conclusion === "failure" ? "run" : "ignore"; const body = payload.comment?.body ?? ""; return body.includes("@your-bot") ? "candidate" : "ignore"; } Enruta el seguimiento por thread id para que responda el mismo agente
Un hilo (thread) representa la secuencia de eventos consecutivos en una misma PR. Genera el thread_id a partir del repositorio y el número de PR o issue, tal como hace el manejador anterior con acme/api#42. En el diseño propuesto por el artículo, el worker creado para el primer evento se suscribe a su hilo, y los eventos de seguimiento van directos a él sin necesidad de otra operación de enrutamiento.
En la práctica, esto equivale a una tabla de correspondencia entre thread_id y el ID de sesión del agente. Cuando llega una entrega para un hilo con una sesión activa, añade el comentario a esa sesión. De este modo, el agente conserva su contexto: el diff que analizó y las pruebas que ejecutó. Sin esto, tres comentarios en una misma PR generarían tres agentes con respuestas contradictorias.
El artículo incorpora otro detalle muy valioso: los disparadores que llegan mientras el enrutador procesa un turno se agrupan en lote para su siguiente llamada, por lo que una ráfaga de cinco comentarios requiere una sola decisión en lugar de cinco.
Desduplica mediante X-GitHub-Delivery
Cada entrega incluye un GUID en X-GitHub-Delivery. La documentación de GitHub indica que un reenvío reutiliza el mismo valor que el original, lo que lo convierte en la clave de idempotencia ideal. Almacena cada ID (un índice único en tu base de datos funciona a la perfección) y trata las repeticiones como operaciones nulas (no-op) que sigan devolviendo un código 2xx, evitando así que GitHub las clasifique como fallidas.
Esto previene también los ataques de repetición (replay attacks): la firma de una entrega interceptada seguirá siendo válida, pero su ID ya estará registrado.
Deja que tu agente de programación pruebe el endpoint disparador con Apidog CLI
No deberías comprobar manualmente los cálculos de las firmas. Deja que el agente de programación que desarrolló el servicio de recepción escriba también sus pruebas y las ejecute con Apidog CLI. Configúralo una sola vez:
npm install -g apidog-cli@latest apidog auth login --with-token <YOUR_TOKEN> npx -y skills add https://apidog.com # pick your agent when prompted Luego dale a Claude Code, Codex o Cursor un único [REDACTED PROMPT]
In Apidog project , create the endpoint POST /triggers/github from the
sample issue_comment payload in fixtures/issue_comment.json. Then create test cases
against the staging environment:
- valid X-Hub-Signature-256 -> 202 with trigger_id and a thread_id of "#"
- a second comment on the same PR -> same thread_id
- bad signature -> 401
- same X-GitHub-Delivery sent twice -> second call returns duplicate: true, no new job Sign the bodies with the staging webhook secret in a pre-request script. Run them and summarize any failures.
El agente lee cada esquema, valida su payload, crea los recursos y los ejecuta:
bash
apidog cli-schema get endpoint-create
apidog cli-schema validate endpoint-create --file endpoint.json
apidog endpoint create --project --file endpoint.json
apidog cli-schema get test-case-create
apidog cli-schema validate test-case-create --file case-valid-signature.json
apidog test-case create --project --file case-valid-signature.json
apidog run --test-case --project -e -r cli,json
El reporter `cli` muestra si cada aserción pasó o falló, y el informe `json` se genera en `./apidog-reports`, permitiendo al agente ver con exactitud qué comprobación falló (un 200 donde esperabas 401 suele significar que falta el middleware para procesar el cuerpo sin procesar / raw body). La misma instrucción de `apidog run` puede incorporarse en CI con `-r junit`; consulta [Apidog CLI en GitHub Actions](https://apidog.com/es/blog/apidog-cli-github-actions?utm_source=dev.to&utm_medium=wanda&utm_content=n8n-post-automation). Para más detalles sobre la configuración del agente, consulta [Apidog CLI en Claude Code](https://apidog.com/es/blog/apidog-cli-in-claude-code?utm_source=dev.to&utm_medium=wanda&utm_content=n8n-post-automation), y para una estrategia integral de pruebas de webhooks, consulta [cómo probar webhooks](https://apidog.com/es/blog/how-to-test-webhooks?utm_source=dev.to&utm_medium=wanda&utm_content=n8n-post-automation). El plan Free de Apidog incluye equipos de hasta 4 usuarios. ## Antes de activar el webhook 1. Secreto configurado: una firma ausente o errónea devuelve un 401. 2. Respuesta 202 holgadamente por debajo de los 10 segundos y tarea del agente encolada. 3. IDs de entrega almacenados con una restricción de unicidad (unique constraint). 4. Un job periódico que reintenta las entregas fallidas de los últimos 3 días. Si prefieres recurrir a los runners propios de GitHub, [Claude Code GitHub Actions](https://apidog.com/es/blog/claude-code-github-actions?utm_source=dev.to&utm_medium=wanda&utm_content=n8n-post-automation) es la alternativa alojada; un endpoint de recepción por webhook añade las capas de filtrado y enrutamiento de hilos. Si necesitas gestionar reintentos por tu cuenta, consulta [cómo diseñar webhooks confiables](https://apidog.com/es/blog/how-to-design-reliable-webhooks?utm_source=dev.to&utm_medium=wanda&utm_content=n8n-post-automation). ## Preguntas frecuentes **¿Debería usar un webhook de repositorio o una GitHub App?** Un webhook a nivel de repositorio u organización resulta suficiente para un solo equipo. Una GitHub App proporciona al agente una identidad de bot propia, permisos más específicos e instalación en múltiples organizaciones. **¿Qué sucede si mi endpoint no está disponible?** GitHub registra la entrega como fallida y no la reintenta. Puedes reenviar las entregas de los últimos 3 días desde la configuración del webhook o mediante la API REST. **¿Cómo evito que el agente se responda a sí mismo?** Descarta en el filtro de la ruta rápida cualquier entrega cuyo `sender` sea la cuenta de tu bot, antes de ejecutar cualquier otro proceso. **¿Por qué devolver 202 en lugar de 200?** Ambos códigos se consideran respuestas exitosas para GitHub. Sin embargo, un 202 Accepted indica con claridad a cualquiera que revise los registros que el trabajo fue encolado y no finalizado. **¿El diseño del superagente de DeepSeek es algo que pueda activar de inmediato?** No. El artículo describe una arquitectura conceptual y su plugin prototipo no constituye un producto oficial de DeepSeek. La capa de disparadores debes construirla tú mismo, tal como se detalló anteriormente. 
