Um KI-Coding-Agents über GitHub-Webhooks auszulösen, leiten Sie einen Repository-Webhook an einen eigenen Intake-Endpunkt weiter, verifizieren den Header X-Hub-Signature-256 anhand des Raw-Bodys, antworten innerhalb des 10-Sekunden-Zeitfensters von GitHub mit 202 und übergeben das Event an eine Queue. Ein Worker filtert das Event anschließend, ordnet es einem Thread zu (Repository plus PR-Nummer) und startet oder versorgt den Agenten.
Der Rest dieser Anleitung zeigt jeden Schritt im Code und wie Sie Ihren Coding-Agenten den Endpunkt mit der Apidog CLI testen lassen.
Warum KI-Coding-Agents per GitHub-Webhook statt Polling ausgelöst werden sollten
Ein Webhook-Trigger ist ein HTTP-Aufruf, den GitHub genau in dem Moment an Ihren Server sendet, in dem in einem Repository etwas passiert: ein Kommentar, ein Review oder ein abgeschlossener Workflow. Ihr Agent schläft, bis ein Delivery eintrifft. Dadurch verbraucht er weder Tokens noch API-Aufrufe, solange nichts geschieht, und reagiert innerhalb von Sekunden statt erst beim nächsten Polling-Intervall.
Minütliches Polling verbraucht Rate-Limits für leere Antworten und hinkt dennoch um bis zu eine Minute hinterher. Die ausführliche Erklärung finden Sie unter webhooks vs polling.
Das Team von DeepSeek Harness vertrat dasselbe Argument in seinem Essay “Exploring Super-agent Design”, veröffentlicht am 1. November 2026. Sie nennen diese Inputs Triggers: Der Agent überwacht Events und bleibt ansonsten inaktiv. Der Essay beschreibt eine Architektur sowie ein Prototyp-Plugin und kein fertiges DeepSeek-Feature. Wir haben das gesamte Design in how to build a super-agent aufgeschlüsselt; dieser Beitrag baut lediglich die Trigger-Ebene auf – passend für jeden Coding-Agenten.

Welche GitHub-Webhook-Events einen Agenten starten sollten
Abonnieren Sie nur Events, bei denen auch ein menschliches Teammitglied aktiv werden würde. Jedes zusätzliche Event ist ein Delivery, das Sie verifizieren, speichern und filtern müssen.
| Event | Zu überwachende Aktion | Was der Agent tut |
|---|---|---|
issue_comment |
created |
Antwortet auf einen Kommentar in einem Issue oder einer PR-Konversation, zum Beispiel „@bot fix the failing test“ |
pull_request_review_comment |
created |
Reagiert auf einen Kommentar zu einer bestimmten Zeile im Diff |
pull_request |
opened, synchronize |
Prüft einen neuen PR oder führt nach einem Push ein erneutes Review durch |
workflow_run |
completed with conclusion: failure |
Liest die Fehlerprotokolle und schlägt einen Fix vor |
check_run |
completed with a failing conclusion |
Wie oben, für von Apps gemeldete Checks |
Zwei Details aus der GitHub webhook events reference ersparen Ihnen zeitraubendes Debugging: Erstens wird issue_comment sowohl bei Kommentaren zu Issues als auch zu Pull Requests ausgelöst. Ein PR-Kommentar enthält jedoch ein issue.pull_request-Objekt – daran lassen sich beide unterscheiden. Zweitens wird workflow_run mit der Action completed unabhängig davon ausgelöst, ob der Durchlauf erfolgreich war oder fehlgeschlagen ist. Sie müssen workflow_run.conclusion daher selbst prüfen.
Payloads sind auf maximal 25 MB begrenzt; GitHub liefert niemals größere Payloads aus.
Die X-Hub-Signature-256-Signatur anhand des Raw-Bodys verifizieren
Wenn Sie ein Secret für den Webhook hinterlegen, signiert GitHub jedes Delivery mit HMAC SHA-256 über den unformatierten Request-Body (Raw Body) und sendet den Hex-Digest als X-Hub-Signature-256: sha256=<digest>. Ihr Endpunkt berechnet den Digest neu und vergleicht beide Werte in konstanter Zeit.
Drei Regeln aus GitHubs Leitfaden zur validating webhook deliveries:
- Hashen Sie die Raw-Bytes und kein neu serialisiertes JSON-Objekt. Das Parsen und erneute Umwandeln in einen String verändert Whitespaces und führt zu abweichenden Hashes.
- Vergleichen Sie mit einer Constant-Time-Funktion wie Nodes
crypto.timingSafeEqual, niemals mit==. - Verwenden Sie
X-Hub-Signature-256. Der ältere HeaderX-Hub-Signaturebasiert auf SHA-1 und existiert nur noch für Legacy-Integrationen.
Hier ist der Intake-Service in Node mit Express:
import express from "express";
import crypto from "node:crypto";
const app = express();
const SECRET = process.env.GITHUB_WEBHOOK_SECRET;
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);
Der Handler führt vier leichtgewichtige Operationen aus und nichts, was blockiert oder lange dauert. Verschiedene Signaturverfahren anderer Anbieter finden Sie unter webhook signature verification.
Innerhalb von 10 Sekunden mit 2xx antworten und Agent-Aufgaben in die Queue einreihen
Gemäß GitHubs webhook best practices sollte Ihr Server innerhalb von 10 Sekunden mit einem 2xx-Statuscode antworten. Dauert es länger, trennt GitHub die Verbindung und stuft das Delivery als fehlgeschlagen ein.
Ein Durchlauf des Agenten dauert Minuten und kann daher niemals synchron innerhalb des Requests stattfinden. Übergeben Sie das Event an eine Queue (Redis, SQS, eine Postgres-Tabelle oder eine andere persistente Lösung) und geben Sie sofort 202 Accepted zurück. Ein separater Worker-Prozess liest die Events aus der Queue, wendet die Filter an und startet den Agenten.
Fehlgeschlagene Deliveries fallen ins Gewicht: GitHub stellt sie nicht automatisch erneut zu. Sie können sie bis zu 3 Tage lang manuell oder über die API redeliver them. Ein zu langsamer Handler führt daher dazu, dass der Trigger eines Kommentars unbemerkt verloren geht, sofern es niemandem auffällt.
Zweistufiges Filtern: Fast-Path im Code, Slow-Path über das Modell
Die meisten Deliveries sollten das Modell gar nicht erst erreichen. Der DeepSeek-Essay teilt die Filterung in einen Fast-Path im Code und einen Slow-Path auf, bei dem ein LLM als Prompts formulierte Richtlinien anwendet. Diese Trennung sorgt dafür, dass Kosten nur für echte Arbeit und nicht für herkömmliches Repository-Rauschen anfallen.

Fast-Path (Code, läuft in Mikrosekunden):
- Repository-Allowlist: Nur freigegebene Repositories verarbeiten.
- Sender-Regeln: Den eigenen Bot-Account des Agenten ignorieren – andernfalls entsteht eine Endlosschleife, in der er auf seine eigenen Nachrichten antwortet.
- Mention-Modus: Einen Durchlauf nur starten, wenn der Kommentar
@your-botenthält. Der Essay nennt drei empfehlenswerte Modi: nur auf explizite Anfragen antworten, als Kandidaten für den Slow-Path behandeln oder ignorieren.
Slow-Path (LLM, verarbeitet die verbleibenden Events):
Übergeben Sie dem Modell den Kommentartext zusammen mit einem kurzen Policy-Prompt wie: „Handelt es sich hierbei um eine Aufforderung, Code in diesem PR zu ändern? Antworte mit Ja oder Nein und einer einzeiligen Begründung.“ Nur ein „Ja“ startet den Agenten. So werden Kommentare wie „Danke @bot, sieht gut aus“ herausgefiltert, die zwar die Mention-Regel erfüllen, aber keine Aktion erfordern.
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";
}
Folge-Events per Thread-ID routen, damit derselbe Agent antwortet
Ein Thread bezeichnet die Abfolge zusammenhängender Events zu einem PR. Bilden Sie die thread_id aus dem Repository und der PR- oder Issue-Nummer, wie im obigen Handler mit acme/api#42 gezeigt. Im Konzept des Essays abonniert der für das erste Event erstellte Worker seinen Thread, und nachfolgende Events werden ohne weiteren Routing-Aufruf direkt an ihn weitergeleitet.
In der Praxis entspricht dies einer Lookup-Tabelle von der thread_id zur Session-ID des Agenten. Trifft ein Delivery für einen Thread mit aktiver Session ein, wird der Kommentar an diese Session angehängt. So behält der Agent seinen Kontext: das gelesene Diff, die ausgeführten Tests. Ohne diesen Mechanismus würden drei Kommentare zu einem PR drei verschiedene Agenten instanziieren, die sich gegenseitig widersprechen.
Der Essay liefert noch ein weiteres nützliches Detail: Trigger, die eintreffen, während der Router gerade eine Verarbeitung durchführt, werden für den nächsten Aufruf gebündelt (gebatcht). So erfordert eine Welle von fünf Kommentaren nur eine einzige Entscheidung statt fünf.
Deduplizierung über X-GitHub-Delivery
Jedes Delivery enthält eine GUID im Header X-GitHub-Delivery. Laut GitHub-Dokumentation verwendet eine erneute Zustellung dieselbe ID wie das Original, was sie zum perfekten Idempotenz-Schlüssel macht. Speichern Sie jede ID (beispielsweise über einen Unique-Index in Ihrer Datenbank) und behandeln Sie Wiederholungen als No-Op, der dennoch mit 2xx antwortet, damit GitHub die Zustellung nicht als fehlgeschlagen wertet.
Zudem werden so Replay-Angriffe verhindert: Die Signatur eines abgefangenen Deliveries wäre zwar gültig, die ID ist jedoch bereits gespeichert.
Den Trigger-Endpunkt vom Coding-Agenten mit der Apidog CLI testen lassen
Die Signaturberechnung sollten Sie nicht manuell testen. Lassen Sie den Coding-Agenten, der den Intake-Service geschrieben hat, auch die passenden Tests verfassen und mit der Apidog CLI ausführen. Die einmalige Einrichtung:
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
Geben Sie Claude Code, Codex oder Cursor anschließend folgenden Prompt:
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.
Der Agent liest jedes Schema, validiert die Payload, erstellt die Ressourcen und führt sie aus:
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
Der cli-Reporter gibt für jedes Assertion das Ergebnis (Pass/Fail) aus, und der json-Report wird unter ./apidog-reports abgelegt. So erkennt der Agent sofort, welche Prüfung fehlgeschlagen ist (ein Status 200 statt des erwarteten 401 weist in der Regel darauf hin, dass die Middleware für den Raw-Body fehlt).
Derselbe Befehl apidog run lässt sich mit -r junit in Ihre CI integrieren; siehe Apidog CLI in GitHub Actions. Weitere Details zur Agent-Einrichtung finden Sie unter Apidog CLI in Claude Code und zu übergreifenden Strategien für Webhook-Tests unter how to test webhooks. Der Free-Tarif von Apidog deckt Teams mit bis zu 4 Benutzern ab.
Bevor Sie den Webhook aktivieren
- Secret ist gesetzt; eine fehlende oder falsche Signatur liefert den Status 401.
- 202-Antwort in deutlich unter 10 Sekunden; Agent-Aufgaben werden in die Queue gestellt.
- Delivery-IDs werden mit einem Unique-Constraint gespeichert.
- Ein Job stellt fehlgeschlagene Deliveries der letzten 3 Tage erneut zu.
Wenn Sie lieber GitHubs eigene Runner nutzen möchten, ist Claude Code GitHub Actions der gehostete Weg; ein eigener Webhook-Intake bietet zusätzlich Filterung und Thread-Routing. Wie Sie Retries auf Ihrer Seite handhaben, erfahren Sie unter how to design reliable webhooks.
FAQ
Sollte ich einen Repository-Webhook oder eine GitHub App verwenden? Ein Repository- oder Organisations-Webhook reicht für ein einzelnes Team völlig aus. Eine GitHub App verleiht dem Agenten eine eigene Bot-Identität, präzisere Berechtigungen und die Möglichkeit zur Installation über mehrere Organisationen hinweg.
Was passiert, wenn mein Endpunkt nicht erreichbar ist? GitHub markiert das Delivery als fehlgeschlagen und unternimmt keinen automatischen Wiederholungsversuch. Sie können Deliveries der letzten 3 Tage über die Webhook-Einstellungen oder die REST-API erneut auslösen.
Wie verhindere ich, dass der Agent sich selbst antwortet? Verwerfen Sie im Fast-Path-Filter jedes Delivery, dessen sender Ihr Bot-Account ist, bevor nachgelagerte Logik ausgeführt wird.
Warum sollte man 202 statt 200 zurückgeben? Für GitHub gelten beide Statuscodes als Erfolg. 202 Accepted signalisiert jedoch jedem, der die Logs liest, dass die Aufgabe in die Queue eingereiht und noch nicht abgeschlossen wurde.
Ist das Super-Agent-Design von DeepSeek eine Funktion, die man einfach aktivieren kann? Nein. Der Essay beschreibt eine Architektur, und das dort erwähnte Prototyp-Plugin ist kein offizielles DeepSeek-Produkt. Die Trigger-Ebene bauen Sie selbst auf – genau wie oben beschrieben.
