Loading blog posts...
Loading blog posts...
جاري التحميل...

يمكن أن يساعد Pi Durable الوكيل على استئناف عمله بعد إعادة النشر، لكن حفظ محادثته لن يمنعه من إرسال الفاتورة نفسها مرتين.
ملخص سريع
harness.resume عند بدء التشغيل.replay: 'safe' على أداة إلا إذا كان تكرار تنفيذها لا يسبب ضرراً.تخيّل وكيلاً أمضى 40 دقيقة في مهمة صيانة: فحص مستودعاً، وسجّل خطة، وبدأ عملية نشر، ثم استُبدلت الحاوية التي يعمل فيها. قد يوضح سجل المحادثة ما كان الوكيل ينوي فعله، لكن استئناف العمل يحتاج أيضاً إلى معرفة ما اكتمل، وما حُفظ من تغييرات الحالة، وما إذا كانت عملية النشر قد حدثت فعلاً.
يوفر Pi Durable آليات حفظ البيانات وتنفيذ العمل لمعالجة هذه المشكلة. صدر بالتزامن مع Pi 1.0 من مطوري وكيل البرمجة Pi، الذي أصبح الآن تحت مظلة Earendil. وهو مكتبة تبني تطبيقك بالاعتماد عليها، وتوفر مكونات منفصلة لسجل المحادثة وحالة التطبيق والعمل غير المكتمل:
| المكوّن | ما يحفظه أو ينسّقه | فائدته العملية |
|---|---|---|
| Harness | التخزين وتثبيت التغييرات والجدولة | ينسّق التنفيذ واستئناف العمل |
| Conversation | رسائل المستخدم وردود المساعد ونتائج الأدوات | يحفظ سجل المحادثة |
| Task | وحدة عمل تُحفظ لها نقاط تحقق | يتابع دورة استجابة النموذج أو استدعاء أداة أو خطوة مخصصة في سير العمل |
| Document | حالة التطبيق بصيغة JSON ذات أنواع محددة، تُعرّف باستخدام defineDoc | يحفظ التقدم في بيانات منظمة خارج سجل المحادثة |
| Submission | مُدخل له هوية يمكن الرجوع إليها | يتيح للجهة المستدعية استرجاع العمل المُرسل وانتظار اكتماله مجدداً بعد إعادة التشغيل |
يمكن لعملية تثبيت واحدة (commit) أن تحفظ معاً إدخالات سجل المحادثة، وتغييرات Document، ومهام Task الجديدة، وتحديثات Submission. وبذلك، لا يجد نظام الاستئناف قراراً مسجلاً من دون التحديث المقابل له في حالة التطبيق. لكن هذا الضمان لا يتجاوز حدود التخزين: فلا يمكنه جعل تثبيت معاملة في قاعدة البيانات وتسليم بريد إلكتروني عبر خدمة خارجية عملية واحدة لا تقبل التجزئة.
ابدأ بالحزم المذكورة في المستودع الرسمي:
bashnpm install --save-exact @earendil-works/pi-durable @earendil-works/pi-ai @earendil-works/chord
يسجّل الخيار --save-exact إصدارات محددة للاعتماديات المباشرة. أضف كلاً من package.json وملف القفل إلى نظام التحكم بالإصدارات: فما زال Pi Durable تجريبياً، وقد تتغير واجهة API الخاصة به. استخدم الأمثلة الحالية في المستودع لبناء التطبيق كاملاً، ولا تخمّن الوسائط المطلوبة لدوال الإنشاء.
ينبغي أن يشمل تسلسل بدء التشغيل الخطوات التالية:
openNodeSqliteStorage('./agent.sqlite')، بعد استيرادها من @earendil-works/pi-durable/storage/sqlite/node.Harness.open.harness.resume عند كل بدء تشغيل، وقبل قبول أي مدخلات جديدة.root.submit.يجب أن تؤدي إعادة تشغيل التطبيق إلى استئناف العمل المحفوظ، لا إلى إرسال الطلب الأصلي كمهمة جديدة.
إذا كان لديك وكيل لفرز الطلبات يعمل عبر webhook، فمرّر مع الإرسال قيمة ثابتة لـ requestId، مثل job-42. وفقاً لـ توثيق Pi Durable وأمثلته، تعيد المحاولة بهذا المعرّف كائن Submission الموجود بالفعل. استخدم المعرّف الثابت للحدث الوارد متى أمكن. فتوليد معرّف جديد عند كل محاولة تسليم يلغي فائدة منع التكرار.

تحتاج أدوات وكيل العمليات إلى سياسات مختلفة للاستئناف: فقراءة الإعدادات ليست مثل التحقق من حالة النشر، ولا مثل بدء عملية نشر.
| إجراء الأداة | خيار إعادة التنفيذ | السبب |
|---|---|---|
| قراءة ملف إعدادات | ضع العلامة replay: 'safe' إذا كان تكرار القراءة لا يسبب ضرراً | تكرار القراءة لا يغيّر النظام |
| الاستعلام عن حالة النشر | ضع العلامة replay: 'safe' إذا كانت نقطة النهاية للقراءة فقط | قد يساعد التحقق مجدداً من الحالة على استئناف العمل |
| بدء عملية نشر | اتركها بلا علامة | ربما بدأ الاستدعاء السابق عملية النشر بالفعل |
| إرسال فاتورة | اتركها بلا علامة | قد يؤدي التكرار إلى تنفيذ إجراء خارجي مرتين |
يجعل Pi Durable، من خلال defineTool، أمان إعادة التنفيذ خياراً صريحاً. فإذا انقطع تنفيذ أداة تحمل علامة الأمان، يمكن تشغيلها مجدداً. أما الأداة التي لا تحمل هذه العلامة، فيُبلغ Harness النموذج بانقطاعها، كما يوضح الإعلان الرسمي.
وهذا هو السلوك الافتراضي المناسب. فقد تتوقف العملية بعد أن تقبل خدمة خارجية الطلب، وقبل أن يسجّل الوكيل النتيجة، لتبقى النتيجة غير مؤكدة.
تحذير
يمنع requestId الخاص بـ Submission تكرار مدخلات المحادثة. لكنه لا يضمن تنفيذ الإجراءات الخارجية مرة واحدة فقط. للمدفوعات أو رسائل البريد أو عمليات النشر، استخدم آلية المزوّد لمنع تكرار الأثر (idempotency)، أو تحقّق من النتيجة الخارجية وطابقها مع الحالة المحلية قبل إعادة المحاولة.
مفتاح منع تكرار الأثر (idempotency key) هو معرّف ثابت يتيح للخدمة التعرّف على الطلبات المتكررة للعملية نفسها. احتفظ بهذا المعرّف عبر جميع المحاولات.
يمكن لـ Document تتبّع الإجراءات المكتملة ومعرّفات العمليات الخارجية. لكنه لا يلغي احتمال التعطل بين نجاح الإجراء الخارجي وتثبيت سجل اكتماله محلياً. لذلك، يحتاج الاستئناف إلى وسيلة للاستعلام من المزوّد أو حسم هذا الغموض بطريقة أخرى.
بالنسبة إلى وكيل العمليات، يُفضّل سير عمل يبدأ النشر، ويحتفظ بمعرّف العملية الخارجية، ثم يتحقق من حالتها بشكل منفصل. وإذا ترك الانقطاع نتيجة البدء مجهولة، فاشترط التحقق من النتيجة أو الحصول على موافقة قبل إعادة المحاولة.
إذا كتبت الحاوية الملف ./agent.sqlite في نظام ملفات مؤقت، فستفقد حالتها المحفوظة عند زواله. ضع الملف على وحدة تخزين دائمة قبل اختبار الاستئناف.
يوصي المستودع الرسمي باستخدام SQLite للوكلاء الذين يعملون لفترات طويلة. اختر نظام تخزين آخر لتلبية حاجة محددة، لا لمجرد افتراض أن قاعدة البيانات المضمّنة محدودة بطبيعتها.
| نظام التخزين | الاستخدام المناسب | القيد |
|---|---|---|
| الذاكرة | الاختبارات والتشغيل المؤقت | تختفي الحالة عند انتهاء العملية |
| SQLite | الوكلاء الذين يعملون لفترات طويلة | يحتاج إلى تخزين دائم ونسخ احتياطية وعملية واحدة تديره |
| JSONL | السجلات الصغيرة التي تريد فحصها يدوياً | يحتفظ بالسجل كاملاً في الذاكرة |
| تخزين مخصص | نظام تخزين تفرضه بنيتك التحتية | تقع عليك مسؤولية التنفيذ والتحقق من صحته |
يحفظ JSONL سجل JSON واحداً في كل سطر. وصيغته المقروءة مفيدة، لكن الاحتفاظ بالسجل في الذاكرة يجعله خياراً افتراضياً غير مناسب لوكيل يستمر سجله في النمو بلا حد. توفر المكتبة أيضاً واجهة تخزين صغيرة، واختبارات توافق، واختبارات قياس أداء للتنفيذات المخصصة. تساعد هذه الأدوات على التحقق من محوّل التخزين، لكنها لا تجعل أي نظام مقترح يعتمد على Postgres أو تخزين المفتاح والقيمة جاهزاً للإنتاج تلقائياً.
ضع قواعد واضحة للنشر:
لن يعيد Pi Durable تشغيل العملية بنفسه. على Server يعمل بنظام Linux، يُعد systemd مع Restart=always خياراً بسيطاً. أما في الحاويات، فاستخدم سياسة لإعادة التشغيل ووحدة تخزين دائمة موصولة بالحاوية. تتولى SQLite حفظ بيانات قاعدة البيانات بشكل دائم. ومع ذلك، تحتاج كل عملية بديلة إلى استدعاء harness.resume.

وكيل برمجة يعمل طوال الليل خيار منطقي كتطبيق أول، لأن المستودع الرسمي يتضمن بالفعل مثالاً صغيراً لوكيل برمجة. ولحفظ حالة التخطيط في بيانات منظمة، اتبع مثال مخطط الإجازات واحتفظ بالتقدم في كائنات Document.
تغطي القدرات المدمجة ونقاط التوسعة احتياجات متعددة:
| الحاجة | واجهة API المناسبة | ما يبقى عليك تحديده |
|---|---|---|
| أدوات البرمجة المحلية | CodingTools وNodeExecutionEnv | الوصول إلى نظام الملفات وصلاحيات shell وعزل التنفيذ |
| سياسات الأدوات | wrapTool | تسجيل الأحداث والتحقق من الموافقات وحدود معدل الاستخدام |
| الإضافات أثناء التشغيل | createRegistry وdefineExtension وloadExtension | التغييرات الآمنة أثناء تنفيذ العمل |
| صلاحيات خاصة بكل محادثة | thread.configure | الأدوات التي يمكن لكل محادثة الوصول إليها |
| إدارة السياق | root.compact | متى وكيف تُقلّص سياق النموذج |
| متابعة التقدم مباشرة | thread.watch وthread.watchEvents | سلوك واجهة المستخدم والتعامل مع إعادة الاتصال |
توفر CodingTools، من @earendil-works/pi-durable/tools، أدوات القراءة والكتابة والتحرير وbash. وتشغّلها NodeExecutionEnv، من @earendil-works/pi-durable/env/node، محلياً، لذا فصلاحياتها هي الصلاحيات التي تمنحها لوكيلك.
في محادثة خاصة بالعمليات، يمكن استخدام thread.configure({ tools: { remove: [deploy] } }) لإلغاء الوصول إلى أداة نشر. ضع آليات الموافقة والتدقيق في غلاف للأداة. لا تعتمد على تعليمات النموذج وحدها لتذكّر السياسة.
يمكن للإضافات إضافة أدوات، وخطافات (hooks)، وأقسام لتعليمات النموذج عبر section، وأغلفة عبر wrapTool، ومهام مخصصة عبر defineTask. يتيح النمط الموثّق registry.install(await loadExtension('./ops.ts')) تحميل شيفرة إضافات جديدة أثناء تشغيل الوكيل، لكن التغييرات أثناء التشغيل تحتاج هي الأخرى إلى اختبارات استئناف.
يستخدم المثال الرسمي لتقليص السياق reserveTokens: 16384 وbackgroundTokens: 32768. ويتحكم التقليص في ما يدخل إلى سياق النموذج من دون حذف السجل المحفوظ بشكل دائم.
لا توجد وكلاء فرعية مدمجة. وتوضح الأمثلة كيفية تنفيذ وكيل فرعي كأداة، مع استخدام api.createTask وapi.waitForTask لدعم المهام الفرعية.
اختبر انقطاع عملية نشر بعد أن تقبل الخدمة الخارجية الطلب، وقبل أن يحفظ الوكيل نتيجته. فهذا اختبار أفضل للقدرة على التعافي من التعطل مقارنة بإيقاف عملية خاملة والتأكد من ظهور رسائلها مجدداً.
تمثل الأمثلة الرسمية، ضمن packages/durable/test/examples، أفضل نقطة بداية، لأنها تواكب تغييرات API بدرجة لا يستطيع مقال في مدونة مجاراتها. استخدمها لاختبار سير العمل الذي اخترته، ثم أضف حالات تعطل عند نقاط تنفيذ آثاره الخارجية.
يناسب Pi Durable مهام البرمجة الطويلة، وأدوات التخطيط المنظمة، وفرز الطلبات عبر webhook، وسير عمل العمليات ذي سياسات الاستئناف الواضحة. ولا تحتاج إليه للسكربتات التي تعمل مرة واحدة، أو المحادثات عديمة الحالة، أو إذا كان فريقك يحتاج إلى API مستقرة خلال الربع الحالي.
تبقى مسؤولاً عن بيانات اعتماد النموذج، والأدوات، وواجهة المستخدم، ونسخ التخزين الاحتياطية وتنظيفه، والإشراف على العملية، وضوابط أمان الإجراءات الخارجية. يشرح التوثيق أيضاً كيفية تكييف التخزين للعمل مع Bun أو Cloudflare Durable Object، لكن هذه التكاملات تحتاج إلى إعداد.

--save-exact، ثم أضف package.json وملف القفل إلى نظام التحكم بالإصدارات.requestId نفسه، وتأكد من أن الإرسال يعيد Submission الموجود بالفعل.harness.resume يستعيد العمل من قاعدة البيانات الدائمة.packages/durable/test/examples.يتيح Pi Durable استئناف العمل بعد انقطاعه، لكن القواعد التي تحدد سلوك أدواتك هي ما يقرر إن كان الاستئناف آمناً. ابدأ بوكيل واحد محدود النطاق، وتخزين SQLite دائم، واختبار تعطل مخطط له عند أخطر إجراء خارجي ينفذه. ولا توسّع استقلاليته إلا عندما يعطي هذا الاختبار نتيجة يمكنك تفسيرها.