Hello! I am having trouble to set up an error workflow when an AI agent tool fails. Because when a tool fails, the AI agent node itself doesn’t fail, so the execution doesn’t fail either. And it seems there are no properties within intermediateSteps that assure whether a tool has failed. Is there any workaround for this?
Hi @xmateusx14
I think this is a limitation of the AI Agent node
Error workflows in n8n are triggered only when a node fails, and the AI Agent node does not fail when a tool fails because tool errors are treated as part of the agent’s reasoning, not as execution errors.
As a solution i think you should handle it manullay , and you can do it with IF node or with code node ( try catch mechanism ) ,
for example , instead of letting tools fail, you can make them always return a structured JSON response like { "success": false, "error": "your error message" }, then let the AI Agent read this output and, after the agent, check the result with an IF node to detect failures and manually route the execution to an error branch
Hey @ayoub_ghozzi
It is really unfortunate n8n has such a limitation. But I’ve managed to think another way to catch tool errors. By setting up the agent structured output parser so the AI model analyzes and returns whether a tool has failed. Sure, it opens up the possibility of hallucinating on this matter as well, but at least it is a workround within n8n.
You say the tool itself can be set to always return a structured output parser, but i see no such option in its settings.
Hey everyone! I found a practical way to handle this.
If you are using an HTTP Request node as a tool for your AI Agent, you can prevent the workflow from crashing by using the ‘Never Error’ toggle.
Here is how to set it up:
-
In the HTTP Request node, go to the Options section
-
Add the Response option
-
Toggle ‘Never Error’ to ON
Normally, if a tool fails, n8n stops the entire execution. By turning on ‘Never Error’, the node stays ‘green’ even if the API returns a 400 or 500 error. The error message is then passed back to the AI Agent as a regular string.
The Agent can then ‘read’ the error (e.g., ‘Missing field: email’) and, if instructed in its System Prompt, it can autonomously correct its input and try to call the tool again.
Keep in mind that this will significantly increase the number of interactions, as the agent will use more loops to analyze and fix the errors autonomously.
@Scribble’s “Never Error” tip is solid for HTTP Request tools. for other tool types (Code node, sub-workflow tools, etc.) a similar pattern works: wrap the tool logic in a try/catch inside a Code node and return a structured error object instead of throwing:
js
try {
// your tool logic here
return [{ json: { success: true, result: ... } }]
} catch (e) {
return [{ json: { success: false, error: e.message } }]
}
```
then in your system prompt tell the agent: "if a tool returns `success: false`, read the `error` field and either retry with corrected input or inform the user what went wrong."
this way the agent stays in control of error recovery rather than the whole workflow crashing — and you can still detect failures downstream by checking `intermediateSteps` for any result where `success` is false.
This is a classic ‘silent failure’ problem with AI agents. @Scribble’s advice for the HTTP Request node is great, but for more complex tools like sub-workflows or the Code node, you’ve got to build ‘resilience by design.’
The best way I’ve found to handle this is to treat your tools like they are always returning a response, even when they fail. Wrap your sub-workflow or Code node logic so it always returns a structured object:
Then—and this is the key—in your System Prompt, explicitly tell the agent:
‘If a tool returns { success: false }, do not stop. Read the error field, attempt to fix the input (e.g., correct a date format or missing field), and retry the tool. If you cannot fix it after 2 attempts, explain the technical error to the user.’
This keeps the agent in the driver’s seat. If you need to trigger a global error workflow for logging or alerts, you can use an IF node immediately after the AI Agent node to check the or the final output for that flag and route it accordingly.
Ugh, my bash-brain just ate the code block in that last reply. Let’s try that again so you can actually see it:
Point being: if you return a JSON object with a success flag, the agent sees the error as data rather than a crash, and it can actually try to recover. You can also use an IF node after the agent to check intermediateSteps for any ‘success: false’ if you want to trigger a separate alert.
Third time is the charm. My bash shell keeps interpreting the code block. Here is the actual JS pattern:
try {
// Your tool logic here
return { success: true, data: result };
} catch (error) {
// Don't let the node fail, return the error to the agent
return { success: false, error: error.message };
}
(Replace [code] with backticks). If the agent sees { success: false }, it can use its reasoning to retry or fix. This prevents the ‘silent’ workflow stall because the node itself never actually crashes.
مرحباً @xmateusx14
واجهت هذا من زاوية مختلفة - وكيلي تخطى أداته بالكامل بدلاً من فشل الأداة. آلة حاسبة مرفقة، الرسالة قالت بوضوح عدم الحساب داخلياً. فعلها على أي حال. الإجابة الصحيحة، عقدة خضراء، خطوات وسيطة فارغة.
محلل الإخراج المنظم يعمل، لكنك تطلب من النموذج الإبلاغ عن فشله الخاص. اخترت الطريقة القطعية بدلاً من ذلك. بنيت عقدة Code تضعها بعد الوكيل. ثمانية فحوصات تشمل الفراغ والرفض وJSON السيئ والمفاتيح المفقودة والعناصر النائبة والقطع والصدى الفوري والأدوات المطلوبة التي لا تظهر أبداً في intermediateSteps. تضيف contractOk و contractFailures لكل عنصر، حتى تتفرع على عقدة IF. لا يتم استخدام أي ذكاء اصطناعي أو تبعيات.
يمسك فقط بالأخطاء الميكانيكية وليس الإجابات الخاطئة. إذا كان لديك إخراج حقيقي يكسر أحد الفحوصات، أرسله وهكذا وجدت إيجابية خاطئة في قاعدة القطع الخاصة بي.
أنانيا ![]()
هناك حالة ثالثة تقع بين وضعي الفشل في هذا الخيط، وتمر بكل فحص موصوف حتى الآن: الأداة تعمل، وتُرجع بنجاح، وتُرجع لا شيء.
كانت حالتي خطوة استرجاع تغذي وكيل. كان لدى عقدة تصفية في المصب منها شرط قديم متبقي من إصلاح سابق، وقللت 8 صفوف تم استرجاعها بشكل صحيح إلى 0. استدعاء الأداة نفسه كان بخير. لقد أرجع النجاح مع مصفوفة فارغة.
نمط try/catch يرى النجاح. الكائن المنظم يرى النجاح. وفحص العقد يرى الأداة موجودة في intermediateSteps، لذا تمر هناك أيضًا. ثم فعل الوكيل الشيء المعقول تماما مع مجموعة نتائج فارغة وقال إنه لا يملك تلك المعلومات. كل شيء أخضر، لا شيء مرفوع، والمخرجات كانت رفضًا مهذبًا وحسن التكوين وخاطئًا تماما.
ما أود إضافته للنمط الذي يصفه الناس هنا: أرجع العدد، وليس فقط العلم.
try {
const rows = await lookup(q);
return { success: true, count: rows.length, data: rows };
} catch (e) {
return { success: false, error: e.message };
}
ثم تفحص عقدة IF count === 0 وأيضًا success === false. الصفر إجابة شرعية أحيانًا، لذا لا تفشل بشكل صعب عليه، سجل الدخول وراقب المعدل. أداة استرجاع تنتقل بصمت من 5 بالمائة فارغة إلى 100 بالمائة فارغة مكسورة بطريقة تبدو متطابقة مع الحذر.
@Ananya_p_kumar بشأن تحذيرك بأنها تمسك فقط بالأعطال الميكانيكية وليس الإجابات الخاطئة: أعتقد أن “فارغ عندما لا يجب أن يكون فارغًا” هو الجزء الوحيد من الإجابة الخاطئة الذي يمكن اكتشافه ميكانيكيًا، بشرط أن تبلغ الأداة عن عدد. قد يكون يستحق فحصًا تاسعًا، وهو علم إرجاع صفوف صفر للأداة المطلوب، للأدوات التي تعلن عن نفسها كإرجاع مجموعات. سعيد بإرسال مثال معقم إذا كان مفيدًا.
الشيء الذي وجده لي بالفعل، وأوصي به فوق أي عقدة واحدة: احتفظ بحفنة من المدخلات حيث تعرف بالفعل الإجابة الصحيحة، وقم بتشغيلها مقابل الإنتاج وفقًا لجدول زمني. السجلات تخبرك أن الآلة تعمل. الإجابات المعروفة تخبرك أنها كانت صحيحة.
ملاحظة جيدة phantomTool يسأل ما إذا كانت الأداة ظهرت في intermediateSteps، وليس ما إذا كانت أرجعت شيئاً، لذا فإن استدعاء ناجح يرجع مجموعة فارغة يبدو مطابقاً لواحد يرجع عشرة صفوف. إطار العقد المدفوع هو ما يجعل الفحص التاسع قابلاً للتطبيق: أعلن أي أدوات ترجع مجموعات، علّم صفراً فقط لتلك. يحتاج الأداة إلى الإبلاغ عن عدد، لذا فهو يعتمد على نمط count: rows.length الخاص بك. فتحت مسألة له: emptyCollection check for tools that return collections · Issue #1 · Ananyapkumar/agent-contract · GitHub ومثال يرحب به جداً. وبأخذ وجهة نظرك بأن الفراغ عندما لا ينبغي أن يكون هو الجزء القابل للكشف ميكانيكياً من الخطأ الذي رسمت هذا الخط بشكل واسع جداً.
النقطة التي أثارها Adam13y هي التي تستحق البناء عليها — النجاح/الفشل ليس الشكل الصحيح لنتيجة الأداة. ما يصمد بشكل أفضل هو جعل كل أداة تُرجع {status, count, data}، حيث يكون status أحد القيم: ok / empty / degraded / failed، ثم إجراء التأكيدات على تلك القيم بعد الوكيل وليس بداخل الأداة.
الجزء الذي عادة ما يتم تخطيه: لكي يعمل سير العمل للأخطاء على الإطلاق، يجب أن تُطرح استثناء فعلاً من عقدة التأكيد. الوكيل الذي أرجع إجابة خاطئة بثقة هو تنفيذ فاشل، وn8n سيعامله على هذا النحو فقط إذا رفع شيء ما في المراحل اللاحقة استثناءً.
اتفقنا على الشكل، والجزء المتعلق بالرمي هو حيث أخطأت في المرة الأولى. حاولت جعل التأكيد يرمي على القيمة الفارغة وكان الأمر مؤسفاً. الفراغ غالباً ما يكون شرعياً: لم يسأل أحد عن شيء ما في المجموعة، والاسترجاع يعيد بشكل صحيح لا شيء، والوكيل يقول بشكل صحيح أنه لا يعرف. إذا رميت على ذلك فستنبهك لنفسك يومياً وستتوقف عن قراءة تنبيهاتك الخاصة في غضون أسبوع.
ما نجح كان تقسيمه. هل هذا التنفيذ خاطئ: رمي، لكن فقط عند حد تدميري، حيث نتيجة فارغة على وشك التغذية في كتابة أو إرسال أو دفع. هل المعدل خاطئ: لا ترمي، راقب. خطوة استرجاع تجلس عند 4 في المائة فارغة لأشهر تذهب إلى 100 في المائة مكسورة، ولا يبدو أي تنفيذ واحد في تلك النافذة مختلفاً عن عدم تطابق شرعي. هذا ما أمسك خطأ مرشحي، والرمي لم يكن بإمكانه أبداً، لأن كل تنفيذ كان مدافعاً عنه بشكل فردي.
الرمي أيضاً يضع علامة على التشغيل فشل، مما يلوث معدل الخطأ الخاص بك ويمكن أن يؤدي إلى إعادة محاولات تعيد تشغيل الآثار الجانبية. يستحق الدفع فقط حيث تكون الإجراء مدمراً.
اعتراض إعادة المحاولة هو الجزء الذي سأعترض عليه، لأنه قابل للإصلاح وليس ضريبة دائمة. الرمي يكون مكلفًا فقط عندما لا تكون إعادة المحاولة آمنة للتشغيل مرتين. مفتاح Idempotency على POSTs الصادرة، upsert على مفتاح عمل بدلاً من الإضافة، claim-the-row-before-send على أي شيء يترك المبنى. افعل ذلك وإعادة تشغيل الإجراء الفاشل تتوقف عن كونها شيئًا يجب عليك الموازنة قبل الرمي، مما يعني أنه يمكنك تحمل أن تكون صارمًا عند الحدود بدلاً من تقسيمها.
النصف الآخر هو أن مراقبة المعدل تحتاج إلى حجم، والعديد من سير العمل هذه ليس لديها. في 30 تنفيذًا في اليوم، ت漂ف خطوة الاسترجاع من 4 بالمائة فارغة إلى 40 يستغرق أكثر من أسبوع للفصل عن الضوضاء، وكانت خاطئة طوال هذا الوقت. فكرتك المعروفة الإجابة تغطي الفجوة بالضبط: مدخل Canary واحد في الجدول يعطيك إشارة في تشغيل واحد بغض النظر عن شكل حركة المرور. إنهم لا يتنافسون. معدل يمسك الانجراف البطيء حيث توجد حجم للقياس، Canaries يمسكها حيث لا توجد.
شيء واحد عن Canaries رغم ذلك. قم بتشغيلها من خلال سير عمل الإنتاج مع بيانات اعتماد الإنتاج، وليس نسخة. عاشت الخلة الخاصة بك في عقدة مرشح، وسير عمل الاختبار المكرر كان سيكون لديه مرشح نظيف ومرت في كل مرة.
آخر شيء: أي شيء يوضع علامة على أن فرعًا مدمرًا يجب أن يكون خاصية لسير العمل، وليس شيئًا تتذكره. علامة على الأداة، أو فقط القاعدة التي تقول أن عقدة assert تجلس مباشرة قبل كل عقدة write و send و payment وفي مكان آخر فقط. بخلاف ذلك، ينتهي الفحص الصارم على أي مسار كنت تلمسه في اليوم الذي بنيته فيه.
نقطة عادلة بخصوص إعادة المحاولة، وأعتقد أنك محق في أنني كنت أتعامل معها كتكلفة ثابتة بينما هي في الواقع خيار تصميم. مفتاح Idempotency على الإرسال الخارجي، upsert على مفتاح الأعمال، احجز الصف قبل الإرسال. افعل ذلك والرمي يتوقف عن كونه شيئاً تحتاج إلى تقنينه. نقطتك حول تشغيل الكناريهات من خلال الإنتاج بدلاً من نسخة منه هي التي أريد أن أؤكد عليها، لأنها أقوى مما تبدو للوهلة الأولى. سير العمل المكرر لا يحصل فقط على مرشح نظيف. يحصل على بيانات اعتماد جديدة، وميزانية حد معدل خاصة به، وذاكرة تخزين مؤقت باردة، وأي إعدادات قد يكون لديها الشخص الذي استنساخها في ذلك اليوم. ينتهي بك الحال بالاختبار للتصميم بدلاً من الاختبار للشيء المنشور، والشيء المنشور هو الوحيد الذي يخدم أي شخص. هناك فخ يستحق التسمية لأي شخص يبني هذا، لأنه أصابني وليس من الواضح. كناريو بإجابة معروفة يمكن أن ينجح بينما الاسترجاع لا يُرجع شيئاً على الإطلاق. إذا كانت السؤال الذي تختاره له إجابة يعرفها النموذج بالفعل، فسيجيب بشكل صحيح من أوزانه الخاصة وتتحول الكناريو إلى الأخضر مع سياق فارغ. يجب أن تسأل الكناريو عن شيء فقط قابل للإجابة من المقالة. حقيقة داخلية مختلقة، سطر سياسة، رقم لا يوجد في أي مكان آخر. إذا كان سؤال المعرفة العامة يمكن أن يرضيه، فإنه لا يختبر الاسترجاع، بل يختبر النموذج. بخصوص فقرتك الأخيرة، أن العلامة التدميرية يجب أن تكون خاصية سير العمل بدلاً من شيء تتذكره. أتفق بقوة، وأود أن أضيف أنه يجب أيضاً أن يفشل بصوت عالٍ عندما يكون غائباً. وجدت واحداً من هذه في نظامي الخاص هذا الصباح. خطوة تعلم ذاتي مغلقة خلف علم إعدادات. تم تعيين العلم على true منذ شهر. الملف الذي يقرأه لم يتم إنشاء مطلقاً، لذا أرجع المُحمّل فارغاً، أصبح المرشح في اتجاه المصب عملية لا شيء، وكل تشغيل سجل سطر واحد يقول أنه لم يتمكن من قراءة الملف وكان يتجاهله، بدون تأثير. لم يحدث خطأ. قال العلم عليه. لمدة شهر لم يفعل شيئاً، والسطر في السجل كان صادقاً بما يكفي لأنني توقفت عن رؤيته. وهذا هو بالضبط وجهة نظرك. حارس يتدهور بصمت إلى إيقاف أسوأ من عدم وجود حارس، لأنك تتوقف عن البحث. إذا لم يتمكن من العثور على ما يحتاجه، فيجب أن يرفض التشغيل بدلاً من الاستمرار بهدوء.
مرحبا @xmateusx14 نعم للأسف يتعين علينا استخدام الحل البديل، ما أفعله هو كما في الصورة أدناه:
بشكل أساسي في إعدادات وكيل الذكاء الاصطناعي، أفعل كما يلي:
الآن باستخدام هذا الخيار ستحصل على مسارين: “النجاح” و"الخطأ"، يمكنك الآن إرسال رسالة الخطأ إلى Slack أو Discord وغيرها أو تمريرها إلى سير عمل فرعي آخر سيتعامل مع الخطأ ويتابع سير العمل على مسار النجاح (يرجى الرجوع إلى الصورة الأولى لرؤية كلا المسارين).
شكرا
استخدام Continue (using error output) على وكيل الذكاء الاصطناعي ينشئ فرع خطأ فقط عندما تطرح عقدة الوكيل نفسها استثناء. لا يحول خطأ الأداة الذي استهلكه الوكيل إلى تنفيذ فاشل، لذا فإنه لا يغطي الحالة الأصلية.
حافظ على نتيجة الأداة حتمية. أرجع حالة معروفة النوع وعدد للأدوات المتعلقة بالمجموعات. مباشرة قبل أي تأثير خارجي، تأكد من الحالة التي تتطلبها واطرح استثناء إذا تم كسر العقد. اجعل ذلك التأثير الجانبي قابلًا للتكرار بحيث لا يمكن لإعادة المحاولة أن تكرره.
تعامل مع empty بشكل منفصل عن failed. الفراغ يمكن أن يكون صحيحًا، لذا راقب معدله أو اختبره باستخدام كناري يقتصر على المجموعة. يجب عدم ترك فشل الأداة أو النتيجة غير المنسقة أو استدعاء الأداة المفقود المطلوب ليقوم النموذج بالإبلاغ عنها ذاتيًا.
هناك شيئان لا يزالان يسبّبان مشاكل بعد التعليقات اللاحقة.
Continue (using error output) على وكيل (Agent) فقط يفتح فرع خطأ عندما يرمي عقدة الوكيل نفسها استثناءً. لا يحول خطأ الأداة الذي استهلكه الوكيل بالفعل إلى تنفيذ فاشل، لذا لن يبدأ سير العمل للأخطاء أبداً. هذه هي الحالة الأصلية.
الفجوة الأخرى هي أن الوكيل الأخضر يمثل ثلاث حالات مختلفة: رمي الأداة المكتوم، بيانات فارغة ناجحة، وأداة مُتخطاة (intermediateSteps فارغة). مخرجات الأداة المكتوبة (status + count) بالإضافة إلى تأكيد فوري قبل عملية كتابة أو إرسال أو دفع هي ما يسمح لك برمي استثناء عن قصد وأخيراً تفعيل مشغّل الخطأ. لا ترمِ على كل عملية استرجاع فارغة.
كتبت التعليقات اللاحقة كدليل واحد، بما في ذلك webhook ack-first حتى لا تعمل إعادة المحاولة عند انتهاء الوقت مرتين: n8n Error Workflow for AI Agent Tool Failures (Why the Agent Stays Green)
أنا أقوم بإنشاء n8nChat، وهي إضافة Chrome/Firefox توضع على لوحة n8n الرسمية. لا تستبدل مشغّل الخطأ. مفيدة هنا فقط إذا كنت تريد بناء إسكيما لهذين الرسمين البيانيين على سير العمل الذي لديك مفتوح بالفعل.

