كيفية استخدام GitHub Webhooks لتشغيل وكلاء البرمجة بالذكاء الاصطناعي

استخدم GitHub webhooks لتشغيل وكلاء البرمجة بالذكاء الاصطناعي: تحقّق من X-Hub-Signature-256، ورُدّ برمز 202 خلال 10 ثوانٍ، ونفّذ التصفية على مرحلتين، ووجّه المهام بحسب تسلسل المحادثات، واستبعد الإرساليات المكررة.

Ashley Innocent

Ashley Innocent

5 نوفمبر 2026

كيفية استخدام GitHub Webhooks لتشغيل وكلاء البرمجة بالذكاء الاصطناعي

Apidog للمؤسسات

النشر على الخوادم المحلية

SSO و RBAC

متوافق مع SOC 2

استكشف Apidog للمؤسسات

لاستخدام خطافات الويب (Webhooks) في GitHub لتشغيل وكلاء البرمجة بالذكاء الاصطناعي، وجِّه خطاف الويب في المستودع إلى نقطة نهاية استقبال (Intake endpoint) تملكها، وتحقق من ترويسة X-Hub-Signature-256 بمقارنتها بنص الطلب الخام (Raw body)، ثم أرسل استجابة بالرمز 202 ضمن مهلة الـ 10 ثوانٍ المحددة من GitHub، وأدرج الحدث في طابور انتظار (Queue). بعد ذلك، يتولى عامل معالجة (Worker) تصفية الحدث وربطه بسلسلة محادثات (المستودع متبوعًا برقم طلب السحب)، ثم يبدأ تشغيل الوكيل أو تزويده بالبيانات.

يوضح بقية هذا الدليل كل خطوة برمجيًا، وكيفية جعل وكيل البرمجة يختبر نقطة النهاية باستخدام Apidog CLI.

لماذا يُفضَّل تشغيل وكلاء البرمجة بالذكاء الاصطناعي عبر خطافات الويب بدلاً من الاستقصاء الدوري؟

يُعد مُشغِّل خطاف الويب (Webhook trigger) استدعاء HTTP يُرسله GitHub إلى خادمك فور وقوع حدثٍ ما في المستودع: كإضافة تعليق، أو تقديم مراجعة، أو اكتمال سير عمل (Workflow). يظل وكيلك في حالة خمول حتى يصل إشعار الاستلام، فلا يستهلك أي رموز (Tokens) أو استدعاءات لواجهة برمجة التطبيقات (API calls) في حال عدم وجود أي نشاط، كما يستجيب خلال ثوانٍ معدودة بدلاً من الانتظار حتى دورة الاستقصاء التالية.

أما الاستقصاء الدوري (Polling) كل دقيقة، فيستنزف حدود معدل الطلبات (Rate limit) بردود فارغة، ومع ذلك يظل متأخرًا بمدة تصل إلى دقيقة كاملة. يمكنك الاطلاع على التفاصيل الموسعة في مقال webhooks vs polling.

طرح فريق DeepSeek Harness الحجة نفسها في مقالهم “Exploring Super-agent Design” المنشور في 1 نوفمبر 2026؛ حيث أطلقوا على هذه المدخلات اسم المُشغِّلات (Triggers): يراقب الوكيل الأحداث ويبقى ساكنًا فيما عدا ذلك. يصف المقال بنية معمارية ونموذجًا أوليًا لإضافة، وليس ميزة تم إطلاقها رسميًا في DeepSeek. وقد قمنا بتفصيل التصميم الكامل في مقال how to build a super-agent؛ أما هذا المقال فيركز فقط على بناء طبقة المُشغِّلات لأي وكيل برمجة.

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

ما هي أحداث خطافات الويب في GitHub التي ينبغي أن تُشغِّل الوكيل؟

اشترك فقط في الأحداث التي يتوقع أي شخص من زميله في الفريق اتخاذ إجراء بشأنها؛ فكل حدث إضافي يمثل إشعارًا يتعين عليك التحقق منه وتخزينه وتصفيته.

الحدث الإجراء المُراد مراقبته ما يقوم به الوكيل
issue_comment created يجيب على تعليق في مسألة (Issue) أو في محادثة طلب سحب (PR)، على سبيل المثال: “@bot fix the failing test”
pull_request_review_comment created يستجيب لتعليق على سطر محدد في الفروقات البرمجية (diff)
pull_request opened, synchronize يراجع طلب سحب جديدًا أو يعيد المراجعة بعد دفع تعديلات جديدة (push)
workflow_run completed مع conclusion: failure يقرأ سجلات الفشل ويقترح حلاً للمشكلة
check_run completed مع نتيجة تشير إلى الفشل الأمر نفسه كما أعلاه، ولكن لعمليات الفحص التي تُبلغ عنها التطبيقات

هناك تفصيلتان من مرجع أحداث خطافات الويب في GitHub ستوفران عليك الكثير من وقت تصحيح الأخطاء: أولاً، يُطلَق الحدث issue_comment للتعليقات على كلٍّ من المسائل وطلبات السحب؛ ويحتوي تعليق طلب السحب على الكائن issue.pull_request، وهو ما يُمكّنك من التمييز بينهما. ثانياً، يُطلَق الحدث workflow_run بالإجراء completed سواء نجح التشغيل أو فشل، لذا يجب عليك التحقق من workflow_run.conclusion بنفسك.

يبلغ الحد الأقصى لحجم حمولة البيانات (Payload) 25 ميغابايت؛ ولا يُرسل GitHub أي حمولة تتجاوز ذلك إطلاقًا.

التحقق من توقيع X-Hub-Signature-256 على نص الطلب الخام

عند تعيين سر (Secret) لخطاف الويب، يوقع GitHub كل عملية تسليم باستخدام HMAC SHA-256 لنص الطلب الخام، ويُرسل الخلاصة الست عشرية كالتالي: X-Hub-Signature-256: sha256=<digest>. تقوم نقطة النهاية لديك بإعادة حساب الخلاصة ومقارنة القيمتين في وقت ثابت (Constant time).

ثلاث قواعد أساسية من دليل GitHub حول التحقق من عمليات تسليم خطافات الويب:

  1. احسب تجزئة البايتات الخام (Raw bytes)، وليس كائن JSON بعد إعادة تسلسله؛ حيث تؤدي إعادة التحويل إلى نص إلى تغيير المسافات البيضاء وبالتالي فشل التطابق.
  2. قارن باستخدام دالة تعمل في وقت ثابت مثل دالة crypto.timingSafeEqual في Node، وتجنب استخدام == تمامًا.
  3. استخدم الترويسة X-Hub-Signature-256؛ فالترويسة الأقدم X-Hub-Signature تعتمد على SHA-1 ومخصصة فقط للتكاملات القديمة.

إليك خدمة الاستقبال باستخدام Node مع 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);

تقوم دالة المعالجة بأربع مهام بسيطة وسريعة ولا تستهلك أي وقت إضافي. للاطلاع على مخططات التوقيع المتبعة لدى مختلف المزودين، راجع webhook signature verification.

الرد برمز 2xx خلال 10 ثوانٍ وإدراج مهام الوكيل في طابور انتظار

تنص أفضل ممارسات خطافات الويب في GitHub على ضرورة استجابة خادمك برمز 2xx خلال 10 ثوانٍ؛ وإذا استغرق وقتًا أطول، ينهي GitHub الاتصال ويُسجل عملية التسليم كفاشلة.

تستغرق دورة عمل الوكيل عدة دقائق، لذا لا يمكن تنفيذها إطلاقًا أثناء معالجة الطلب نفسه. أضِف الحدث إلى طابور انتظار (مثل Redis أو SQS أو جدول في Postgres أو أي حل دائم)، وأرجع الرمز 202 Accepted على الفور. بعد ذلك، تتولى عملية معالجة (Worker process) منفصلة سحب الأحداث من الطابور وتطبيق التصفية وبدء تشغيل الوكيل.

حالات الفشل مهمة للغاية؛ حيث إن GitHub لا يعيد محاولة تسليم الطلبات الفاشلة تلقائيًا. يمكنك إعادة تسليمها يدويًا أو عبر واجهة برمجة التطبيقات (API) لمدة تصل إلى 3 أيام، ولهذا فإن دالة المعالجة البطيئة ستتسبب في فقدان مُشغِّل هذا التعليق بصمت ما لم ينتبه أحد للأمر.

التصفية على مرحلتين: مسار سريع برمجيًا ومسار بطيء باستخدام النموذج

ينبغي ألا يصل معظم ما يُسلَّم إلى النموذج على الإطلاق. يقسم مقال DeepSeek عملية التصفية إلى مسار سريع مكتوب بالكود، ومسار بطيء يطبق فيه نموذج لغوي كبير (LLM) سياسات مكتوبة كمطالبات (Prompts). يضمن هذا التقسيم ربط التكاليف بالعمل الحقيقي فقط بدلاً من استنزافها في ضوضاء المستودع.

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

المسار السريع (برمجيًا، يستغرق ميكروثانية):

المسار البطيء (عبر النموذج اللغوي، يعمل على ما يتجاوز التصفية الأولى):

مرِّر للنموذج نص التعليق مع مطالبة سياسة قصيرة، مثل: "هل هذا طلب لتعديل الكود في طلب السحب هذا؟ أجب بنعم أو لا مع ذكر السبب في سطر واحد". الإجابة بـ "نعم" وحدها هي التي تُشغِّل الوكيل. يتيح ذلك استبعاد تعليقات مثل "thanks @bot, looks good"، والتي تجتاز شرط الإشارة بالاسم لكنها لا تتطلب أي إجراء فعلي.

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

توجيه المتابعات عبر معرّف السلسلة لضمان استجابة الوكيل نفسه

تُمثل سلسلة المحادثة (Thread) تتابع الأحداث المتتالية لطلب سحب واحد. قم ببناء thread_id من اسم المستودع ورقم طلب السحب أو المسألة، تمامًا كما تفعل دالة المعالجة أعلاه مع acme/api#42. وفقًا لتصميم المقال، يشترك عامل المعالجة المُنشأ للحدث الأول في سلسلته الخاصة، وتُوجَّه أحداث المتابعة إليه مباشرة دون الحاجة إلى عملية توجيه إضافية.

عمليًا، يتم ذلك عبر جدول بحث يربط thread_id بمعرّف جلسة الوكيل (Agent session id). وعندما يصل إشعار يخص سلسلة محادثات لها جلسة نشطة، ألحق التعليق بتلك الجلسة؛ مما يتيح للوكيل الاحتفاظ بسياقه السابق: الفروقات البرمجية التي قرأها، والاختبارات التي نفذها. وبدون هذا الإجراء، ستؤدي ثلاثة تعليقات على طلب سحب واحد إلى إنشاء ثلاثة وكلاء قد تتناقض إجراءاتهم.

ويضيف المقال تفصيلة إضافية جديرة بالاهتمام: يتم تجميع المُشغِّلات التي تصل أثناء انشغال الموجّه في دورة عمل، لتعالَج دفعة واحدة في استدعائه التالي؛ وبذلك تكلف موجة مفاجئة من خمسة تعليقات قرارًا واحدًا بدلاً من خمسة قرارات منفصلة.

منع التكرار باستخدام معرّف X-GitHub-Delivery

تحمل كل عملية تسليم معرّف GUID خاص في الترويسة X-GitHub-Delivery. وتوضح وثائق GitHub أن إعادة التسليم تستخدم نفس القيمة الأصلية، مما يجعلها مفتاح التحقق من عدم التكرار (Idempotency key) المثالي. قم بتخزين كل معرّف (عبر فهرس فريد في قاعدة بياناتك مثلاً)، وتعامل مع الطلبات المكررة على أنها عمليات بلا تأثير (No-op) مع الاستمرار في إرجاع الرمز 2xx حتى لا يُصنفها GitHub على أنها فاشلة.

كما يسهم ذلك في التصدي لهجمات إعادة الإرسال (Replay attacks)؛ فحتى لو كان توقيع الطلب الملتقط صحيحًا، سيكون معرّفه مخزنًا بالفعل.

دع وكيل البرمجة يختبر نقطة نهاية المُشغِّل باستخدام Apidog CLI

لا ينبغي لك اختبار العمليات الحسابية للتوقيع يدويًا. دع وكيل البرمجة الذي كتب خدمة الاستقبال يتولى كتابة اختباراتها بنفسه وتشغيلها عبر Apidog CLI. يمكنك إعداده لمرة واحدة كالتالي:

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

ثم وجِّه مطالبة واحدة إلى Claude Code أو Codex أو 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.

يقرأ الوكيل كل مخطط (Schema)، ويتحقق من صحة حمولة بياناته، ثم ينشئ الموارد وينفذها:

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 نتيجة النجاح أو الفشل لكل توكيد (Assertion)، بينما يُحفظ تقرير json في المسار ./apidog-reports، مما يُمكّن الوكيل من تحديد أي فحص قد تعطل (فالحصول على 200 بينما كنت تتوقع 401 يعني غالبًا غياب البرمجية الوسيطة الخاصة بمعالجة نص الطلب الخام raw-body).

يمكن استخدام سطر apidog run نفسه ضمن التكامل المستمر (CI) مع الخيار -r junit؛ راجع Apidog CLI in GitHub Actions. للمزيد حول إعداد الوكيل، اقرأ Apidog CLI in Claude Code، وللاطلاع على استراتيجية شاملة لاختبار خطافات الويب، راجع how to test webhooks. تغطي الخطة المجانية من Apidog فرق العمل التي تضم حتى 4 مستخدمين.

قبل تفعيل خطاف الويب

  1. تعيين السر (Secret)؛ بحيث يُقابَل التوقيع المفقود أو غير الصحيح برمز 401.
  2. الرد برمز 202 في مدة أقل بكثير من 10 ثوانٍ، مع إدراج مهام الوكيل في طابور انتظار.
  3. تخزين معرّفات التسليم بقيد فريد يمنع التكرار (Unique constraint).
  4. وجود مهمة تعيد محاولة تنفيذ عمليات التسليم الفاشلة خلال الأيام الثلاثة الماضية.

إذا كنت تفضل استخدام بيئة التشغيل الخاصة بـ GitHub، فإن Claude Code GitHub Actions هو الخيار المستضاف؛ بينما تتيح نقطة استقبال خطافات الويب ميزات التصفية وتوجيه سلاسل المحادثات. لمعرفة المزيد حول إعادة المحاولات من جانبك، راجع how to design reliable webhooks.

زر

الأسئلة الشائعة

هل ينبغي لي استخدام خطاف ويب للمستودع أم تطبيق GitHub App؟ يُعد خطاف الويب الخاص بالمستودع أو المؤسسة كافيًا لفريق عمل واحد؛ بينما يمنح تطبيق GitHub App الوكيل هوية بوت مستقلة خاصة به، وصلاحيات أكثر دقة، وإمكانية التثبيت عبر مؤسسات متعددة.

ماذا يحدث إذا تعطلت نقطة النهاية الخاصة بي؟ يُسجل GitHub عملية التسليم على أنها فاشلة ولا يعيد المحاولة تلقائيًا. ومع ذلك، يمكنك إعادة تسليم الطلبات الفاشلة خلال الأيام الثلاثة الماضية من إعدادات خطاف الويب أو عبر واجهة برمجة تطبيقات REST.

كيف أمنع الوكيل من الرد على نفسه؟ قم بإسقاط أي إشعار تسليم يكون فيه sender هو حساب البوت الخاص بك في مرحلة تصفية المسار السريع، قبل تنفيذ أي إجراء آخر.

لماذا نُرجع الرمز 202 بدلاً من 200؟ كلاهما يُعتبران رمز نجاح بالنسبة إلى GitHub؛ لكن الرمز 202 Accepted يوضح لأي شخص يقرأ سجلات خادمك أن المهمة قد أُدرجت في طابور الانتظار ولم تكتمل بعد.

هل تصميم الوكيل الفائق (Super-agent) من DeepSeek ميزة جاهزة يمكنني تفعيلها مباشرة؟ لا، فالمقال يصف بنية هيكلية معمارية، كما أن إضافته النموذجية الأولية ليست منتجًا رسميًا من DeepSeek؛ بل يتعين عليك بناء طبقة المُشغِّلات بنفسك كما هو موضح أعلاه.

ممارسة تصميم API في Apidog

اكتشف طريقة أسهل لبناء واستخدام واجهات برمجة التطبيقات