مراقبة الوكلاء (Observability): الخطافات (Hooks) وAlloy وGrafana
> ربطنا Claude Code وCodex بمكدس Grafana واحد باستخدام OpenTelemetry وAlloy، ثم استخدمنا التتبعات (traces) والسجلات لإيجاد مشكلات سلوك الوكلاء وإصلاحها من مصدرها.
تفشل أنظمة الوكلاء بطرق غريبة.
أحيانًا تكون المشكلة في النموذج. أحيانًا تكون المشكلة في الأداة. أحيانًا يكون خادم MCP لديك سليمًا تمامًا، لكن الوكيل اختار المتخصص الخطأ، أو أمضى نصف الجلسة في عمل صدفة (shell) لم تتوقعه، أو استهلك التكلفة بصمت في حلقة بدت مثمرة من الخارج.
إذا لم تستطع رؤية الفرق، فأنت لا تُشغِّل نظام وكلاء فعليًا. أنت تخمِّن.
لذا بنينا مكدس مراقبة (observability) لسير عملنا الخاص: Claude Code وCodex وأحداث خطافات (hooks) Claude وأحداث إشعارات (notify) Codex وOpenTelemetry الأصلي وGrafana Alloy وGrafana Cloud في الطرف الآخر.
الجزء المثير للاهتمام ليس “لقد صنعنا لوحة معلومات (dashboard)”. الجزء المثير للاهتمام هو أننا اضطررنا إلى تقسيم القياس عن بُعد إلى تدفقين مختلفين لأن لا تغذية واحدة أعطتنا الصورة الكاملة.
المشكلة: قياس عن بُعد للوكلاء مجزَّأ
تُصدر وكلاء البرمجة الحديثة بالفعل بعض القياس عن بُعد. هذا يساعد، لكنه غير كافٍ.
يُجيد OTEL الأصلي الإجابة عن أسئلة مثل:
- كم عدد الطلبات التي أرسلناها؟
- كم كلفت الجلسة؟
- أين توجد الامتدادات (spans) والتتبعات (traces)؟
- هل ارتفع الكمون؟
لكنه أسوأ بكثير في الإجابة عن أسئلة مثل:
- أي خادم MCP اعتمد عليه الوكيل؟
- هل حدث هذا الفشل في
Bash، أم في أداة ملفات مدمجة، أم في استدعاء MCP؟ - أي مهارة (skill) فعليًا نشِطت؟
- أي نوع من الوكلاء الفرعيين أُرسِل؟
- هل كانت الجلسة تقوم بعمل مفيد، أم مجرد تخبط؟
هذا الصنف الثاني من الأسئلة أقرب إلى الخطافات (hooks) منه إلى التتبعات (traces).
لكن العكس صحيح أيضًا: بعض أهم أسئلة الأداء أقرب إلى التتبعات منها إلى الخطافات.
إذا أردت معرفة أين تراكم الكمون فعليًا، وأي الامتدادات كانت بطيئة، أو ما إذا كانت الجلسة قد استهلكت الوقت في استدعاءات النموذج مقابل تنفيذ الأدوات، فأنت بحاجة إلى بيانات التتبع بقدر حاجتك إلى الأحداث الدلالية.
البنية التي انتهينا إليها
نُشغِّل مسارَي قياس عن بُعد جنبًا إلى جنب.
Claude Code
native OTEL -> Alloy -> Grafana Cloud
hooks -> send_event.py -> Grafana Cloud Loki
Codex
native OTEL -> Alloy -> Grafana Cloud
notify hook -> codex_notify.py -> shared Loki schema
هذا الانقسام مقصود.
وهو أيضًا غير متماثل. يمنحنا Claude Code سطح خطافات دورة حياة أغنى بكثير. يمنحنا Codex OTEL أصليًا بالإضافة إلى سطح إشعارات (notify)، لذا نُطبِّع أحداث إتمام الأدوار الأرق في مخطط السجل نفسه بدلًا من التظاهر بأن كلا وقتَي التشغيل يعرضان الضوابط ذاتها.
OTEL الأصلي يمنحنا التدفق الأساسي: السجلات والتتبعات من وقت التشغيل نفسه، بالإضافة إلى المقاييس حيث يُصدرها وقت التشغيل فعليًا.
أحداث الخطافات والإشعارات تمنحنا الطبقة الدلالية: أشياء مثل PreToolUse وPostToolUse وPostToolUseFailure وUserPromptSubmit وSubagentStop وSkillActivated، والبيانات الوصفية المصنَّفة التي نهتم بها فعليًا عند تصحيح سلوك الوكيل. يسهم Claude Code هنا بتدفق الأحداث الأغنى. ويسهم Codex بتدفق مُطبَّع أرق لكن لا يزال مفيدًا.
لماذا توجد الخطافات (Hooks) أساسًا
يُثري خط أنابيب الخطافات لدينا الأحداث قبل وصولها إلى Loki.
بدلًا من الاكتفاء بالقول “عملت أداة ما”، نصنِّف الحدث في حقول مثل:
tool_type: مدمجة (builtin)، وMCP، ومهارة (skill)، ووكيل (agent)، وbashmcp_server: أي خلفية MCP تعاملت مع الاستدعاءbash_cli: عائلة أمر الصدفةsubagent_type: أي نوع من المتخصصين أُرسِلagent_tool: ما إذا كان المصدر Claude Code أم Codex
هذا يعني أننا نستطيع طرح أسئلة مهمة تشغيليًا:
{service_name="claude-code-hooks"} | agent_tool="codex-cli"
{service_name="claude-code-hooks"} | tool_type="mcp"
{service_name="claude-code-hooks"} | json | bash_cli="git"
تلك ليست حقولًا زائدة عن الحاجة. إنها الفرق بين “شعرتُ بأن الوكيل بطيء” و“أمضى الوكيل الدقائق العشر الأخيرة في عمليات git كثيفة الصدفة (shell) مع معدل فشل أدوات مرتفع”.
ثمة تفصيل تنفيذي يبدو أغرب مما هو عليه: لا يزال تدفق Loki المشترك يستخدم service_name="claude-code-hooks" كتصنيف حتى عندما يأتي الحدث من Codex. الانقسام الحقيقي بين وقتَي التشغيل يحدث عند agent_tool.
لماذا تقع Alloy في المنتصف
Grafana Alloy ليست مجرد مُعيد توجيه في هذا الإعداد. إنها حدود السياسة.
نوجِّه تدفق OTEL الأصلي من Claude Code وCodex إلى بروكسي محلي لـAlloy عند localhost:4318، ثم نترك Alloy تنظِّف الحمولة (payload) قبل إعادة توجيهها إلى Grafana Cloud.
هذا مهم لأن القياس عن بُعد الخام للوكلاء مليء بحقول عالية التعداد المتمايز مفيدة للتحليل لكنها فظيعة كتصنيفات مفهرَسة:
session_idprompt_id- عدد الرموز (tokens)
- المدد الزمنية
- كتل معاملات الأدوات
إذا فهرست كل شيء، تحصل على انفجار تصنيفات ويوم سيء.
لذا تقوم Alloy بثلاثة أشياء من أجلنا:
- تُبقي مجموعة صغيرة جدًا من التصنيفات منخفضة التعداد المتمايز مفهرَسة.
- تنقل الحقول الصاخبة لكن المفيدة إلى بيانات وصفية منظَّمة.
- تُسقِط الضجيج الخالص كليًا.
الفكرة المهمة بسيطة: راقِب أكثر، وفهرِس أقل.
لماذا يتجاوز تدفق الخطافات Alloy
تدفق الخطافات مُهيَّأ لـLoki بالفعل.
بحلول الوقت الذي يدفع فيه send_event.py حدثًا، نكون قد قررنا بالفعل أي الحقول تستحق المعاملة كتصنيف وأيها ينتمي إلى جسم JSON المنظَّم. يذهب ذلك التدفق مباشرة إلى بوابة OTLP الخاصة بـGrafana Cloud بدلًا من المرور مجددًا عبر Alloy.
لذا يمتلك النظام تقسيمًا واضحًا للعمل:
- Alloy تُروِّض تدفق OTEL الأصلي الخام.
- إثراء الخطافات يجعل الأحداث الدلالية قابلة للاستعلام.
هذا يُبقي البنية أبسط من محاولة إجبار كل شيء عبر مسار واحد.
ما تُظهره لوحة المعلومات فعليًا
لقطة الشاشة أدناه من إحدى لوحات معلومات المراقبة خلف سير عمل وكلائنا. إنها ليست معيارًا (benchmark)، والأرقام مجرد شريحة زمنية آنية. الهدف هو شكل البيانات: تغذية النشاط، واستدعاءات الأدوات، والإخفاقات، والمطالبات، والتصنيفات حسب الوكيل، والأدوات المدمجة، واستخدام MCP، وأوامر الصدفة، والمهارات.
الجزء المفيد هو أن لوحة المعلومات هذه تعيش على مكدس Grafana نفسه مع بقية قياس عن بُعد للوكلاء. يمكننا التصفية حسب الوكيل المصدر وعائلة الأداة والنظر عبر أوقات التشغيل دون ابتكار قصة مراقبة مختلفة لكل نظام.
لماذا تهم التتبعات (Traces) أكثر مما تبدو للوهلة الأولى
تخبرنا السجلات بفئة العمل الذي حدث. تخبرنا التتبعات بكيفية تكشُّف العمل عبر الزمن.
هذا الفرق مهم في أنظمة الوكلاء لأن “بطيء” وصف فظّ أكثر من اللازم ليكون مفيدًا.
يمكن للتتبع أن يخبرنا ما إذا كان الألم قادمًا من:
- كمون النموذج
- زمن تنفيذ الأداة
- محاولات إعادة متكررة
- تفاعل واحد مكلف بشكل خاص مع MCP
- ذيل طويل من عمليات صغيرة بدت غير ضارة عند عزلها
عمليًا نستخدم تدفق الخطافات وتتبعات Tempo معًا.
- سجلات الخطافات تجيب: أي نوع من الأشياء حدث؟
- التتبعات تجيب: أين ذهب الوقت؟
هذا المزيج هو ما يحوِّل المراقبة من لوحة معلومات إلى تفسير.
أين يقع Codex
Codex جزء من المكدس نفسه، لكنه ليس مطابقًا لـClaude Code.
بالنسبة إلى Codex نربط قطعتين:
- OTEL الأصلي من Codex إلى Alloy
- خطاف ويب (webhook) إشعارات إلى
codex_notify.py، الذي يُحوِّل إتمامات الأدوار إلى مخطط Loki نفسه الذي نستخدمه لأحداث الخطافات
هذا يمنحنا تصفية موحَّدة مثل agent_tool="codex-cli" داخل تدفق السجل نفسه.
التحفظ الصادق: حمولة إشعارات Codex أرق حاليًا من حمولة خطافات Claude Code لأنها ليست نوع سطح التكامل نفسه. في إعدادنا اليوم، يمكن تطبيع إتمامات أدوار Codex في المخطط المشترك، لكن الاستخلاص الغني أداةً بأداة لا يزال أفضل في تدفق OTEL الأصلي منه في جسر الإشعارات.
هذا ليس سببًا لتجنّب هذا المنشور. إنه بيت القصيد من المنشور. تُبنى أنظمة المراقبة الحقيقية من إشارات غير مثالية.
Grafana عبر MCP يغيِّر قواعد اللعبة
التحوّل الأكبر هو أن Grafana ليست مجرد مكان يزوره البشر في متصفح.
في هذا المستودع نعرض Grafana أيضًا عبر MCP. هذا يعني أن الوكيل يستطيع الاستعلام عن Loki وPrometheus وTempo مباشرة بدلًا من الانتظار حتى يفحص إنسان لوحات المعلومات يدويًا أولًا.
هذا يحوِّل المراقبة إلى مُدخَل نشِط في سير العمل.
يستطيع الوكيل أن يسأل:
- أي عائلات أدوات فشلت أكثر في الساعة الأخيرة؟
- أي خادم MCP هيمن على جلسة ما؟
- هل قلَّلت التغييرات الأخيرة من إخفاقات الأدوات، أم أنها فقط نقلت العمل إلى مسارات أكثر كثافة في الصدفة (shell) بالأخطاء نفسها؟
- أي التتبعات تُظهر أعلى كمون أو محاولات إعادة متكررة؟
بمجرد أن يتوفر لك ذلك، تكون قريبًا جدًا من حلقة تحسين ذاتي.
من لوحة المعلومات إلى حلقة التغذية الراجعة
هذا هو الجزء الذي نجده الأكثر إثارة للاهتمام.
بمجرد أن يصبح مكدس المراقبة قابلًا للاستعلام من طبقة الوكيل، يتوقف القياس عن بُعد عن كونه سطح إبلاغ سلبي ويصبح إشارة تحكّم.
تبدو الحلقة كما يلي:
- يُصدر نشاط الوكيل تتبعات ومقاييس وسجلات خطافات مُثراة.
- تخزِّن Grafana الأدلة في Loki وTempo وPrometheus حيث توجد المقاييس.
- تستعلم الوكلاء عن تلك الأدلة عبر Grafana MCP.
- يحدِّد النظام مزيج الأدوات السيئ، والمهارات الهشة، والتوجيه الضعيف، أو سير العمل كثيف الصدفة الذي يستمر في إنتاج أخطاء يمكن تجنّبها.
- يُعدِّل الوكلاء أو المشغِّلون المطالبات، أو إعدادات الوكيل، أو أوصاف المهارات، أو قواعد التوجيه، أو صلاحية الوصول إلى الأدوات.
- تُنتج الجلسة التالية شكل قياس عن بُعد جديدًا، وتتكرر الدورة.
هكذا تنتقل من “لوحة معلومات مثيرة للاهتمام” إلى “نظام تحسين قابل للقياس”.
الهدف ليس تعظيم فئة أداة واحدة. الهدف هو الوصول إلى المزيج الصحيح من سطر الأوامر، والأدوات المدمجة، واستدعاءات MCP، والمهارات للعمل الذي يُنجَز فعليًا.
ما الذي يتيح لنا هذا الإجابة عنه
بمجرد أن يستقر وقتا التشغيل كلاهما على مكدس Grafana نفسه، نستطيع الإجابة عن أسئلة تشغيلية أسرع بكثير:
- هل تتركّز الإخفاقات في عائلة أداة واحدة؟
- هل يخلق سير العمل كثيف الصدفة أخطاء يمكن تجنّبها حيث كان ينبغي وجود أداة أعلى مستوى؟
- أي خوادم MCP تحمل عبء العمل؟
- هل ندفع مقابل نشاط وكيل لا يُنتج تقدمًا ذا معنى؟
- هل جلسة ما غير صحية بسبب النموذج، أو الأدوات، أو طبقة التنسيق؟
هذا مفيد بشكل خاص في سير عمل متعدد الوكلاء، حيث لا تخبرك عبارة “كان الوكيل مشغولًا” بأي شيء تقريبًا.
إذا استمر إرسال متخصص واحد وأنتج معدلات فشل مرتفعة، فتلك مشكلة توجيه أو صياغة مطالبة.
إذا هيمن خادم MCP واحد على كل الاستدعاءات، فقد تكون تلك بنية جيدة أو علامة على أن كل شيء آخر عبء ميت.
إذا ارتفعت إخفاقات الأدوات بينما بقيت التكلفة عالية، فلديك مشكلة تشغيلية، لا مشكلة جودة.
إذا استمر عمل الصدفة في الفشل بطرق متوقَّعة يمكن تجنّبها حيث كان ينبغي وجود أداة أعلى مستوى، فتلك إشارة منتج.
إذا نشِطت مهارة واحدة باستمرار دون أن تحسِّن النتائج، فتلك إشارة مطالبة أو توجيه.
الدرس الحقيقي
الدرس الأعمق هنا هو أن مراقبة الوكلاء تحتاج إلى قياس عن بُعد لوقت التشغيل وقياس عن بُعد لسير العمل معًا.
يخبرك قياس عن بُعد لوقت التشغيل بما فعله النظام.
يخبرك قياس عن بُعد لسير العمل بما ظن الوكيل أنه يفعله.
نحتاج إلى كليهما.
إذا احتفظت فقط بالتتبعات والعدَّادات، تفوتك الطبقة الدلالية. وإذا احتفظت فقط بأحداث الخطافات، يفوتك الكمون، والامتدادات، والصورة الأوسع لوقت التشغيل.
وإذا احتفظت بكليهما لكن لم تُغذِّهما أبدًا مرة أخرى إلى طبقة الوكيل، فلديك مراقبة، لا تكيّف.
هذا المزيج هو ما يجعل النظام قابلًا للتفسير بما يكفي للتشغيل، وقابلًا للضبط بما يكفي للتحسين.
ما لا يزال غير كامل
لا تزال هناك حواف خشنة.
- لا يتضمن كل حدث خطاف بيانات المدة والرموز التي نرغب فيها.
- لا تزال بعض أفضل طرق عرض التوقيت تأتي من تتبعات Tempo، لا من سجلات الخطافات.
- Codex اليوم أقل ثراءً دلاليًا من Claude Code في تدفق الأحداث المُثرى.
- لقطة شاشة لوحة المعلومات سطح عمليات حي، لا قطعة تسويقية مصقولة.
تلك النقطة الأخيرة مقصودة. نفضِّل عرض لوحة الأجهزة الحقيقية على التظاهر بأن أنظمة الوكلاء تُفسِّر نفسها بطريقة سحرية.
لماذا يهم هذا بالنسبة إلى Maguyva
Maguyva يدور حول منح الوكلاء ذكاء كود أفضل. لكن بمجرد أن يبدأ الوكلاء فعليًا بأداء عمل مفيد، تظهر حاجة جديدة على الفور: تحتاج إلى رؤية كيف يتصرفون.
تصبح جودة البحث، وجودة التوجيه، واختيار الأدوات، وكفاءة السياق كلها مشكلات قابلة للمراقبة.
لهذا نعتقد أن الأمر يستحق الكتابة عنه. مكدس الوكلاء المستقبلي ليس مجرد مطالبات وأدوات. إنه مطالبات، وأدوات، وطبقة أجهزة القياس التي تخبرك ما إذا كان كل شيء يعمل.
إذا كنت تبني سير عمل جاد للوكلاء، فالمراقبة ليست بنية تحتية اختيارية. إنها جزء من المنتج.
قراءات ذات صلة
المزيد من سجل بناء Maguyva
لماذا رقّينا بحث الكود إلى voyage-4-large_
انتقلنا بتضميناتنا للكود إلى voyage-4-large — الذي يتصدر حاليًا لوحة صدارة RTEB العامة لاسترجاع الكود. النسخة الصادقة: المقايضة التي نقبلها، وما نُفهرِسه فعليًا، ولماذا ندفع مقابل تضمينات متميزة.
التحسين الذاتي المتكرر للغات: صقل ذكاء الكود عبر نحو 280 لغة_
ندعم ذكاء الكود لنحو 280 لغة. لا يستطيع أي إنسان تدقيق ذلك يدويًا. لذا بنينا حلقة تحسين ذاتي متكرر للغات — فحص عيّني، وحكَم LLM، وإصلاح شيء واحد، وإعادة تحقق — ونُشغِّلها بأسطول من الوكلاء المعزولين حتى يصبح الاستخلاص صحيحًا فعلًا، لا مجرد أخضر (green).
البحث المدمَج متعدد الأنماط: اختيار المسترجِع الصحيح لكل استعلام_
استعلام مثل "أين يُعرَّف parseConfig" يحتاج إلى بحث مختلف عن "كيف تعمل المصادقة". يصنِّف Maguyva النية، ويُرجِّح أربعة أنماط استرجاع تبعًا لذلك، ثم يدمج النتائج عبر Reciprocal Rank Fusion الموزون.