DEV Community

Cover image for Como Usar Webhooks do GitHub para Acionar Agentes de IA para Programação
Lucas
Lucas

Posted on Originally published at apidog.com

Como Usar Webhooks do GitHub para Acionar Agentes de IA para Programação

Como Usar Webhooks do GitHub para Acionar Agentes de IA para Programação

Para usar webhooks do GitHub para acionar agentes de código com IA, aponte um webhook do repositório para um endpoint de entrada que você controla, valide o cabeçalho X-Hub-Signature-256 em relação ao corpo bruto (raw body), responda com 202 dentro da janela de 10 segundos do GitHub e envie o evento para uma fila. Em seguida, um worker filtra o evento, mapeia-o para uma conversa (repositório mais número da PR) e inicializa ou alimenta o agente.

Experimente o Apidog hoje

O restante deste guia apresenta cada etapa em código e mostra como fazer seu agente de código testar o endpoint utilizando o Apidog CLI.

Por que acionar agentes de código com IA via webhooks do GitHub em vez de polling

Um gatilho por webhook é uma chamada HTTP que o GitHub faz ao seu servidor no exato momento em que algo acontece em um repositório: um comentário, uma revisão ou a conclusão de um fluxo de trabalho (workflow). O agente permanece inativo até que uma entrega chegue, consumindo zero tokens e zero chamadas de API enquanto nada estiver acontecendo, reagindo em segundos em vez de aguardar a próxima verificação.

Fazer polling a cada minuto desperdiça o limite de requisições (rate limit) com respostas vazias e ainda gera um atraso de até um minuto. Para uma explicação detalhada, consulte webhooks vs polling.

A equipe do DeepSeek Harness apresentou o mesmo argumento no artigo "Exploring Super-agent Design", publicado em 1º de novembro de 2026. Eles chamam essas entradas de Triggers (Gatilhos): o agente monitora eventos e fica inativo no restante do tempo. O artigo descreve uma arquitetura e um protótipo de plugin, e não um recurso nativo lançado pelo DeepSeek. Detalhamos o projeto completo em como criar um superagente; este artigo aborda especificamente a camada de gatilhos para qualquer agente de código.

Fluxo de um webhook do GitHub até um agente: um evento do GitHub chega a POST /triggers/github, que valida o cabeçalho X-Hub-Signature-256, deduplica o X-GitHub-Delivery e responde com 202 em menos de 10 segundos; em seguida, uma fila e um roteador de conversas enviam o evento para um agente já existente para aquela conversa ou inicializam um novo agente de código

Quais eventos de webhook do GitHub devem acionar um agente

Assine apenas eventos sobre os quais um membro humano da equipe agiria. Cada evento adicional significa uma entrega a mais para validar, armazenar e filtrar.

Evento Ação monitorada O que o agente faz
issue_comment created Responde a um comentário em uma issue ou na conversa de uma PR, como "@bot conserte o teste que está falhando"
pull_request_review_comment created Responde a um comentário em uma linha específica do diff
pull_request opened, synchronize Revisa uma nova PR ou faz uma nova revisão após um push
workflow_run completed com conclusion: failure Analisa os logs com falha e propõe uma correção
check_run completed com status de falha Mesma função descrita acima, mas para verificações reportadas por apps

Dois detalhes da documentação de eventos de webhook do GitHub podem poupar muito tempo de depuração. Primeiro: issue_comment é disparado tanto para comentários em issues quanto em pull requests; no caso de PRs, o evento inclui um objeto issue.pull_request, que permite diferenciá-los. Segundo: workflow_run com ação completed é disparado quer a execução tenha passado ou falhado; portanto, é fundamental verificar o campo workflow_run.conclusion manualmente.

O tamanho máximo dos payloads é de 25 MB; o GitHub nunca entrega nada maior que isso.

Valide a assinatura X-Hub-Signature-256 no corpo bruto da requisição

Ao configurar um segredo no webhook, o GitHub assina cada entrega usando HMAC SHA-256 calculado sobre o corpo bruto da requisição (raw body) e envia o hash hexadecimal no cabeçalho X-Hub-Signature-256: sha256=<digest>. Seu endpoint deve recalcular esse hash e comparar os dois valores em tempo constante.

Três regras essenciais do guia do GitHub sobre validação de entregas de webhooks:

  1. Calcule o hash sobre os bytes brutos, e não sobre um objeto JSON serializado novamente. Fazer o parse e converter de volta para string altera os espaços em branco e invalida a correspondência.
  2. Compare utilizando uma função de tempo constante, como o crypto.timingSafeEqual do Node, e nunca com o operador ==.
  3. Utilize X-Hub-Signature-256. O cabeçalho legado X-Hub-Signature usa SHA-1 e existe apenas para integrações antigas.

Veja a implementação do serviço de entrada em Node com 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);
Enter fullscreen mode Exit fullscreen mode

Esse manipulador executa apenas quatro operações leves, sem gargalos de processamento. Para conhecer os esquemas de assinatura adotados por outros provedores, consulte nosso artigo sobre verificação de assinatura de webhooks.

Responda 2xx em até 10 segundos e enfileire o trabalho do agente

As boas práticas para webhooks do GitHub determinam que seu servidor deve responder com um status 2xx dentro de 10 segundos. Se o tempo for excedido, o GitHub encerra a conexão e registra a entrega como falha.

Como a execução de um agente pode levar minutos, ela nunca deve ocorrer no ciclo da própria requisição. Envie o evento para uma fila (Redis, SQS, uma tabela no Postgres ou qualquer solução persistente) e retorne 202 Accepted imediatamente. Um worker dedicado fará a leitura da fila, aplicará os filtros necessários e iniciará o agente.

Tratar falhas é crucial: o GitHub não reenvia automaticamente entregas que falharam. É possível reenviá-las manualmente ou via API por até 3 dias; assim, um endpoint lento perderá silenciosamente o acionamento de um comentário a menos que alguém identifique o problema.

Filtre em dois estágios: caminho rápido em código e caminho detalhado com o modelo

A maioria das entregas nunca deveria chegar a um modelo de IA. O artigo da DeepSeek divide a filtragem em duas etapas: um caminho rápido (fast path) implementado em código e um caminho mais detalhado (slow path) onde um LLM valida diretrizes definidas em prompts. Essa separação garante que os custos fiquem atrelados a tarefas reais, e não ao ruído gerado no repositório.

Funil de filtragem em dois estágios: todas as entregas de webhook do GitHub passam por um caminho rápido com regras em código (repositório, remetente, allowlist de bots, menção obrigatória via @), descartando a maioria dos eventos sem chamadas ao modelo; os eventos restantes passam pela validação de diretrizes com LLM no caminho detalhado, descartando eventos não acionáveis antes de iniciar o agente

Caminho rápido (em código, roda em microssegundos):

  • Allowlist de repositórios: processe apenas os repositórios explicitamente autorizados.
  • Regras de remetente: ignore a própria conta do bot do agente para evitar loops infinitos onde ele responde a si mesmo.
  • Modo de menção: inicie uma execução somente se o comentário contiver @seu-bot. O artigo destaca três abordagens recomendadas: responder apenas a solicitações explícitas, encaminhar como candidato para a verificação detalhada ou simplesmente ignorar.

Caminho detalhado (com LLM, avalia os eventos restantes):

Envie ao modelo o texto do comentário acompanhado de uma instrução objetiva de diretriz, como: "Esta mensagem solicita alterações no código desta PR? Responda com 'sim' ou 'não' e uma breve justificativa em uma linha." O agente só é iniciado se a resposta for afirmativa. Isso descarta comentários como "obrigado @bot, ficou ótimo", que atendem à regra de menção, mas não demandam nenhuma ação.

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";
}
Enter fullscreen mode Exit fullscreen mode

Roteie mensagens seguintes pelo thread_id para manter o mesmo agente

Uma conversa (thread) corresponde à sequência de eventos que ocorrem em uma mesma PR. Crie o thread_id combinando o repositório com o número da PR ou issue, como no exemplo anterior: acme/api#42. Na arquitetura proposta pelo artigo, o worker criado no primeiro evento passa a monitorar essa conversa, permitindo que os eventos seguintes sejam encaminhados diretamente a ele sem a necessidade de uma nova etapa de roteamento.

Na prática, isso funciona como uma tabela de mapeamento entre o thread_id e o identificador de sessão do agente. Quando chega uma entrega associada a uma conversa com uma sessão ativa, o novo comentário é anexado a essa mesma sessão. Assim, o agente preserva seu contexto original — o diff analisado e os testes executados. Sem essa estrutura, três comentários em uma mesma PR poderiam gerar três agentes trabalhando simultaneamente e com respostas conflitantes.

O artigo traz outro detalhe importante: eventos que chegam enquanto o roteador ainda está processando uma etapa anterior são agrupados em lote para a próxima chamada, garantindo que uma sequência de cinco comentários resulte em apenas uma tomada de decisão, e não cinco.

Deduplique utilizando X-GitHub-Delivery

Cada entrega inclui um identificador exclusivo (GUID) no cabeçalho X-GitHub-Delivery. De acordo com a documentação do GitHub, os reenvios utilizam exatamente o mesmo identificador da entrega original, tornando esse valor a chave de idempotência perfeita. Armazene cada identificador (um índice único no banco de dados resolve isso) e trate repetições como operações neutras (no-op) retornando 2xx, evitando que o GitHub marque a tentativa como falha.

Essa abordagem também impede ataques de repetição (replay attacks): mesmo que a assinatura de uma requisição interceptada seja válida, o identificador já terá sido registrado previamente.

Deixe seu agente de código testar o endpoint de gatilho com o Apidog CLI

Não gaste tempo testando cálculos de assinatura manualmente. O próprio agente de código que desenvolveu o serviço de entrada pode escrever e executar os testes usando o Apidog CLI. Faça a configuração inicial:

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
Enter fullscreen mode Exit fullscreen mode

Em seguida, forneça um único prompt ao Claude Code, Codex ou Cursor:

In Apidog project <projectId>, 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:
1. valid X-Hub-Signature-256 -> 202 with trigger_id and a thread_id of "<repo>#<number>"
2. a second comment on the same PR -> same thread_id
3. bad signature -> 401
4. 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.
Enter fullscreen mode Exit fullscreen mode

O agente lê cada schema, valida os payloads correspondentes, cria os recursos necessários e executa os testes:

apidog cli-schema get endpoint-create
apidog cli-schema validate endpoint-create --file endpoint.json
apidog endpoint create --project <projectId> --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 <projectId> --file case-valid-signature.json
apidog run --test-case <caseId> --project <projectId> -e <stagingEnvId> -r cli,json
Enter fullscreen mode Exit fullscreen mode

O formatador cli exibe o status de sucesso ou falha para cada validação (assertion), enquanto o relatório json é salvo no diretório ./apidog-reports, permitindo que o agente identifique com precisão o que deu errado (receber 200 quando se esperava 401, por exemplo, costuma indicar a ausência do middleware para leitura do raw body).

O mesmo comando apidog run pode ser integrado ao pipeline de CI com o parâmetro -r junit; veja mais detalhes em Apidog CLI no GitHub Actions. Para aprender a configurar o agente, confira o guia sobre o Apidog CLI no Claude Code e, para estratégias mais completas de testes, veja como testar webhooks. O plano gratuito do Apidog atende equipes de até 4 usuários.

Checklist antes de ativar o webhook

  1. O segredo está configurado; assinaturas ausentes ou incorretas retornam status 401.
  2. A resposta 202 é enviada bem antes do limite de 10 segundos, com o processamento do agente devidamente enfileirado.
  3. Os identificadores de entrega são salvos com restrição de unicidade (unique constraint).
  4. Existe uma rotina para reprocessar entregas com falha dos últimos 3 dias.

Se você preferir utilizar o runner nativo do próprio GitHub, o caminho hospedado é o Claude Code GitHub Actions; a implementação de um endpoint de entrada dedicado adiciona o controle de filtragem e o roteamento de conversas. Para conferir estratégias de novas tentativas na sua aplicação, leia nosso artigo sobre como projetar webhooks confiáveis.

Perguntas Frequentes (FAQ)

Devo usar um webhook de repositório ou um GitHub App? Para um único time, um webhook configurado no repositório ou na organização é suficiente. Já um GitHub App fornece uma identidade de bot própria para o agente, permissões mais granulares e suporte a instalação em múltiplas organizações.

O que acontece se meu endpoint estiver fora do ar? O GitHub registrará a entrega como falha e não tentará o envio novamente de forma automática. Você poderá reenviar as entregas realizadas nos últimos 3 dias através das configurações do webhook ou pela API REST.

Como impedir que o agente responda às suas próprias mensagens? Descarte qualquer entrega cujo sender corresponda à conta do seu bot logo no filtro do caminho rápido, antes de qualquer outro processamento.

Por que retornar o status 202 em vez de 200? Para o GitHub, ambos são interpretados como sucesso. No entanto, o status 202 Accepted deixa claro para qualquer pessoa que analisar seus logs que a tarefa foi enfileirada, e não concluída.

A arquitetura de superagente da DeepSeek já está pronta para uso? Não. O artigo apresenta apenas um conceito de arquitetura, e o protótipo de plugin citado não é um produto oficial da DeepSeek. A camada de acionamento por gatilhos deve ser construída por você, seguindo o passo a passo demonstrado acima.

Top comments (0)