يستدعي الوكيل نقطة نهاية تحويل ترميز الفيديو الخاصة بك. تعيد نقطة النهاية رمز 202 Accepted ومعرف مهمة. الوكيل، الذي ليس لديه أي فكرة عما يعنيه 202 في نظامك، يبلغ بأن التحويل اكتمل وينتقل إلى الخطوة التالية، التي تقرأ ملفًا غير موجود بعد.
العمليات طويلة الأمد تعطل الوكلاء بطريقة محددة. المكالمة المتزامنة لها عقد واضح: ترسل، تنتظر، تحصل على إجابة. المكالمة غير المتزامنة تقسم ذلك إلى بداية ونهاية، والفجوة بينهما هي حيث يختلط الأمر على الوكلاء. يعلنون النجاح مبكرًا، أو يستطلعون ألف مرة في حلقة ضيقة، أو يبقون معلقين لمدة ست دقائق ممسكين بدور محادثة مفتوحًا.
يغطي هذا الدليل كيفية تصميم العقد غير المتزامن بحيث يمكن للوكيل اتباعه، ومتى يتم الاستطلاع ومتى يتم التسليم، وكيفية كتابة الأدوات لكي يتصرف النموذج، وكيفية اختبار المسار بأكمله بما في ذلك الحالات البطيئة والفاشلة. يغطي منشورنا حول استعادة أخطاء الوكيل الجانب الفاشل لاستدعاءات API؛ هذا المنشور يغطي تلك التي تنجح ببطء.
يتناسب Apidog مع النقطة التي تحتاج فيها لإثبات أن الوكيل يتعامل مع مهمة تستغرق أربع دقائق ثم تفشل، وهو ليس شيئًا ترغب في اكتشافه في بيئة الإنتاج.
لماذا يسيء الوكلاء التعامل مع العمليات غير المتزامنة؟
تسبب ثلاث عادات معظم المشاكل.
تتعامل النماذج مع رمز 2xx على أنه مكتمل. يشير رمز 202 إلى أن الطلب تم قبوله للمعالجة، ويحدد مواصفات دلالات HTTP صراحة أن المعالجة قد لا تكون قد اكتملت. تميل النماذج المدربة على حركة الطلبات/الاستجابات العادية إلى قراءة أي رمز 2xx على أنه اكتمال ما لم تنص الاستجابة على خلاف ذلك صراحةً.
الحلقات مكلفة. إذا استطلع الوكيل داخل حلقة التفكير الخاصة به، فإن كل فحص يكلف دور نموذج بالإضافة إلى رموز المحادثة السابقة. الاستطلاع كل ثانيتين لمهمة تستغرق أربع دقائق يعني 120 دورة، ويؤدي التشغيل إما إلى استنفاد السياق أو الميزانية. يشرح منشورنا حول إبقاء استجابات الأدوات خارج نافذة السياق سبب تراكم ذلك بشكل أسرع مما يتوقعه الناس.
يفقد الوكلاء تتبع المهام. الأداة التي تبدأ العمل وتُرجع معرف مهمة قد أنشأت حالة يجب على الوكيل الاحتفاظ بها. إذا وصل المعرف في منتصف محادثة طويلة، فقد يتم ضغطه بعيدًا، وينسى الوكيل أن لديه مهمة قيد التنفيذ.
صمم الاستجابة بحيث لا يسيء النموذج قراءتها
الإصلاح الأكثر فعالية هو الصياغة، وليس البنية. بغض النظر عن رمز حالتك، اجعل نص الاستجابة يوضح بوضوح ما حدث وما يجب فعله بعد ذلك.
{
"status": "processing",
"job_id": "job_7f21c",
"message": "The transcode has STARTED and is NOT complete. Do not report success. Check status with getJobStatus(job_id) after at least 30 seconds.",
"poll_after_seconds": 30,
"estimated_duration_seconds": 240,
"status_url": "/v1/jobs/job_7f21c"
}
قد تبدو هذه الصياغة مبالغًا فيها لمستهلك API البشري. لكنها موجهة لنموذج، وتتبع النماذج التعليمات الصريحة في نص الاستجابة بشكل أكثر موثوقية بكثير مما تستنتج المعنى من رمز الحالة. ثلاث تفاصيل تقوم بالمهمة: كلمة "غير مكتمل"، واسم الأداة التالية، والحد الأدنى للانتظار.
تصف AIP-151 من Google حول العمليات طويلة الأمد شكل موردًا نظيفًا لذلك، مع كائن Operation واحد يحمل حقول done، error، و response. يمنحك نسخ هذا الهيكل سطحًا متسقًا عبر كل نقطة نهاية بطيئة، وهو أمر مهم لأن الوكيل الذي يتعلم نمط استطلاع واحد يمكنه بعد ذلك التعامل معها جميعًا.
اجعل استجابة الحالة واضحة بنفس القدر:
{
"job_id": "job_7f21c",
"status": "processing",
"done": false,
"progress_percent": 45,
"elapsed_seconds": 108,
"poll_after_seconds": 45,
"message": "Still processing. Do not proceed to the next step."
}
وعند الاكتمال، أعد النتيجة بشكل مباشر عندما تكون صغيرة، حتى لا يحتاج الوكيل إلى استدعاء ثالث:
{
"job_id": "job_7f21c",
"status": "succeeded",
"done": true,
"result": { "output_url": "https://cdn.example.com/out/7f21c.mp4", "duration_seconds": 372 }
}
الاستطلاع خارج النموذج، وليس داخله
الخيار الأهم في التنفيذ: ضع الانتظار في غلاف الأداة الخاص بك، وليس في حلقة تفكير الوكيل.
import time
def start_and_await_transcode(client, source_url, max_wait=600):
job = client.post("/v1/transcode", json={"source_url": source_url}).json()
job_id = job["job_id"]
delay = job.get("poll_after_seconds", 5)
waited = 0
while waited < max_wait:
time.sleep(delay)
waited += delay
status = client.get(f"/v1/jobs/{job_id}").json()
if status.get("done"):
if status["status"] == "succeeded":
return {"status": "succeeded", "result": status["result"]}
return {"status": "failed", "error": status.get("error")}
delay = min(int(delay * 1.5), 60)
return {
"status": "timed_out",
"job_id": job_id,
"message": f"Still running after {max_wait}s. Job {job_id} continues in the background.",
}
من جانب النموذج، هذا هو استدعاء أداة واحد يستغرق بعض الوقت ويعيد إجابة نهائية. لا توجد حلقة استطلاع في السياق، ولا معرفات مهام منسية، ولا 120 دورة. يحافظ التراجع على عدد الطلبات معقولًا، ويمنع السقف المهمة العالقة من تعليق التشغيل إلى الأبد. تعتبر وثيقة أمازون حول المهلات، وإعادة المحاولة، والتراجع مع التذبذب المرجع الذي يستحق القراءة قبل ضبط هذه الأرقام.
قاعدتان تجعلان هذا آمنًا. قم دائمًا بتحديد سقف للانتظار، وقم دائمًا بإعادة معرف المهمة عند انتهاء المهلة حتى يتمكن الوكيل أو الإنسان من التحقق لاحقًا. لا تعد أبدًا بنتيجة غامضة: succeeded (نجح)، failed (فشل)، و timed_out (انتهت المهلة) هي ثلاث نتائج مختلفة، ويجب أن يرى النموذج ثلاث كلمات مختلفة.
بالنسبة للمهام التي تُقاس بالساعات بدلاً من الدقائق، يتوقف الاستطلاع داخل الغلاف عن كونه منطقيًا. حينئذٍ، يكون الشكل الصحيح هو وجود أداتين، واحدة للبدء وواحدة للتحقق، بالإضافة إلى سجل دائم للمهام قيد التنفيذ خارج المحادثة حتى لا يُفقد أي شيء بسبب الضغط. قم بتخزين job_id، والمهمة التي ينتمي إليها، والوقت الذي بدأت فيه، واجعل الوكيل يقرأ تلك القائمة في بداية كل تشغيل.
متى تكون Webhooks هي الإجابة الأفضل
الاستطلاع بسيط ويعمل في كل مكان. المرتجعات أكثر كفاءة وتتطلب المزيد من العمل لتشغيلها. التوازن مغطى جيدًا في مقارنتنا بين Webhooks مقابل الاستطلاع، والنسخة الخاصة بالوكيل أضيق.
استخدم الاستطلاع عندما تستغرق المهمة ثوانٍ إلى دقائق، وعندما ينتظر الوكيل النتيجة للمتابعة، أو عندما لا يمكنك استضافة نقطة نهاية عامة. معظم أعباء عمل الوكيل تقع هنا.
استخدم Webhooks عندما تستغرق المهام ساعات، عندما يبدأ الوكيل العمل وينتقل، أو عندما يتم تشغيل العديد من المهام في وقت واحد ويكون استطلاع كل منها مضيعة. التكلفة حقيقية: أنت بحاجة إلى مستقبل عام، والتحقق من التوقيع، ومعالجة إعادة المحاولة، وطريقة لإيقاظ الوكيل عند وصول المرتجع. تغطي أدلتنا حول تصميم Webhooks موثوقة و التحقق من توقيع Webhook تلك الأساسيات.
خيار متوسط يستحق المعرفة. يمنحك بث تقدم المهمة عبر أحداث خادم-مرسلة دلالات الدفع دون نقطة نهاية عامة، حيث يحمل العميل الاتصال. يناسب الوكلاء التفاعليين حيث يراقب إنسان، ويغطي دليلنا حول بث استجابات API باستخدام SSE التنفيذ.
أياً كان اختيارك، يجب أن يكون مسار الإكمال متكافئًا (idempotent). تُعيد Webhooks المحاولة، وتتنافس عمليات الاستطلاع، ولا ينبغي لوكيل يرى "نجح" مرتين أن يبدأ الخطوة التالية مرتين. يغطي منشورنا حول تكافؤ العمليات لوكلاء الذكاء الاصطناعي المفاتيح التي تجعل ذلك آمنًا.
اختبر المسار البطيء، وليس فقط السريع
تختفي أخطاء العمليات غير المتزامنة لأن بيئات الاختبار سريعة. المهمة التي تستغرق أربع دقائق في الإنتاج تكتمل في 200 مللي ثانية مقابل برنامج وهمي محلي، لذا فإن الوكيل لا يختبر الحالة التي سيواجهها بالفعل أبدًا.
أربع سيناريوهات تستحق البناء عمدًا.
المهمة البطيئة حقًا. قم بمحاكاة نقطة نهاية الحالة بحيث تُرجع processing (جارٍ المعالجة) لعدة استدعاءات أولية ثم succeeded (نجحت) بعد ذلك. هذا يثبت أن الغلاف يستطلع، يتراجع، ويعود في النهاية. في Apidog يمكنك قيادة هذا بمحاكاة تختلف حسب عدد الطلبات أو بواسطة معلمة تحكم، بحيث يتم تشغيل نفس الاختبار بنفس الطريقة في كل مرة.

المهمة التي تفشل متأخرة. أعد processing ثلاث مرات، ثم failed (فشلت) مع نص خطأ. يجب على الوكيل الإبلاغ عن الفشل بدلاً من اعتبار الاستطلاع المكتمل مهمة مكتملة. هذه هي الحالة التي تنتج فقدانًا صامتًا للبيانات عندما تكون خاطئة.
انتهاء المهلة. استمر في جعل المحاكاة تعيد processing بعد سقف الغلاف وتأكد من أن الأداة تعيد timed_out (انتهت المهلة) مع بقاء معرف المهمة سليمًا، وليس استثناءً وليس نجاحًا مزيفًا.
الاكتمال المكرر. قم بتسليم النجاح مرتين، عن طريق إعادة محاولة webhook أو عن طريق استطلاع متسارع، وتأكد من أن الخطوة التالية تعمل مرة واحدة.
احفظ السيناريوهات الأربعة كلها بحيث يتم تشغيلها في CI. لا تكلف إعادة تشغيلها شيئًا، وتلتقط الانحدار حيث يقوم شخص ما بتقصير مهلة أو يبتلع خطأ. النهج الأوسع موجود في دليلنا لاختبار عقود API.
ثلاث مهام تكشف المشكلة
توليد التقارير. يطلب وكيل مالي تصديرًا ربع سنويًا. يستغرق 90 ثانية. باستخدام أداة ساذجة، يحصل الوكيل على معرف مهمة، ويعلن أن التقرير جاهز، ثم يسلم رابط تنزيل معطوب للمستخدم. مع غلاف مانع، ينتظر 90 ثانية ويعيد عنوان URL الحقيقي. نفس واجهة برمجة التطبيقات (API)، نتائج معاكسة، والفرق الوحيد هو مكان حدوث الانتظار.
عمليات الاستيراد بالجملة. يقوم وكيل العمليات بتحميل 20,000 سجل. تستغرق عملية الاستيراد ثماني دقائق وتفشل جزئيًا في الصف 14,000. هذه هي الحالة التي تعاقب الفحص الساذج للنجاح: لقد انتهت المهمة، لذا فإن حالة done صحيحة، ولكن النتيجة تحمل قائمة بالصفوف المرفوضة. قم بإرجاع النتائج الجزئية صراحة، مع التعدادات، واجعل الوكيل يقرأها قبل المتابعة.
خطوط أنابيب النماذج والبناء. يقوم وكيل بتشغيل تدريب أو بناء CI يستغرق 40 دقيقة. الاستطلاع داخل الغلاف هو الشكل الخاطئ هنا؛ فالعملية ستبقي الدور مفتوحًا لفترة طويلة جدًا. ابدأ المهمة، سجل المعرف في تخزين دائم، أنهِ الدور، ودع فحصًا مجدولًا أو استدعاءً يوقظ المتابعة. يغطي منشورنا حول تسليم الوكيل المتعدد وتمرير السياق نقل تلك الحالة بين عمليات التشغيل دون فقدانها.
إعطاء شكل للنتائج الجزئية
غالبًا ما تنتهي المهام الطويلة في مكان ما بين النجاح والفشل، ويجبرك نموذج الحالتين على الكذب بشأن ذلك. اجعل الحالة الثالثة واضحة:
{
"job_id": "job_a11f",
"status": "completed_with_errors",
"done": true,
"summary": { "processed": 20000, "succeeded": 19860, "failed": 140 },
"errors_url": "/v1/jobs/job_a11f/errors?limit=50",
"message": "Import finished. 140 rows failed and were not written. Review errors before reporting success."
}
شيئان مهمان في هذا الحمولة. التعدادات مضمنة، بحيث يمكن للوكيل أن يقرر دون استدعاء آخر. الصفوف الفاشلة موجودة خلف عنوان URL مع حد، بحيث لا تهبط 140 كائن خطأ في السياق دون دعوة.
يجب على أحدهم رؤية المهمة التي توقفت
ينتهي مسار انتهاء المهلة بمعرف مهمة ورسالة تفيد بأن العمل لا يزال قيد التشغيل. هذه هي القيمة المرتجعة الصحيحة، وهي مفيدة فقط إذا وصلت إلى شخص ما.
حيث يكون الوكيل خدمتك الخاصة، وجّهه إلى أي قائمة انتظار يراقبها فريقك بالفعل. وحيث يكون الوكيل هو وقت تشغيل برمجي يعمل من خلال المهام المخصصة، فإن المنصة التي تشغله عادة ما يكون لديها مكان لوصول هذا الأمر. في Sharkly، يبقى التشغيل الذي ينتهي مسدودًا في مهمته مع حالة تنفيذه ونتيجته، ويفصل صندوق الوارد العناصر التي تحتاج إلى رد بشري أو مراجعة عن التحديثات العادية. النقطة ليست الأداة المحددة. بل هي أن "لا يزال قيد التشغيل، تحقق لاحقًا" يحتاج إلى مالك، وإلا سيصبح "لم يتحقق أحد".

قائمة تحقق موجزة
- كل نقطة نهاية بطيئة تُرجع معرف مهمة، وعنوان URL للحالة، ورسالة واضحة اللغة تفيد بأن العمل لم ينتهِ.
- تحمل استجابات الحالة حقل منطقي
done، وليس مجرد سلسلة نصية يجب على النموذج تفسيرها. - يتم الاستطلاع داخل غلاف الأداة مع تراجع أُسيّ وسقف صارم.
- تُرجع المهلات معرف المهمة حتى يمكن استئناف العمل بدلاً من فقده.
- النجاح، والفشل، وانتهاء المهلة هي ثلاث قيم إرجاع مميزة.
- يتم تسجيل المهام قيد التنفيذ خارج المحادثة لأي شيء يستغرق أكثر من بضع دقائق.
- تكون معالجة الإكمال متكافئة، سواء وصلت الإشارة عن طريق الاستطلاع أو عن طريق الاستدعاء.
- يتم حفظ اختبارات للحالات البطيئة، والفشل المتأخر، وانتهاء المهلة، والاكتمال المكرر.
اضبط صياغة الاستجابة وغلافها بشكل صحيح، وستتوقف العمليات طويلة الأمد عن كونها حالة خاصة للوكيل. يقوم الوكيل باستدعاء أداة، ينتظر، ويحصل على إجابة، وهذا هو العقد الذي يتعامل معه بأفضل شكل. قم بتنزيل Apidog لبناء برامج محاكاة المهام البطيئة جنبًا إلى جنب مع الاختبارات.
أسئلة مكررة
هل يجب أن تُرجع واجهة برمجة التطبيقات (API) رمز 202 أو 200 لبدء عملية غير متزامنة؟ رمز 202 Accepted هو الرمز الصريح ويشير إلى العملاء القياسيين بأن المعالجة لم تكتمل. لا تعتمد عليه وحده للوكلاء، لأن نص الاستجابة هو ما يقرأه النموذج بأكثر موثوقية. استخدم كليهما.
كم من الوقت يجب أن تنتظر حزمة الأداة قبل الاستسلام؟ قم بتعيين الحد الأقصى أعلى بقليل من أسوأ حالة واقعية لنقطة النهاية، عادة ما بين دقيقتين وعشر دقائق. بعد ذلك، تقوم الحزمة بحجب دور المحادثة لفترة طويلة جدًا، وتكون أداة "التحقق لاحقًا" شكلًا أفضل.
ما هي فترة الاستطلاع التي يجب أن أستخدمها؟ ابدأ من تلميح الخادم الخاص poll_after_seconds إذا كان موجودًا، ثم تراجع بعامل حوالي 1.5 مع سقف حوالي 60 ثانية. الاستطلاع الثابت كل ثانية يهدر الطلبات ويمكن أن يسبب تجاوز حدود المعدل، كما هو موضح في دليلنا حول تجاوز حدود المعدل.
هل يمكن للوكيل أن يقوم بشيء مفيد أثناء انتظاره؟ فقط إذا كانت منسقك يدعم استدعاءات الأدوات المتزامنة. في هذه الحالة، ابدأ المهمة، وقم بالعمل المستقل، ثم تحقق من الحالة. أما إذا لم يكن يدعم ذلك، فإن الغلاف الذي يسبب الحجب أبسط وأقل عرضة للخطأ من جدول زمني تم إنشاؤه يدويًا.
كيف أمنع الوكيل من إعلان النجاح مبكرًا؟ اذكر ذلك بوضوح في نص الاستجابة، واكشف عن حقل منطقي done، واجعل أداة الإكمال هي المكان الوحيد الذي تظهر فيه النتيجة. إذا كانت استجابة البدء لا تحتوي على نتيجة، فلن يكون هناك ما يمكن للنموذج الإبلاغ عنه كنتيجة.
هل تعمل Webhooks للوكلاء الذين يعملون على حاسوب محمول؟ ليس بشكل مباشر، لأنه لا توجد نقطة نهاية عامة. استخدم نفقًا للتطوير، كما هو موضح في دليلنا حول اختبار واجهات برمجة تطبيقات (APIs) localhost باستخدام خدمات Webhook، أو التزم بالاستطلاع حتى يعمل الوكيل في مكان يمكن الوصول إليه.
