التجارب
وكلاء ACP المرتبطين بالخيوط
نظرة عامة
تحدد هذه الخطة كيفية دعم OpenClaw لوكلاء ترميز ACP في القنوات القادرة على التعامل مع الخيوط (Discord أولاً) بدورة حياة واستعادة على مستوى الإنتاج. المستند ذو الصلة:
تجربة المستخدم المستهدفة:
- يقوم المستخدم بإنشاء أو تركيز جلسة ACP في خيط
- يتم توجيه رسائل المستخدم في ذلك الخيط إلى جلسة ACP المرتبطة
- ينتج الوكيل مخرجات تتدفق مرة أخرى إلى شخصية نفس الخيط
- يمكن أن تكون الجلسة مستمرة أو لمرة واحدة مع ضوابط تنظيف صريحة
ملخص القرار
التوصية طويلة المدى هي هندسة معمارية هجينة:
- نواة OpenClaw تملك مخاوط مستوى التحكم في ACP
- هوية الجلسة وبيانات التعريف
- ربط الخيوط وقرارات التوجيه
- ضمانات التسليم وقمع التكرارات
- دلالات تنظيف دورة الحياة والاستعادة
- خلفية وقت تشغيل ACP قابلة للإضافة
- الخلفية الأولى هي خدمة إضافة مدعومة بـ acpx
- وقت التشغيل يتعامل مع نقل ACP، والطابور، والإلغاء، وإعادة الاتصال
يجب ألا يعيد OpenClaw تنفيذ آليات النقل الداخلية لـ ACP في النواة. يجب ألا يعتمد OpenClaw على مسار اعتراض يعتمد فقط على الإضافات للتوجيه.
الهندسة المعمارية المثالية (الهدف النهائي)
معاملة ACP كمستوى تحكم من الدرجة الأولى في OpenClaw، مع محولات وقت تشغيل قابلة للإضافة. الضمانات غير القابلة للتفاوض:
- كل ربط خيط ACP يشير إلى سجل جلسة ACP صالح
- كل جلسة ACP لها حالة دورة حياة صريحة (
creating,idle,running,cancelling,closed,error) - كل تشغيل ACP له حالة تشغيل صريحة (
queued,running,completed,failed,cancelled) - الإنشاء، والربط، والوضع الأولي في الطابور هي عمليات ذرية
- إعادة محاولة الأوامر لا تنتج تأثيرات جانبية (لا توجد تشغيلات مكررة أو مخرجات Discord مكررة)
- مخرجات قناة الخيط المرتبط هي إسقاط لأحداث تشغيل ACP، وليست تأثيرات جانبية عشوائية
نموذج الملكية طويل المدى:
AcpSessionManagerهو الكاتب الوحيد والمنسق لـ ACP- يعيش المدير في عملية البوابة أولاً؛ يمكن نقله إلى عملية مساعدة مخصصة لاحقًا خلف نفس الواجهة
- لكل مفتاح جلسة ACP، يمتلك المدير ممثلًا واحدًا في الذاكرة (تنفيذ أوامر متسلسل)
- المحولات (
acpx، خلفيات مستقبلية) هي تنفيذات للنقل/وقت التشغيل فقط
نموذج الاستمرارية طويل المدى:
- نقل حالة مستوى التحكم في ACP إلى مخزن SQLite مخصص (وضع WAL) تحت دليل حالة OpenClaw
- ا لاحتفاظ بـ
SessionEntry.acpكإسقاط توافق أثناء الهجرة، وليس كمصدر للحقيقة - تخزين أحداث ACP بطريقة الإلحاق فقط لدعم إعادة التشغيل، واستعادة بعد التعطل، والتسليم الحتمي
استراتيجية التسليم (جسر نحو الهدف النهائي)
- جسر قصير المدى
- الاحتفاظ بميكانيكيات ربط الخيوط الحالية وسطح تكوين ACP الحالي
- إصلاح أخطاء فجوة بيانات التعريف وتوجيه أدوار ACP عبر فرع ACP أساسي واحد
- إضافة مفاتيح عدم إنتاج التأثيرات الجانبية وفحوصات التوجيه الفاشلة مغلقة على الفور
- التحويل طويل المدى
- نقل مصدر الحقيقة لـ ACP إلى قاعدة بيانات مستوى التحكم + ممثلين
- جعل تسليم الخيط المرتبط يعتمد فقط على الإسقاط القائم على الأحداث
- إزالة سلوك الرجوع القديم الذي يعتمد على بيانات تعريف إدخال الجلسة الانتهازية
لماذا ليس فقط إ ضافات بحتة
خطافات الإضافة الحالية ليست كافية للتوجيه الشامل لجلسات ACP بدون تغييرات في النواة.
- التوجيه الوارد من ربط الخيط يحل إلى مفتاح جلسة في إرسال النواة أولاً
- خطافات الرسائل هي من نوع أطلق وانسى ولا يمكنها إيقاف مسار الرد الرئيسي
- أوامر الإضافة جيدة لعمليات التحكم ولكن ليس لاستبدال تدفق الإرسال لكل دور في النواة
النتيجة:
- وقت تشغيل ACP يمكن أن يكون قابلاً للإضافة
- فرع توجيه ACP يجب أن يوجد في النواة
الأساس الحالي لإعادة الاستخدام
تم تنفيذه بالفعل ويجب أن يظل معياريًا:
- هدف ربط الخيط يدعم
subagentوacp - تجاوز توجيه الخيط الوارد يحل عن طريق الربط قبل الإرسال العادي
- هوية الخيط الصادرة عبر webhook في تسليم الرد
- تدفق
/focusو/unfocusمع توافق هدف ACP - مخزن ربط مستمر مع الاستعادة عند بدء التشغيل
- دورة حياة فك الربط عند الأرشفة، والحذف، وفك التركيز، وإعادة التعيين، والحذف
توسع هذه الخطة هذا الأساس بدلاً من استبداله.
الهندسة المعمارية
نموذج الحدود
النواة (يجب أن تكون في نواة OpenClaw):
- فرع إرسال وضع جلسة ACP في خط أنابيب الرد
- تحكيم التسليم لتجنب التكرار بين القناة الأصلية والخيط
- استمرارية مستوى التحكم في ACP (مع إسقاط توافق
SessionEntry.acpأثناء الهجرة) - دلالات فك الربط لدورة الحياة وفصل وقت التشغيل المرتبطة بإعادة تعيين/حذف الجلسة
خلفية الإضافة (تنفيذ acpx):
- إشراف عامل وقت تشغيل ACP
- استدعاء عملية acpx وتحليل الأحداث
- معالجات أوامر ACP (
/acp ...) وتجربة مستخدم المشغل - الإعدادات الافتراضية والت شخيصات الخاصة بالخلفية
نموذج ملكية وقت التشغيل
- عملية بوابة واحدة تملك حالة تنسيق ACP
- يتم تشغيل تنفيذ ACP في عمليات فرعية تحت الإشراف عبر خلفية acpx
- استراتيجية العملية هي طويلة الأمد لكل مفتاح جلسة ACP نشط، وليس لكل رسالة
هذا يتجنب تكلفة بدء التشغيل في كل مطالبة ويبقي دلالات الإلغاء وإعادة الاتصال موثوقة.
عقد وقت التشغيل الأساسي
إضافة عقد وقت تشغيل ACP أساسي حتى لا يعتمد كود التوجيه على تفاصيل CLI ويمكنه تبديل الخلفيات دون تغيير منطق الإرسال:
export type AcpRuntimePromptMode = "prompt" | "steer";
export type AcpRuntimeHandle = {
sessionKey: string;
backend: string;
runtimeSessionName: string;
};
export type AcpRuntimeEvent =
| { type: "text_delta"; stream: "output" | "thought"; text: string }
| { type: "tool_call"; name: string; argumentsText: string }
| { type: "done"; usage?: Record<string, number> }
| { type: "error"; code: string; message: string; retryable?: boolean };
export interface AcpRuntime {
ensureSession(input: {
sessionKey: string;
agent: string;
mode: "persistent" | "oneshot";
cwd?: string;
env?: Record<string, string>;
idempotencyKey: string;
}): Promise<AcpRuntimeHandle>;
submit(input: {
handle: AcpRuntimeHandle;
text: string;
mode: AcpRuntimePromptMode;
idempotencyKey: string;
}): Promise<{ runtimeRunId: string }>;
stream(input: {
handle: AcpRuntimeHandle;
runtimeRunId: string;
onEvent: (event: AcpRuntimeEvent) => Promise<void> | void;
signal?: AbortSignal;
}): Promise<void>;
cancel(input: {
handle: AcpRuntimeHandle;
runtimeRunId?: string;
reason?: string;
idempotencyKey: string;
}): Promise<void>;
close(input: { handle: AcpRuntimeHandle; reason: string; idempotencyKey: string }): Promise<void>;
health?(): Promise<{ ok: boolean; details?: string }>;
}
تفاصيل التنفيذ:
- الخلفية الأولى:
AcpxRuntimeيتم ش حنها كخدمة إضافة - تحل النواة وقت التشغيل عبر السجل وتفشل مع خطأ مشغل صريح عندما لا يكون هناك خلفية وقت تشغيل ACP متاحة
نموذج بيانات مستوى التحكم والاستمرارية
مصدر الحقيقة طويل المدى هو قاعدة بيانات ACP SQLite مخصصة (وضع WAL)، للتحديثات المعاملية والاستعادة الآمنة من التعطل:
acp_sessionssession_key(pk),backend,agent,mode,cwd,state,created_at,updated_at,last_error
acp_runsrun_id(pk),session_key(fk),state,requester_message_id,idempotency_key,started_at,ended_at,error_code,error_message
acp_bindingsbinding_key(pk),thread_id,channel_id,account_id,session_key(fk),expires_at,bound_at
acp_eventsevent_id(pk),run_id(fk),seq,kind,payload_json,created_at
acp_delivery_checkpointrun_id(pk/fk),last_event_seq,last_discord_message_id,updated_at
acp_idempotencyscope,idempotency_key,result_json,created_at, unique(scope, idempotency_key)
export type AcpSessionMeta = {
backend: string;
agent: string;
runtimeSessionName: string;
mode: "persistent" | "oneshot";
cwd?: string;
state: "idle" | "running" | "error";
lastActivityAt: number;
lastError?: string;
};
قواعد التخزين:
- الاحتفاظ بـ
SessionEntry.acpكإسقاط توافق أثناء الهجرة - تبقى معرفات العمليات والمقابس في الذاكرة فقط
- دورة الحياة المستمرة وحالة التشغيل تعيش في قاعدة بيانات ACP، وليس في JSON الجلسة العام
- إذا مات مالك وقت التشغيل، تعيد البوالة التمييه من قاعدة بيانات ACP وتستأنف من نقاط التفتيش
التوجيه والتسليم
الوارد:
- الاحتفاظ بالبحث الحالي لربط الخيوط كخطوة توجيه أولى
- إذا كان الهدف المرتبط هو جلسة ACP، قم بتوجيهها إلى فرع وقت تشغيل ACP بدلاً من
getReplyFromConfig - الأمر الصريح
/acp steerيستخدمmode: "steer"
الصادر:
- يتم تسوية تدفق أحداث ACP إلى أجزاء رد OpenClaw
- يتم حل هدف التسليم عبر مسار الوجهة المرتبط الحالي
- عندما يكون خيط مرتبط نشطًا لدور تلك الجلسة، يتم قمع اكتمال القناة الأصلية
سياسة البث:
- بث المخرجات الجزئية مع نافذة دمج
- فاصل زمني أدنى قابل للتكوين وأقصى بايتات للقطعة للبقاء ضمن حدود معدل Discord
- يتم دائمًا إصدار الرسالة النهائية عند الاكتمال أو الفشل
آلات الحالة وحدود المعاملات
آلة حالة الجلسة:
creating -> idle -> running -> idlerunning -> cancelling -> idle | erroridle -> closederror -> idle | closed
آلة حالة التشغيل:
queued -> running -> completedrunning -> failed | cancelledqueued -> cancelled
حدود المعاملات المطلوبة:
- معاملة الإنشاء
- إنشاء صف جلسة ACP
- إنشاء/تحديث صف ربط خيط ACP
- وضع صف تشغيل أولي في الطابور
- معاملة الإغلاق
- وضع علامة على الجلسة كمغلقة
- حذف/انتهاء صلاحية صفوف الربط
- كتابة حدث إغلاق نهائي
- معاملة الإلغاء
- وضع علامة على التشغيل المستهدف بالإلغاء/ملغي مع مفتاح عدم إنتاج التأثيرات الجانبية
لا يُسمح بنجاح جزئي عبر هذه الحدود.
نموذج المم ثل لكل جلسة
AcpSessionManager يشغل ممثلًا واحدًا لكل مفتاح جلسة ACP:
- صندوق بريد الممثل يسلسل التأثيرات الجانبية
submit,cancel,close, وstream - يمتلك الممثل تمييه المقبض وقت التشغيل ودورة حياة عملية محول وقت التشغيل لتلك الجلسة
- يكتب الممثل أحداث التشغيل بالترتيب (
seq) قبل أي تسليم إلى Discord - يقوم الممثل بتحديث نقاط تفتيش التسليم بعد الإرسال الصادر الناجح
هذا يزيل السباقات عبر الأدوار ويمنع المخرجات المكررة أو غير المرتبة للخيوط.
عدم إنتاج التأثيرات الجانبية وإسقاط التسليم
يجب أن تحمل جميع إجراءات ACP الخارجية مفاتيح عدم إنتاج التأثيرات الجانبية:
- مفتاح عدم إنتاج التأثيرات الجانبية للإنشاء
- مفتاح عدم إنتاج التأثيرات الجانبية للمطالبة/التوجيه
- مفتاح عدم إنتاج التأثيرات الجانبية للإلغاء
- مفتاح عدم إنتاج التأثيرات الجانبية للإغلاق
قواعد التسليم:
- يتم اشتقاق رسائل Discord من
acp_eventsبالإضافة إلىacp_delivery_checkpoint - تستأنف إعادة المحاولة من نقطة التفتيش دون إعادة إرسال القطع التي تم تسليمها بالفعل
- انبعاث الرد النهائي هو مرة واحدة بالضبط لكل تشغيل من منطق الإسقاط
الاستعادة والشفاء الذاتي
عند بدء تشغيل البوابة:
- تحميل جلسات ACP غير النهائية (
creating,idle,running,cancelling,error) - إعادة إنشاء الممثلين بكسل عند أول حدث وارد أو بجدوى ضمن الحد الأقصى المُكون
- تسوية أي تشغيلات
runningتفتقد نبضات الحياة ووضع علامةfailedأو الاستعادة عبر المحول
عند رسالة خيط Discord واردة:
- إذا كان الربط موجودًا ولكن جلسة ACP مفقودة، فشل مغلق مع رسالة ربط قديمة صريحة
- اختياريًا، فك الربط التلقائي للربط القديم بعد التحقق الآمن للمشغل
- عدم توجيه روابط ACP القديمة بصمت إلى مسار LLM العادي
دورة الحياة والسلامة
العمليات المدعومة:
- إلغاء التشغيل الحالي:
/acp cancel - فك ربط الخيط:
/unfocus - إغلاق جلسة ACP:
/acp close - الإغلاق التلقائي للجلسات الخاملة حسب TTL الفعال
سياسة TTL:
- TTL الفعال هو الحد الأدنى من
- TTL العام/للجلسة
- TTL ربط خيط Discord
- TTL مالك وقت تشغيل ACP
ضوابط السلامة:
- قائمة السماح لوكلاء ACP بالاسم
- تقييد جذور مساحة العمل لجلسات ACP
- قائمة السماح لبيئة التشغيل للتمرير
- الحد الأقصى للجلسات المتزامنة لـ ACP لكل حساب وعالميًا
- تراجع إعادة التشغيل المحدود لتعطلات وقت التشغيل
سطح التكوين
المفاتيح الأساسية:
acp.enabledacp.dispatch.enabled(مفتاح إيقاف توجيه ACP مستقل)acp.backend(الافتراضيacpx)acp.defaultAgentacp.allowedAgents[]acp.maxConcurrentSessionsacp.stream.coalesceIdleMsacp.stream.maxChunkCharsacp.runtime.ttlMinutesacp.controlPlane.store(sqliteافتراضي)acp.controlPlane.storePathacp.controlPlane.recovery.eagerActorsacp.controlPlane.recovery.reconcileRunningAfterMsacp.controlPlane.checkpoint.flushEveryEventsacp.controlPlane.checkpoint.flushEveryMsacp.idempotency.ttlHourschannels.discord.threadBindings.spawnAcpSessions
مفاتيح الإضافة/الخلفية (قسم إضافة acpx):
- تجاوزات أمر/مسار الخلفية
- قائمة السماح لبيئة التشغيل للخلفية
- الإعدادات المسبقة لكل وكيل للخلفية
- مهلات بدء/إيقاف الخلفية
- الحد الأقصى للتشغيلات قيد التنفيذ لكل جلسة للخلفية