لماذا مراجعة التتبع ليست تحققًا
التتبع هو سجل لتشغيل حدث بالفعل. يُظهر الأدوات التي استُدعيت، وبأي ترتيب، وبأي وسائط، وما الذي عاد. إنه مفيد لتصحيح الأخطاء ولبناء حدس حول سلوك الوكيل. لكنه ليس إشارة جاهزية.
عندما يراجع فريق تتبعًا ويعلن أن الوكيل تم التحقق منه، فإنهم يتحققون من مجموعة السيناريوهات التي اختاروها، لا من البيئة التي سيواجهها الوكيل. الحالات التي تنجح هي التي فكّر أحدهم في تشغيلها. والحالات التي تفشل في الإنتاج هي، بحكم التعريف، التي لم يفكّر أحد في تشغيلها. لا يمكن للتتبع أن يحتويها.
هذا مهم لأن بوابات الموافقة غالبًا ما تُبنى على تشغيلات تجريبية. يراقب صاحب المصلحة الوكيل وهو يكمل مهمة، يرى تتبعًا نظيفًا، ويوقّع. الخطر الذي كان يُفترض أن يُزال عند البوابة يُنقل بدلًا من ذلك إلى نافذة النشر، حيث يكون رصده أكثر تكلفة والتراجع عنه أصعب. البوابة لم تقلّل الخطر؛ بل نقلته.
يجب أن يكون التحقق عملية نشطة. أنت لا تقرأ سلوك الوكيل وتستنتج الجاهزية. أنت تُشوّش البيئة وتراقب ما إذا كان مسار تعافي الوكيل يصمد. هذا هو حقن الأخطاء، وبالنسبة للوكلاء هو الشكل الوحيد للتحقق الذي ينتج أدلة حول أعطال لم ترها بعد.
فئات الأخطاء التي تستحق الحقن
حقن الأخطاء للوكلاء ليس تجربة فوضى عامة. الأعطال التي تهم هي التي تتفاعل مع تخطيط الوكيل واستخدامه للأدوات وذاكرته. مجموعة بداية عملية:
- مهلات الأدوات. تتوقف واجهة برمجية تابعة عن الاستجابة داخل ميزانية المهلة للوكيل. يجب على الوكيل أن يقرر ما إذا كان سيعيد المحاولة أو يتراجع أو يتوقف، ويجب ألا يلتزم بخطة تفترض أن النتيجة وصلت.
- الاستجابات الجزئية وانحراف المخطط. تُعيد أداة حمولة مقتطعة، أو يتغير نوع حقل أو يختفي. الوكلاء الذين يحللون مخرجات الأدوات بافتراضات ضمنية إما ينهارون أو، الأسوأ، يقرؤون النتيجة قراءة خاطئة صامتة.
- انتهاء صلاحية بيانات الاعتماد أثناء التشغيل. تنتهي صلاحية رمز بعد الالتزام بالخطة ولكن قبل الكتابة النهائية. يجب على الوكيل أن يُظهر العطل بدلًا من إعادة المحاولة ببيانات اعتماد منتهية أو المضي دون تصريح.
- رفض الأذونات بعد الالتزام. يُرفض استدعاء أداة لأسباب تتعلق بالتصريح، لا بالتوافر. هذا مسار تعافٍ مختلف عن المهلة، وغالبًا ما يصل بعد أن يكون الوكيل قد أخبر المستخدم بالفعل أن المهمة جارية.
- تعليمات متعارضة من أداتين. يختلف مصدران حول الحقيقة نفسها. يجب على الوكيل اكتشاف التعارض بدلًا من اختيار آخر ما قرأه.
- سياق قديم يناقض استرجاعًا حديثًا. تتعارض قيمة مخزّنة مؤقتًا في سياق الوكيل مع قراءة حديثة. يجب على الوكيل تفضيل المصدر الحديث وتحديث حالته، لا التوفيق بين الاثنين في إجابة معقولة لكن خاطئة.

ما الذي يجب قياسه
حقن الأخطاء دون قياس ينتج حكايات. القياسات التي تهم هي التي تخبرك ما إذا كان مسار التعافي سلوكًا مصممًا أم حادثًا.
- زمن التعافي. كم يستغرق الوكيل، بالزمن الفعلي أو بجولات النموذج، للوصول إلى حالة مستقرة بعد العطل. التعافي الذي يستغرق وقتًا أطول من الموعد النهائي للمهمة نفسها ليس تعافيًا.
- الخطوات المستهلكة في التعافي. كم من استدعاءات الأدوات ودورات التخطيط تُنفق على العطل. الوكيل الذي يتعافى لكن يستهلك ميزانية خطواته بالكامل لم يتبقَّ لديه قدرة للمهمة.
- الحالة النهائية. هل ينتهي التشغيل في حالة آمنة. الآمن يعني أن الآثار الجانبية إما مُلتزم بها بشكل صحيح أو غير مُلتزم بها إطلاقًا، ويُخبر المستخدم بأي منهما. التشغيل الذي ينتهي بكتابة جزئية ورسالة نجاح هو فشل بغض النظر عن مدى رشاقة تعافيه.
- تباعد المسار. بعد كل عطل محقون، قارن المسار المخطط بالمسار المنفذ. التباعد ليس سيئًا تلقائيًا، لكن التباعد غير المقيس كذلك. إذا غيّر الوكيل خطته بصمت، فقد فقدت القدرة على التفكير في سلوكه.
هذه القياسات ليست درجة واحدة. إنها ملف تعريف. تشغيل يتعافى بسرعة لكن ينتهي بشكل غير آمن أسوأ من تشغيل يستغرق وقتًا أطول وينتهي بشكل نظيف. يتيح لك الملف إجراء هذه المقايضة بشكل صريح.
آلية ملموسة: أداة حقن الأخطاء
الآلية التي تجعل هذا قابلًا للتكرار هي أداة تقع بين الوكيل وأدواته. إنها ليست محاكاة. إنها وسيط يمكنه تطبيق مجموعة أخطاء على استجابات الأدوات الحية أو المسجلة.
class FaultInjector:
def __init__(self, faults, seed):
self.faults = faults
self.rng = random.Random(seed)
def wrap(self, tool):
def call(*args, **kwargs):
fault = self._select(tool.name)
if fault == "timeout":
raise ToolTimeout(tool.name)
if fault == "schema_drift":
return self._mutate_schema(tool(*args, **kwargs))
if fault == "partial":
return self._truncate(tool(*args, **kwargs))

تسجّل الأداة، لكل عطل محقون، زمن التعافي، والخطوات المستهلكة، والحالة النهائية، والتباعد بين المسارات المخططة والمنفذة. تُدار مجموعة الأخطاء بإصدارات إلى جانب الوكيل. عندما يتغير prompt أو يتغير مخطط أداة، تُعاد مجموعة الأخطاء. الانحدار هو عطل كان يتعافى بشكل نظيف سابقًا ولم يعد كذلك.
## جعله قابلًا للتكرار
مجموعة أخطاء غير مُدارة بإصدارات هي اختبار لمرة واحدة. مجموعة أخطاء مُدارة بإصدارات هي أصل.
الممارسة هي التعامل مع مجموعة الأخطاء كجزء من تعريف الوكيل. عندما يتغير prompt الوكيل، تعمل مجموعة الأخطاء. عندما يتغير مخطط أداة، تعمل مجموعة الأخطاء. عندما يُكتشف عطل إنتاجي جديد، يصبح fixture جديدًا في مجموعة الأخطاء، لا فقرة في تحليل ما بعد الحادث. يظل تحليل ما بعد الحادث موجودًا، لكن مخرجاته اختبار قابل لإعادة الإنتاج، لا سرد.
هذا يغيّر شكل محادثة النشر. بدلًا من السؤال عما إذا كان الوكيل تعامل مع العرض التجريبي، يصبح السؤال: أي فئات أخطاء حُقنت، وكيف بدا ملف التعافي، وهل يفشل أي عطل كان ينجح سابقًا. هذا سؤال له إجابة قائمة على الأدلة.
المقايضة هي أن مجموعة الأخطاء تنمو بشكل رتيب. كل عطل إنتاجي يضيف fixture، وتصبح المجموعة أبطأ. عند نقطة ما تحتاج المجموعة إلى تقسيم إلى طبقات: مجموعة فرعية سريعة تعمل عند كل تغيير prompt، ومجموعة كاملة تعمل قبل النشر. قرار التقسيم إلى طبقات هو نفسه حكم حول أي الأعطال الأكثر احتمالًا للتكرار، ويجب إعادة النظر فيه مع تغيّر بيئة الوكيل.
## سؤال التحقق
السؤال ليس ما إذا كان الوكيل يبدو جيدًا في تتبع. السؤال هو ما يحدث عندما تتوقف الأداة التي يعتمد عليها عن الاستجابة، وتنتهي صلاحية بيانات الاعتماد التي يحملها، ويتناقض السياق الذي يحمله مع ما قرأه للتو. إذا لم تحقن هذه الأعطال، فأنت لا تعرف. وإذا فعلت، فلديك ملف تعافٍ، ومجموعة fixtures، وقرار نشر يستند إلى أدلة بدلًا من تشغيل نظيف.
التحقق ليس قراءة. إنه حقن.
