GitHub Webhook'ları ile Yapay Zeka Kodlama Ajanları Nasıl Tetiklenir?

Yapay zekâ kodlama ajanlarını tetiklemek için GitHub webhook'larını kullanın: X-Hub-Signature-256'yı doğrulayın, 10 saniye içinde 202 yanıtı verin, iki aşamada filtreleyin, thread'e göre yönlendirin ve teslimatları tekilleştirin.

Ashley Innocent

Ashley Innocent

5 November 2026

GitHub Webhook'ları ile Yapay Zeka Kodlama Ajanları Nasıl Tetiklenir?

Kurumsal İçin Apidog

Şirket İçi (On-Premises) Dağıtım

SSO ve RBAC

SOC 2 Uyumlu

Apidog Enterprise'ı Keşfedin

GitHub webhook'larını kullanarak yapay zekâ kodlama ajanlarını tetiklemek için bir depo (repository) webhook'unu kontrolünüzdeki bir giriş uç noktasına (intake endpoint) yönlendirin, X-Hub-Signature-256 üstbilgisini ham gövde (raw body) üzerinden doğrulayın, GitHub'ın 10 saniyelik zaman aşımı süresi içinde 202 yanıtı verin ve olayı bir kuyruğa ekleyin. Ardından bir arka plan işçisi (worker) olayı filtreler, bunu ilgili ileti dizisiyle (depo ve PR numarası) eşleştirir ve ajanı başlatır ya da besler.

Bu rehberin geri kalanında her adımı kod örnekleriyle inceleyecek ve kodlama ajanınızın uç noktayı Apidog CLI ile nasıl test edebileceğini göstereceğiz.

Yapay zekâ kodlama ajanları yoklama (polling) yerine neden GitHub webhook'ları ile tetiklenmeli?

Webhook tetikleyicisi, depoda bir şey gerçekleştiğinde (bir yorum, bir inceleme veya tamamlanan bir iş akışı) GitHub'ın sunucunuza yaptığı bir HTTP çağrısıdır. Ajanınız yeni bir teslimat (delivery) gelene kadar uyku modunda kalır; böylece hiçbir hareketlilik yokken sıfır token harcar, sıfır API çağrısı yapar ve bir sonraki yoklamayı (poll) beklemek yerine saniyeler içinde tepki verir.

Her dakika yoklama yapmak (polling), boş yanıtlar yüzünden hız sınırlarını (rate limit) tüketir ve buna rağmen bir dakikaya varan gecikmelere yol açar. Konunun ayrıntılı açıklamasına webhooks vs polling yazımızdan ulaşabilirsiniz.

DeepSeek Harness ekibi de 1 Kasım 2026'da yayımladıkları “Exploring Super-agent Design” başlıklı makalelerinde aynı argümanı öne sürdü. Bu girdileri Tetikleyici (Trigger) olarak adlandırıyorlar: ajan olayları dinler ve bunun dışında sessiz kalır. Makale, kullanıma sunulmuş bir DeepSeek özelliğini değil, bir mimariyi ve prototip bir eklentiyi anlatıyor. Tasarımın tamamını how to build a super-agent yazımızda ayrıntılarıyla ele almıştık; bu yazıda ise herhangi bir kodlama ajanı için yalnızca tetikleyici katmanını oluşturuyoruz.

Flow of a GitHub webhook into an agent: a GitHub event reaches POST /triggers/github, which verifies X-Hub-Signature-256, dedupes X-GitHub-Delivery and replies 202 in under 10 seconds, then a queue and a thread router send it to an existing agent for that thread or a new coding agent

Bir ajanı hangi GitHub webhook olayları başlatmalı?

Yalnızca bir ekip arkadaşınızın harekete geçmesini bekleyeceğiniz olaylara abone olun. Her fazladan olay; doğrulamanız, saklamanız ve filtrelemeniz gereken ekstra bir teslimat demektir.

Olay İzlenecek eylem Ajanın yaptığı işlem
issue_comment created Bir issue veya PR tartışmasındaki yoruma yanıt verir (örneğin: “@bot fix the failing test”)
pull_request_review_comment created Diff üzerindeki belirli bir satıra yapılan yoruma yanıt verir
pull_request opened, synchronize Yeni bir PR'ı inceler veya yeni bir push sonrasında yeniden inceleme yapar
workflow_run conclusion: failure ile completed Başarısız olan logları okur ve bir düzeltme önerir
check_run Başarısız bir conclusion ile completed Yukarıdakiyle aynı, uygulamalar (GitHub Apps) tarafından bildirilen kontroller için geçerlidir

GitHub webhook olayları referans kılavuzundaki iki ayrıntı sizi hata ayıklama (debugging) zahmetinden kurtarır. İlki, issue_comment olayı hem issue hem de pull request yorumlarında tetiklenir; PR yorumları bir issue.pull_request nesnesi içerir ve ikisini birbirinden bu şekilde ayırt edebilirsiniz. İkincisi, eylemi completed olan workflow_run, çalıştırma başarılı da olsa başarısız da olsa tetiklenir; bu nedenle workflow_run.conclusion değerini kendiniz kontrol etmelisiniz.

İstek yükleri (payload) en fazla 25 MB ile sınırlandırılmıştır; GitHub bundan daha büyük hiçbir şeyi teslim etmez.

Ham gövde üzerindeki X-Hub-Signature-256 imzasını doğrulama

Webhook için bir gizli anahtar (secret) belirlediğinizde GitHub, ham istek gövdesinin HMAC SHA-256 özetini alarak her teslimatı imzalar ve onaltılık (hex) özeti X-Hub-Signature-256: sha256=<digest> olarak gönderir. Uç noktanız bu özeti yeniden hesaplar ve ikisini sabit zamanda (constant-time) karşılaştırır.

GitHub'ın webhook teslimatlarını doğrulama rehberinden üç temel kural:

  1. Yeniden serileştirilmiş bir JSON nesnesini değil, ham baytları hash'leyin. JSON'ı ayrıştırıp (parse) tekrar dizeye dönüştürmek boşluk karakterlerini değiştirir ve eşleşmeyi bozar.
  2. Asla == kullanmayın; Node'un crypto.timingSafeEqual fonksiyonu gibi sabit zamanlı (constant-time) bir fonksiyonla karşılaştırın.
  3. X-Hub-Signature-256 üstbilgisini kullanın. Daha eski olan X-Hub-Signature üstbilgisi SHA-1 kullanır ve yalnızca eski entegrasyonlar için mevcuttur.

İşte Express ile Node'da hazırlanmış giriş servisi:

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);

İşleyici (handler) yalnızca dört hafif işlem yürütür ve yavaş hiçbir şey yapmaz. Farklı sağlayıcıların imza şemaları için webhook signature verification başlıklı yazımıza göz atabilirsiniz.

10 saniye içinde 2xx yanıtı dönün ve ajan işini kuyruğa alın

GitHub'ın webhook en iyi uygulamaları rehberi, sunucunuzun 10 saniye içinde bir 2xx yanıtı vermesi gerektiğini belirtir. Bu sürenin aşılması durumunda GitHub bağlantıyı sonlandırır ve teslimatı başarısız olarak kaydeder.

Bir ajanın çalışması dakikalar sürer, bu nedenle bu işlem asla gelen isteğin içinde gerçekleştirilemez. Olayı bir kuyruğa (Redis, SQS, bir Postgres tablosu veya kalıcı herhangi bir yapı) ekleyin ve hemen 202 Accepted yanıtı dönün. Ayrı bir worker işlemi kuyruktan veriyi çeker, filtreleri çalıştırır ve ajanı başlatır.

Başarısızlıklar önemlidir: GitHub başarısız olan teslimatları otomatik olarak yeniden göndermez. Bu teslimatları 3 güne kadar manuel olarak veya API aracılığıyla yeniden gönderebilirsiniz; dolayısıyla yavaş çalışan bir işleyici, birisi fark etmediği sürece o yoruma ait tetikleyiciyi sessizce kaybeder.

İki aşamalı filtreleme: Kodla hızlı yol, modelle yavaş yol

Gelen teslimatların çoğunun bir modele asla ulaşmaması gerekir. DeepSeek makalesi filtrelemeyi ikiye ayırır: kodla yazılmış bir hızlı yol (fast path) ve bir LLM'in prompt olarak yazılmış kuralları uyguladığı yavaş yol (slow path). Bu ayrım, maliyetlerin depo gürültüsü yerine gerçek iş yüküne bağlı kalmasını sağlar.

Two-stage filter funnel: all GitHub webhook deliveries pass a fast path of code rules (repo, sender, bot allowlist, @mention required), which drops most events with no model call; the rest pass a slow-path LLM policy check that drops non-actionable events before an agent run starts

Hızlı yol (kod, mikrosaniyeler içinde çalışır):

Yavaş yol (LLM, ilk aşamayı geçenler üzerinde çalışır):

Modele yorum metnini ve kısa bir kural istemi (prompt) verin; örneğin: “Bu, bu PR'daki kodu değiştirme talebi midir? Evet veya hayır ve tek satırlık bir gerekçe ile yanıtlayın.” Yalnızca “evet” yanıtı ajanı başlatır. Bu yaklaşım, bahsetme kuralını geçen ancak herhangi bir işlem gerektirmeyen “teşekkürler @bot, harika görünüyor” gibi yorumları yakalar.

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";
}

Aynı ajanın yanıt vermesi için devam mesajlarını ileti dizisi kimliğine (thread_id) göre yönlendirin

İleti dizisi (thread), tek bir PR üzerindeki ardışık olaylar zinciridir. Yukarıdaki işleyicinin acme/api#42 örneğinde yaptığı gibi, thread_id değerini depo adı ile PR veya issue numarasından oluşturun. Makaledeki tasarımda, ilk olay için oluşturulan işçi (worker) bu ileti dizisine abone olur ve devamındaki olaylar başka bir yönlendirme çağrısına gerek kalmadan doğrudan bu işçiye iletilir.

Pratikte bu, thread_id değerinden ajan oturum kimliğine (session id) eşleme yapan bir arama tablosudur (lookup table). Aktif oturumu olan bir ileti dizisi için teslimat geldiğinde, yorumu o oturuma ekleyin. Böylece ajan bağlamını (okuduğu diff, çalıştırdığı test) korur. Bu yapı olmadan, tek bir PR'daki üç ayrı yorum birbiriyle çelişen üç farklı ajanın başlatılmasına neden olur.

Makale, örnek alınmaya değer bir ayrıntı daha ekliyor: Yönlendirici henüz işlem yaparken gelen tetikleyiciler bir sonraki çağrıda toplu olarak (batch) işlenir; böylece art arda gelen beş yorum beş ayrı karar yerine tek bir karar maliyeti yaratır.

X-GitHub-Delivery ile tekilleştirme

Her teslimat bir X-GitHub-Delivery GUID değeri taşır. GitHub belgeleri, yeniden iletilen teslimatların orijinal teslimatla aynı değeri kullandığını belirtir; bu da onu mükemmel bir benzersizlik anahtarı (idempotency key) yapar. Her kimliği saklayın (veritabanınızdaki benzersiz bir dizin işe yarar) ve tekrarlanan istekleri yine de 2xx döndüren etkisiz bir işlem (no-op) olarak ele alın, böylece GitHub bunu başarısız olarak işaretlemez.

Bu yöntem ayrıca yeniden oynatma saldırılarını (replay attacks) da engeller: Ele geçirilen bir teslimatın imzası geçerli görünse bile kimliği zaten saklanmış durumdadır.

Tetikleyici uç noktasını kodlama ajanınızın Apidog CLI ile test etmesini sağlayın

İmza hesaplama mantığını manuel olarak test etmemelisiniz. Giriş servisini yazan kodlama ajanının, testlerini de yazmasını ve Apidog CLI ile çalıştırmasını sağlayın. Kurulumu bir kez yapmanız yeterlidir:

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

Ardından Claude Code, Codex veya Cursor'a tek bir komut verin:

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.

Ajan her şemayı okur, veri yükünü doğrular, kaynakları oluşturur ve bunları çalıştırır:

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

cli raporlayıcısı her doğrulama (assertion) için başarılı veya başarısız durumunu yazdırır ve json raporu ./apidog-reports dizinine kaydedilir; böylece ajan hangi denetimin başarısız olduğunu görür (401 beklediğiniz yerde 200 dönmesi genellikle raw-body ara yazılımının eksik olduğu anlamına gelir).

Aynı apidog run komut satırı -r junit ile CI ortamına eklenebilir; bkz. Apidog CLI in GitHub Actions. Ajan kurulumu hakkında daha fazla bilgi için Apidog CLI in Claude Code yazısını, daha kapsamlı webhook test stratejileri için ise how to test webhooks rehberini okuyabilirsiniz. Apidog'un Ücretsiz planı 4 kullanıcıya kadar olan ekipleri kapsar.

Webhook'u etkinleştirmeden önce

  1. Gizli anahtar (secret) belirlendi; eksik veya hatalı imza 401 alır.
  2. 10 saniyenin oldukça altında 202 yanıtı dönülür, ajan işi kuyruğa alınır.
  3. Teslimat kimlikleri benzersizlik kısıtlamasıyla (unique constraint) saklanır.
  4. Son 3 güne ait başarısız teslimatları yeniden yürüten bir iş (job) yapılandırıldı.

GitHub'ın kendi çalıştırıcısını (runner) kullanmayı tercih ediyorsanız Claude Code GitHub Actions barındırılan (hosted) bir alternatiftir; webhook giriş katmanı ise filtreleme ve ileti dizisi yönlendirmesi kazandırır. Kendi tarafınızdaki yeniden denemeler için how to design reliable webhooks kılavuzuna göz atabilirsiniz.

button

SSS

Depo webhook'u mu yoksa GitHub App mi kullanmalıyım? Tek bir ekip için bir depo veya organizasyon webhook'u yeterlidir. Bir GitHub App ise ajana kendi bot kimliğini, daha ayrıntılı izinleri ve birçok organizasyona yüklenebilme imkânını sağlar.

Uç noktam çökerse ne olur? GitHub teslimatı başarısız olarak kaydeder ve yeniden denemez. Son 3 güne ait teslimatları webhook ayarlarından veya REST API aracılığıyla yeniden gönderebilirsiniz.

Ajanın kendi kendine yanıt vermesini nasıl engellerim? Başka hiçbir şey çalışmadan önce, hızlı yol filtresinde sender değeri bot hesabınız olan tüm teslimatları eleyin.

Neden 200 yerine 202 dönülmeli? Her ikisi de GitHub için başarılı kabul edilir. 202 Accepted, günlüklerinizi (logs) okuyan herkese işin tamamlanmadığını, kuyruğa alındığını belirtir.

DeepSeek süper ajan tasarımı hemen etkinleştirebileceğim bir şey mi? Hayır. Makale bir mimariyi anlatmaktadır ve prototip eklentisi resmi bir DeepSeek ürünü değildir. Tetikleyici katmanını yukarıda gösterildiği gibi kendiniz inşa edersiniz.

API Tasarım-Öncelikli Yaklaşımı Apidog'da Uygulayın

API'leri oluşturmanın ve kullanmanın daha kolay yolunu keşfedin