قبل ستة أشهر، وبينما كنا نعمل على أداة إنتاجية داخلية، اتخذ فريقنا قرارًا مثيرًا للجدل (آنذاك): سنبني مستودعنا من دون أي كود يكتبه البشر. كان يجب أن يُولَّد كل سطر في مستودع مشروعنا بواسطة Codex.
ولإنجاح ذلك، أعدنا تصميم سير العمل الهندسي لدينا من الصفر. بنينا مستودعًا ملائمًا للوكلاء، واستثمرنا كثيرًا في الاختبارات الآلية والحواجز الوقائية، وتعاملنا مع Codex بوصفه زميلًا كامل الأهلية. وقد وثّقنا تلك الرحلة في منشور مدونتنا السابق عن هندسة المنصة.
وقد نجح ذلك، لكننا اصطدمنا بعد ذلك بعنق الزجاجة التالي: تبديل السياق.
ولحل هذه المشكلة الجديدة، بنينا نظامًا سميناه Symphony. إن Symphony(يفتح في نافذة جديدة) منسّق للوكلاء يحوّل لوحة إدارة المشاريع مثل Linear إلى طبقة تحكم لوكلاء البرمجة. تحصل كل مهمة مفتوحة على وكيل، ويعمل الوكلاء باستمرار، ويراجع البشر النتائج.
يشرح هذا المنشور كيف أنشأنا Symphony—ما أدى إلى زيادة بنسبة 500% في طلبات السحب المدمجة لدى بعض الفرق—وكيف تستخدمه لتحويل متتبع المشكلات لديك إلى منسّق وكلاء يعمل دائمًا.
سقف وكلاء البرمجة التفاعليين
حتى مع ازدياد سهولة استخدامهم، ما تزال أدوات البرمجة الوكيلة—سواء أُتيح الوصول إليها عبر تطبيقات الويب أو CLI—أدوات تفاعلية.
ومع ازدياد نطاق العمل الوكيلي في OpenAI، وجدنا نوعًا جديدًا من العبء. كان كل مهندس يفتح بضع جلسات Codex، ويُسنِد المهام، ويراجع المخرجات، ويوجّه الوكيل، ثم يكرر ذلك. عمليًا، كان معظم الأشخاص قادرين على إدارة ثلاث إلى خمس جلسات في وقت واحد بشكل مريح قبل أن يصبح تبديل السياق مؤلمًا. وبعد ذلك، كانت الإنتاجية تنخفض. كنا ننسى أي جلسة تقوم بماذا، ونقفز بين الطرفيات لإعادة الوكلاء إلى المسار الصحيح، ونصحح أخطاء المهام الطويلة التي كانت تتعطل في منتصف الطريق.
كان الوكلاء سريعين، لكن كان لدينا عنق زجاجة على مستوى النظام: انتباه البشر. لقد بنينا فعليًا فريقًا من مهندسين مبتدئين ذوي قدرات عالية جدًا، ثم كلّفنا مهندسينا البشر بإدارتهم التفصيلية. ولم يكن ذلك قابلًا للتوسع.
تحول في المنظور
أدركنا أننا نحسّن الشيء الخطأ. كنا نوجّه نظامنا حول جلسات البرمجة وطلبات السحب المدمجة، في حين أن طلبات السحب والجلسات هما في الحقيقة وسيلة إلى غاية. تُنظَّم سير العمل البرمجية إلى حد كبير حول المخرجات: المشكلات، والمهام، والتذاكر، والمعالم.
لذلك سألنا أنفسنا: ماذا سيحدث إذا توقفنا عن الإشراف المباشر على الوكلاء وسمحنا لهم بدلًا من ذلك بسحب العمل من متتبع المهام لدينا؟
أصبحت تلك الفكرة هي Symphony، وهي مواصفة مكتوبة تعمل كمشرف لتنسيق العمل الوكيلي.
تحويل متتبع المشكلات لدينا إلى منسّق وكلاء
بدأ Symphony بمفهوم بسيط: يجب أن يلتقط وكيل أي مهمة مفتوحة ويكملها. وبدلًا من إدارة جلسات Codex في علامات تبويب متعددة، جعلنا متتبع المشكلات لدينا طبقة التحكم.
في هذا الإعداد، تُطابِق كل مشكلة مفتوحة في Linear مساحة عمل مشتركة مخصصة لوكيل. يراقب Symphony لوحة المهام باستمرار ويضمن أن لكل مهمة نشطة وكيلًا يعمل ضمن الحلقة حتى تكتمل. وإذا تعطّل وكيل أو توقّف، يعيد Symphony تشغيله. وإذا ظهر عمل جديد، يلتقطه Symphony ويبدأ بتنظيم العمل.
بنينا سير عملنا على حالات التذاكر، باستخدام مدير المهام Linear بوصفه آلة حالات.
عمليًا، يفصل Symphony العمل عن الجلسات وعن طلبات السحب. تنتج بعض المشكلات عدة طلبات سحب عبر مستودعات متعددة؛ بينما يكون بعضها الآخر مجرد استقصاء أو تحليل لا يلامس قاعدة الكود مطلقًا.
بمجرد تجريد العمل بهذه الطريقة، يمكن أن تمثل التذاكر وحدات عمل أكبر بكثير.
نستخدم Symphony بانتظام لتنسيق الميزات المعقدة وعمليات ترحيل البنية التحتية. على سبيل المثال، قد ننشئ مهمة نطلب فيها من الوكيل تحليل قاعدة الكود أو Slack أو Notion وإنتاج خطة تنفيذ. وبمجرد أن نرضى عن الخطة، يُنشئ الوكيل شجرة من المهام، ويقسّم العمل إلى مراحل ويحدد التبعيات بين المهام.
لا يبدأ الوكلاء العمل إلا على المهام غير المحجوبة، لذلك يتكشف التنفيذ بصورة طبيعية وعلى نحو أمثل بالتوازي لهذا الرسم البياني غير الدوري الموجّه (DAG) (تسلسل من خطوات التنفيذ). وفي المثال أدناه، وضعنا ترقية React على أنها محجوبة بترحيل إلى Vite. وكما هو متوقع، بدأ الوكلاء ترقية React فقط بعد اكتمال الترحيل إلى Vite.
يمكن للوكلاء أيضًا إنشاء عمل بأنفسهم. أثناء التنفيذ أو المراجعة، يلاحظون كثيرًا تحسينات تقع خارج نطاق المهمة الحالية: مشكلة في الأداء، أو فرصة لإعادة الهيكلة، أو بنية أفضل. وعندما يحدث ذلك، فإنهم ببساطة ينشئون مشكلة جديدة يمكننا تقييمها وجدولتها لاحقًا—وكثير من هذه المهام اللاحقة تلتقطها الوكلاء أيضًا. وبينما نشرف نحن على هذه العملية، يبقى الوكلاء منظمين ويواصلون دفع العمل إلى الأمام.
تقلل طريقة العمل هذه بدرجة كبيرة الكلفة الإدراكية لبدء الأعمال الغامضة. فإذا أخطأ الوكيل في شيء ما، فهذه تظل معلومات مفيدة، وتكلفتها علينا تكاد تساوي الصفر. يمكننا بتكلفة منخفضة جدًا إنشاء تذاكر للوكيل كي يضع نماذج أولية ويستكشف، ثم نتخلص من أي استكشافات لا تعجبنا.
ولأن المنسّق يعمل على devboxes ولا ينام أبدًا، يمكننا إضافة المهام من أي مكان مع العلم أن وكيلًا سيلتقطها. فعلى سبيل المثال، أجرى أحد مهندسي فريقنا ثلاثة تغييرات مهمة من تطبيق Linear على هاتفه من كوخ مريح مع اتصال Wi‑Fi رديء.
زيادة في الاستكشاف نتيجة العمل بهذه الطريقة
عند ملاحظة آثار العمل باستخدام Symphony، كان أوضح تغيير هو المخرجات. ففي بعض الفرق داخل OpenAI، رأينا عدد طلبات السحب المدمجة يرتفع بمقدار 6 أضعاف خلال الأسابيع الثلاثة الأولى. وخارج OpenAI، سلط مؤسس Linear، Karri Saarinen، الضوء على طفرة في مساحات العمل المشتركة التي تم إنشاؤها(يفتح في نافذة جديدة) بالتزامن مع إطلاقنا Symphony. لكن التحول الأعمق هو كيفية تفكير الفرق في العمل.
عندما لم يعد مهندسونا يقضون وقتًا في الإشراف على جلسات Codex، تغيّرت اقتصاديات تغييرات الكود بالكامل. فقد انخفضت الكلفة المتصورة لكل تغيير لأننا لم نعد نستثمر جهدًا بشريًا في دفع التنفيذ نفسه.
وقد غيّر ذلك سلوكنا. أصبح من السهل جدًا الآن إطلاق مهام استكشافية في Symphony. جرّب فكرة، واستكشف إعادة هيكلة، واختبر فرضية، ولا تحتفظ إلا بالنتائج التي تبدو واعدة.
كما أنه يوسّع دائرة من يمكنه بدء العمل. فبإمكان مدير المنتج والمصمم لدينا الآن تقديم طلبات ميزات مباشرة إلى Symphony. لا يحتاجان إلى سحب المستودع أو إدارة جلسة Codex. يصفان الميزة ويحصلان بالمقابل على حزمة مراجعة تتضمن فيديو يشرح عمل الميزة داخل المنتج الحقيقي.
ويتألق Symphony أيضًا في المستودعات الأحادية الكبيرة (مثل الذي لدينا في OpenAI) حيث تكون المرحلة الأخيرة من دمج طلب السحب بطيئة وهشة. يراقب النظام CI، ويعيد الدمج عند الحاجة، ويحل التعارضات، ويعيد المحاولات عند فشل الفحوصات المتقطعة، ويقود التغييرات عمومًا عبر المسار. وبحلول الوقت الذي تصل فيه التذكرة إلى Merging، تكون لدينا ثقة عالية بأن التغيير سيدخل إلى الفرع الرئيسي من دون حاجة إلى متابعة بشرية دقيقة.
بعد تطبيق Symphony، نفوّض المزيد من العمل إلى الوكلاء ونركّز على المهام الأصعب والأكثر استكشافية.
يأتي التقدم بمشكلات جديدة ومختلفة
ينطوي العمل بهذا المستوى على مقايضات. فعندما انتقلنا من توجيه الوكلاء تفاعليًا إلى إسناد العمل إليهم على مستوى التذاكر، فقدنا القدرة على دفعهم باستمرار أثناء التنفيذ وتصحيح المسار عند الحاجة. وأحيانًا كان الوكيل ينتج شيئًا بعيدًا تمامًا عن المطلوب. وكان ذلك مفيدًا—فقد كشفت تلك الإخفاقات عن فجوات في النظام وساعدتنا على جعله أكثر متانة.
وبدلًا من إصلاح النتيجة يدويًا، أضفنا حواجز وقائية ومهارات كي يتمكن الوكلاء من النجاح في المرة التالية. ومع مرور الوقت، قادنا هذا إلى إضافة قدرات جديدة إلى منصتنا، مثل تشغيل اختبارات شاملة، والتحكم في التطبيق عبر Chrome DevTools، وإدارة اختبارات QA السريعة. كما حسّنّا توثيقنا بشكل كبير ووضحنا معنى الجودة المطلوبة.
ليست كل مهمة مناسبة لأسلوب العمل في Symphony. فما تزال بعض المشكلات تتطلب من المهندسين العمل مباشرة مع جلسات Codex التفاعلية، خصوصًا المشكلات الغامضة أو العمل الذي يتطلب حكمًا وخبرة قويين. وعمليًا، تكون هذه عادةً أكثر المهام إثارة ومتعة لكي يقضي مهندسونا وقتهم فيها.
والفرق هو أن Symphony يستطيع التعامل مع الجزء الأكبر من أعمال التنفيذ الروتينية. وهذا يتيح للمهندسين التركيز على مشكلة صعبة واحدة في كل مرة بدلًا من تبديل السياق باستمرار بين مهام أصغر.
وتعلّمنا أيضًا أن معاملة الوكلاء كعُقد جامدة في آلة حالات لا تنجح جيدًا. فالنماذج تصبح أذكى ويمكنها حل مشكلات أكبر من الصندوق الذي نحاول حشرها فيه. فعلى سبيل المثال، كانت الإصدارات المبكرة تحتوي على كل تكاملات GitHub كجزء من المنصة الخارجية—فمثلًا كانت الإصدارات المبكرة تتوقع من Codex إجراء تغييرات على الكود فقط، مع تحديد بقية العملية (إرسال التغييرات، وتشغيل الاختبارات) في الكود. وكان عملنا الوكيلي المبكر يقتصر على مطالبة Codex بتنفيذ المهمة فقط. وقد ثبت أن هذا النهج مقيِّد جدًا. فـ Codex قادر تمامًا على إنشاء عدة طلبات سحب وكذلك قراءة ملاحظات المراجعة ومعالجتها. لذلك زودناه بالأدوات—واجهة الأوامر gh، ومهارات لقراءة سجلات CI، وما إلى ذلك—وأصبحنا الآن نستطيع أن نطلب من Codex القيام بالمزيد، مثل إغلاق طلبات السحب القديمة أو سحب تقارير حول العمل المكتمل مقابل المتروك. وقد وقعت هذه الأنواع من المهام خارج صندوق تنفيذ الميزة الأولي بكثير.
ولذلك اتجهنا في النهاية إلى إعطاء الوكلاء أهدافًا بدلًا من انتقالات صارمة، تمامًا كما يفعل المدير الجيد عندما يكلّف أحد تقاريره المباشرة بهدف ضمن الفريق. إن قوة النماذج تأتي من قدرتها على الاستدلال، لذا امنحها الأدوات والسياق ودعها تعمل.
استخدام Symphony لبناء Symphony
عندما تفتح مستودع Symphony، فإن أول ما ستلاحظه هو أن Symphony، من الناحية التقنية، مجرد ملف SPEC.md—تعريف للمشكلة والحل المقصود. وبدلًا من بناء نظام إشراف معقد، عرّفنا المشكلة والحلول المقصودة، ومنحنا الوكلاء توجيهًا عالي المستوى.
كُتب التطبيق المرجعي بلغة Elixir—لأنه عندما يصبح الكود مجانيًا عمليًا، يمكنك أخيرًا اختيار اللغات وفقًا لنقاط قوتها، مثل التزامن في Elixir—لكن يمكن التعبير عن الفكرة الأساسية في مستند Markdown بسيط. نشجعك على توجيه وكيلك المفضل للبرمجة إلى المواصفة وجعله ينفذ نسخته الخاصة.
كانت النسخة الأولى من Symphony مجرد جلسة Codex تعمل داخل tmux، تستطلع Linear وتُطلق وكلاء فرعيين للمهام الجديدة. لقد نجحت، لكنها لم تكن موثوقة بشكل خاص. أما النسخة الثانية فعاشت داخل مستودع مشروعنا الرئيسي، الذي بُني مع وضع الوكلاء في الاعتبار. كنا قد أنشأنا بالفعل منصة الوكلاء لمنح الوكلاء المهارات والسياق اللازمين لإنجاز عمل عالي الجودة في هذا المستودع، لذا كان Symphony يربط كل ذلك ببساطة.
وبمجرد توفر الوظائف الأساسية، استخدمنا Symphony لبناء Symphony.
عندما عرضنا داخليًا النظام وهو يدير المهام ويرفق فيديو إثبات العمل الخاص به، كانت ردود الفعل إيجابية للغاية: نمت قناة مشروع Symphony لدينا، وبدأت الفرق في أنحاء المؤسسة استخدامه بشكل طبيعي. يُعد توافق المنتج مع السوق داخليًا شرطًا أساسيًا للإطلاق خارجيًا في OpenAI. وبناءً على الاستخدام الذي رأيناه في OpenAI، أصبح من الواضح أنه ينبغي لنا مشاركة Symphony خارج أسوار الشركة.
لذلك استخلصنا الفكرة في ملف مستقل SPEC.md وطلبنا من Codex تنفيذه. وبالنسبة إلى التطبيق المرجعي، اخترنا Elixir، وهي لغة متخصصة نسبيًا تمتلك بدائيات ممتازة لتنسيق العمليات المتزامنة والإشراف عليها. أنشأ Codex تنفيذ Elixir دفعة واحدة، وواصلنا بعد ذلك التكرار على كلٍّ من المواصفة والتنفيذ. ولصقل المواصفة، طلبنا حتى من Codex تنفيذها بعدة لغات أخرى—TypeScript وGo وRust وJava وPython—واستخدام النتائج لتحديد أوجه الغموض وتبسيط النظام. وقد نجح في كل لغة.
ومن خلال عملية بناء Codex، أزلنا كثيرًا من التعقيد العرضي، مثل الاعتماد على مستودعات محددة أو Linear MCP. لم يعد Symphony يعتمد على مستودعاتنا أو سير العمل الداخلي لدينا. وأصبح النهج الأساسي بسيطًا:
لكل مهمة مفتوحة، اضمن أن وكيلًا يعمل في مساحة العمل المشتركة الخاصة به.
إضافةً إلى المساعدة في العمل النشط، أصبح سير عمل التطوير الآن شيئًا يعرفه الوكلاء ويتبعونه. فسير عمل التطوير—العمل على مشكلة، وسحب مستودع، ووضعها قيد التنفيذ حتى يعرف مدير المنتج أنها قيد العمل، وإضافة طلب السحب، ونقلها إلى حالة Review، وإرفاق الفيديوهات، وما إلى ذلك—أصبح الآن موثقًا في ملف بسيط WORKFLOW.md. كل هذا كان عملية يتبعها البشر، لكنه لم يكن موثقًا قط. وبدلًا من الاعتماد على هذه المجموعة الضمنية من الخطوات، نوثقها الآن، ويضمن Symphony أن يتبعها الوكلاء. وهذا يتيح لنا بناء وكلاء يعملون إلى جانبنا. وإذا قررنا أن على الوكلاء أيضًا إرفاق تأمل ذاتي بالعمل المكتمل، فسنضيف ذلك إلى WORKFLOW.md، وسيوجه Symphony الوكلاء إلى تلك الخطوة.
كما أتيحت لنا فرصة استخدام Codex في وضع app server(يفتح في نافذة جديدة)، وهو وضع مدمج بلا واجهة لـ Codex. وقد أتاح لنا هذا الوضع تشغيل Codex والتخاطب معه برمجيًا عبر واجهة JSON-RPC موثقة جيدًا لأشياء مثل بدء سلسلة محادثة أو التفاعل مع الأدوار. وهي طريقة أكثر ملاءمة وقابلية للتوسع بكثير من محاولة التفاعل مع Codex عبر CLI أو جلسات tmux الحية.
كان Codex App Server مناسبًا تمامًا لحالة استخدامنا: فنحن نستفيد من المنصة التي يوفرها Codex مع امتلاك مقابض وخطافات للربط. فعلى سبيل المثال، ولتجنّب كشف رمز الوصول إلى Linear للوكلاء الفرعيين، نستخدم استدعاءات الأدوات الديناميكية(يفتح في نافذة جديدة) لكشف الدالة الخام linear_graphql التي تنفذ طلبات عشوائية على Linear، من دون الاعتماد على MCP أو كشف رمز الوصول للحاويات.
ما التالي
Symphony طبقة تنسيق دنيا مقصودة. نحن نطرحها كمصدر مفتوح لإظهار قوة Codex App Server عند اقترانه بأدوات سير عمل مختلفة، مثل Linear. وبناءً على ذلك، لا نخطط لصيانة Symphony كمنتج مستقل. فكّر فيه بوصفه تطبيقًا مرجعيًا. وعلى غرار كيفية توجيه كثير من المطورين وكلاء البرمجة لديهم إلى منشور هندسة المنصة لتهيئة مستودعاتهم، نأمل أن توجّه وكيلك المفضل للبرمجة إلى مواصفة(يفتح في نافذة جديدة) Symphony ومستودعه(يفتح في نافذة جديدة) لبناء نسخك الخاصة المصممة لبيئاتك.
تكمن القوة في Codex وخادم التطبيق الخاص به. وكان Symphony وسيلة لربط Codex بـ Linear، وهما شيئان كنا نستخدمهما بالفعل، لحل مشكلة إدارة العمل. ومع تحسن وكلاء البرمجة في الاستدلال واتباع التعليمات، نتوقع أن يتحول عنق الزجاجة في الشركات الأخرى أيضًا من كتابة الكود إلى إدارة العمل الوكيلي. والجزء المثير هو أن حاجز تجربة أنظمة وكلاء البرمجة هذه أصبح الآن منخفضًا على نحو مفاجئ. يمكنك ببساطة بناء الأشياء باستخدام Codex.
إشادات من المجتمع
يسعدنا أن نرى مجتمع الهندسة يستخدم Symphony في الأسابيع التي تلت الإطلاق، محققًا أكثر من 15 ألف نجمة على GitHub(يفتح في نافذة جديدة) حتى 23 أبريل.