تم إيقاف تنفيذ وكيل AI للبث (isArtificialRecoveredEventItem) عند قطع اتصال العميل أثناء البث — هل هناك طريقة للاستمرار في البث وترك التنفيذ ينتهي من جانب الخادم؟

عند تفعيل استجابة البث (Response Streaming)، إذا قطع العميل الاتصال (تحديث المتصفح) بينما وكيل الذكاء الاصطناعي لا يزال يبث، يتم إيقاف التنفيذ ويظهر { “isArtificialRecoveredEventItem”: true } مع “تم إيقاف التنفيذ عند هذه العقدة.” أود أن ينتهي التنفيذ من جانب الخادم حتى لو قطع العميل الاتصال، مع الاحتفاظ ببث البيانات.

إعادة الإنتاج البسيطة (n8n عادي، بدون عقد مخصصة)

  1. Chat Trigger (أو Webhook مع Response Mode: Streaming).
  2. عقدة AI Agent مع enableStreaming: true، متصلة بـ:
  • أي نموذج دردشة (مثل OpenAI Chat Model)،
  • أي أداة واحدة تستغرق بضع ثوانٍ (مثل أداة HTTP Request تصل إلى نقطة نهاية بطيئة — أي شيء يبقي الوكيل مشغولاً لفترة كافية للتحديث).
  1. افتح الدردشة المدمجة، وأرسل رسالة تجعل الوكيل استدعاء الأداة.
  2. حدّث الصفحة على الفور، بينما لا يزال يبث.
  3. افتح التنفيذ → تم إيقافه، مخرجات AI Agent = { “isArtificialRecoveredEventItem”: true }.

البيئة

  • n8n: السحابة، الإصدار 2.27.4
  • عقدة AI Agent v3.1, Webhook v2.1 (responseMode: streaming)

المتوقع مقابل الفعلي

  • المتوقع: فقدان العميل للبث لا يجب أن يوقف التشغيل؛ يجب أن ينتهي الوكيل (وأي آثار جانبية للأداة) من جانب الخادم.
  • الفعلي: يتم إيقاف التشغيل في اللحظة التي ينقطع فيها اتصال البث → عنصر متعافي/صناعي.

ما حاولت

  • تعطيل enableStreaming على عقدة AI Agent يتجنبها — لكن بعد ذلك لا يوجد بث (تعطيل البث على أي من العقدتين يعود إلى request-response).
  • أعرف أن النمط الفوري / webhook المزدوج غير المتزامن موجود، لكنه يفقد البث المباشر.

السؤال

هل هناك طريقة مدعومة لفصل عمر التنفيذ عن اتصال HTTP البث — أي الاحتفاظ ببث البيانات مفعلاً ولكن السماح بانتهاء التنفيذ (بدون إيقاف) عند قطع العميل الاتصال أثناء البث؟ أي إعداد أو نمط موصى به؟


هل تريد مني:

  1. تصدير سير عمل بسيط للغاية (Chat Trigger + AI Agent + أداة واحدة لمحاكاة التأخر + LLM) إلى JSON لتضيفه — يمكن إعادة الإنتاج على الفور، مما يزيد بشكل كبير من احتمالية حصولك على المساعدة؟
  2. أم الاحتفاظ بهذا والقيام بملء الإصدار + إضافة لقطات شاشة؟

عند تفعيل استجابة البث (Response Streaming)، إذا قطع العميل الاتصال (تحديث المتصفح) بينما وكيل الذكاء الاصطناعي لا يزال يبث، يتم إيقاف التنفيذ ويظهر { “isArtificialRecoveredEventItem”: true } مع “تم إيقاف التنفيذ عند هذه العقدة.” أود أن ينتهي التنفيذ من جانب الخادم حتى لو قطع العميل الاتصال، مع الاحتفاظ ببث البيانات.

إعادة الإنتاج البسيطة (n8n عادي، بدون عقد مخصصة)

  1. Chat Trigger (أو Webhook مع Response Mode: Streaming).
  2. عقدة AI Agent مع enableStreaming: true، متصلة بـ:
  • أي نموذج دردشة (مثل OpenAI Chat Model)،
  • أي أداة واحدة تستغرق بضع ثوانٍ (مثل أداة HTTP Request تصل إلى نقطة نهاية بطيئة — أي شيء يبقي الوكيل مشغولاً لفترة كافية للتحديث).
  1. افتح الدردشة المدمجة، وأرسل رسالة تجعل الوكيل استدعاء الأداة.
  2. حدّث الصفحة على الفور، بينما لا يزال يبث.
  3. افتح التنفيذ → تم إيقافه، مخرجات AI Agent = { “isArtificialRecoveredEventItem”: true }.

البيئة

  • n8n: السحابة، الإصدار ‹ملء الإصدار›
  • عقدة AI Agent v3.1, Webhook v2.1 (responseMode: streaming)

المتوقع مقابل الفعلي

  • المتوقع: فقدان العميل للبث لا يجب أن يوقف التشغيل؛ يجب أن ينتهي الوكيل (وأي آثار جانبية للأداة) من جانب الخادم.
  • الفعلي: يتم إيقاف التشغيل في اللحظة التي ينقطع فيها اتصال البث → عنصر متعافي/صناعي.

ما حاولت

  • تعطيل enableStreaming على عقدة AI Agent يتجنبها — لكن بعد ذلك لا يوجد بث (تعطيل البث على أي من العقدتين يعود إلى request-response).
  • أعرف أن النمط الفوري / webhook المزدوج غير المتزامن موجود، لكنه يفقد البث المباشر.

@sawsew467 لا توجد أزرار تحكم مدمجة لأي من الثلاثة، البث يربط التنفيذ بالاتصال الحي لذلك قطع الاتصال يفسده (تلك العنصرة المستردة هي علامة “تم الإيقاف قبل الانتهاء” العامة من n8ns، وليست OOM حقيقية)، ولا يوجد شيء موثق لفصله أو إعادة الربط. الحل هو عدم تشغيل العمل الذي يجب أن يبقى في التنفيذ المبث، وإرسال الوكيل وكتابة الذاكرة إلى تنفيذ منفصل بدون بث ينتهي من جانب الخادم، واسمح للعميل بإعادة قراءة السجل عند إعادة التحميل. وأزل الأدوات التي لها آثار جانبية مثل إرسال البريد الإلكتروني من التيار حتى لا تنطلق في دور لا يستمر أبداً.

مرحباً @sawsew467 ،

علامة isArtificialRecoveredEventItem تشير إلى أن التنفيذ توقف بشكل مفاجئ بدلاً من إلغائه بشكل نظيف. عندما ينقطع الاتصال بالمتصفح، يُغلق مقبس TCP، وتستدعي res.write() التالية داخل مُرسل الأجزاء المتدفقة في n8n خطأ EPIPE. ينتشر هذا الخطأ عبر سلسلة رد نداء LangChain إلى محرك سير العمل، مما يسبب توقف التنفيذ في منتصف الطريق. تقوم خدمة الاستعادة بعد ذلك بملء العنصر النائب الاصطناعي لأي عقدة بدأت ولم تحفظ مخرجاتها أبداً.

وبالتالي فإن اتصال SSE والتنفيذ من جانب الخادم مرتبطان معمارياً في تطبيق البث الحالي في n8n. لا توجد علامة إعدادات لفصلهما.

خياراتك الفعلية:

1. تعطيل البث على عقدة AI Agent: ما حاولته بالفعل، لكن من الجدير بالذكر بوضوح: يعمل التنفيذ حتى الانتهاء من جانب الخادم بدون أي خطر قطع الاتصال، والاستجابة الكاملة ترجع عند انتهاء سير العمل. المقابلة بشأن تجربة المستخدم حقيقية لكن التنفيذ موثوق به.

2. الرد فوراً، ثم الاستقصاء: استخدم عقدة Webhook مضبوطة على “Respond Immediately”. تُرجع معرّف التنفيذ على الفور، ويعمل سير العمل بالكامل في الخلفية بدون استجابة HTTP مرفقة (لا توجد اتصالات SSE قابلة للقطع)، ويقوم العميل بالاستقصاء من GET /api/v1/executions/{id} للحصول على النتيجة. ستكتمل الأدوات البطيئة دائماً. تفقد تجربة البث لكنك تكتسب التنفيذ الحتمي. على Cloud أنت ضمن فترة انتظار التنفيذ لمدة 5 دقائق طالما أن HTTP Request ليس بطيئاً بشكل سخيف.

3. عمال وضع الطابور: ذاتية الاستضافة فقط، غير متاحة على Cloud. حتى إذاً، من غير الواضح ما إذا كانت فشل كتابة البث على العملية الرئيسية تفصل بالكامل عن حالة تنفيذ العامل.

بالنسبة لإعدادك بشكل خاص، الخيار 2 هو ربما المسار الأفضل إذا كنت تحتاج إلى اكتمال الأدوات دائماً. تجربة الاستقصاء أقل أناقة من SSE لكنها أكثر قابلية للتنبؤ بكثير من الأمل في بقاء العميل متصلاً.

إذا كان البث مع تحمل القطع حرجاً، فهذا سيتطلب تغييراً في كيفية تعامل n8n مع أخطاء كتابة SSE، وتحديداً عدم نشرها مرة أخرى في محرك التنفيذ.

كل من الردين أعلاه محق في أن بث الوكيل المدمج في n8n يربط العمل بالطلب الحي، لذا فإن قطع الاتصال يهدم التنفيذ، وليس هناك علم لفصلهما اليوم. لكن يمكنك التمتع ببث UX مضمون وإكمال مضمون على جانب الخادم في نفس الوقت. الحيلة هي التوقف عن البث من خلال طلب n8n ونقل البث إلى قناة يشترك بها العميل بشكل مستقل.

شكل يعمل:

  1. تعامل مع الدور كعمل خلفي دائم. خذ الخيار 2 من PurveshGandhi كالأساس: يرد webhook فوراً برقم معرف للدور، يعمل الوكيل حتى الاكتمال على جانب الخادم بدون SSE مرفق، وتحدث كتابة الذاكرة بغض النظر عما يحدث. هذا وحده يجعل العمل الذي يجب أن يستمر محمياً من قطع الاتصال.

  2. استعد البث بكتابة القطع إلى قناة خارجية، وليس إلى HTTP response. مع إنتاج الدور للمخرجات، اكتبها إلى شيء يمكن للمتصفح الاشتراك فيه بشكل مستقل: صف Supabase realtime، أو Redis pub/sub، أو Ably، أو حتى عمود partial_response يستقصي عنه العميل بضع مرات في الثانية. يقرأ المتصفح من تلك القناة، لا من SSE في n8n. الآن قطع الاتصال يسقط جانب القراءة فقط، التنفيذ يستمر في العمل، وعند إعادة التحميل يعيد العميل الاشتراك ويلحق بالأثر من الجزء المخزن. هذه هي إجابة الحصول على كليهما: العمل مقيد بالوظيفة، البث مقيد بالمخزن.

  3. إذا كان سلاسة مستوى الرمز مهماً حقاً، قم بنمذجة البث في أنبوب رقيق خارج n8n (دالة حافة صغيرة تبث رموز النموذج للعميل وتنشر النسخة النهائية مرة أخرى إلى n8n لكتابة الذاكرة الدائمة وأي أدوات). يبقى n8n هو نظام السجل، دالة الحافة تكون مجرد الأنبوب.

واحدة أخرى، بروح نقطة achamm حول الأدوات ذات التأثير الجانبي: احتفظ بكل تأثير جانبي، أرسل بريداً إلكترونياً، اكتب إلى CRM، أي شيء يكلف مالاً، مسيج خلف الدور الملتزم ومفتاح برقم معرف الدور، حتى لا يمكن لدور تم إعادة محاولته أو دور غير مكتمل أن يطلقه مرتين. البث لا يجب أن يكون أبداً ما يقرر ما إذا كان التأثير الجانبي قد حدث.

إذاً أنت في الواقع لا تضطر للاختيار. قيد التنفيذ بوظيفة دائمة، قيد البث بقناة خارجية، وقطع اتصال العميل يتوقف عن الأهمية.

مرحبًا :waving_hand:
أعتقد أنني فهمت المشكلة — هذه حالة حدية شائعة جدًا مع n8n AI Agent + streaming عندما ينقطع اتصال العميل (تحديث المتصفح / إعادة الاتصال).

ما يحدث هنا بشكل أساسي:

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

سأتعامل مع هذا باعتباره دورتي حياة مقترنة حالياً:

  1. دورة حياة بث العميل
    اتصال المتصفح/العميل يريد رموز/أحداث جزئية الآن.

  2. دورة حياة تنفيذ الخادم
    قد تحتاج عملية الوكيل إلى الانتهاء حتى لو قطع العميل الاتصال.

إذا كانت مرتبطة بنفس اتصال HTTP، فإن قطع الاتصال يمكن أن يصبح إشارة إلغاء التنفيذ. بالنسبة للوكلاء طويلي المدى، سأفكك العادة عادة:

  • الطلب يبدأ مهمة ويُرجع job_id؛
  • سير العمل من جانب الخادم يستمر بشكل مستقل؛
  • نقطة البث تشترك فقط في أحداث المهمة؛
  • إذا قُطع البث، تبقى المهمة قيد التشغيل؛
  • يمكن للعميل إعادة الاتصال باستخدام job_id وجلب الحالة/الأحداث/النتيجة الحالية؛
  • الحالات النهائية هي النجاح والفشل والملغاة من قبل المستخدم والمهلة الزمنية المنتهية.

التمييز المهم هو “العميل اختفى” مقابل “المستخدم أراد الإلغاء بقصد.” يجب أن تكون هذه حالات منفصلة.

إذا كان مسار البث الحالي في n8n يربط قطع الاتصال بالإلغاء، فالنمط الأأمن هو وضع الوكيل طويل المدى خلف طبقة مهام دائمة ومعاملة البث كمراقب، وليس مالك التنفيذ.

سؤال واحد غير حساس: هل تحتاج المتصفح إلى استقبال كل رمز وسيط، أم يكفي بث الحالة/الأحداث وجلب النتيجة النهائية عند انتهاء المهمة؟

أهلاً وسهلاً @sawsew467!

هذا قيد معماري حالي في n8n: عندما يكون البث مفعلاً، تكون دورة حياة التنفيذ مرتبطة باتصال الدفع، لذا فإن قطع الاتصال يشير إلى الإجهاض. لا توجد إعدادات مدمجة لفصلهما في الوقت الحالي.

أقرب نمط عامل في n8n اليوم: استخدم Webhook عادي (بدون بث) كنقطة دخول، أعد الرد فوراً برسالة job_id إلى العميل باستخدام عقدة “Respond to Webhook”، ثم قم بتنفيذ عمل الوكيل الفعلي كسير عمل فرعي باستخدام “Execute Workflow” مع ضبطه على وضع “Run in Background”. يقوم العميل بالاستقصاء عن طريق webhook GET ثانٍ باستخدام job_id لجلب النتيجة بمجرد كتابتها في قاعدة بيانات أو مستودع بيانات ثابت. قد تفقد البث الفوري للرموز، لكن تنفيذ الوكيل سيكتمل بغض النظر عن حالة العميل - وهذا يبدو وكأنه ما تحتاجه بالفعل هنا.