الحلقة لم تتغير، فقط زادت الأدوات
«الحلقة لم تتغير قيد أنملة، أضفت فحسب عناصر إلى مصفوفة TOOLS.» — s02_tool_use.py
ما الذي يجب تعديله لإضافة أداة؟
وكيل S01 يعرف فقط bash. كيف تُمكّنه أيضاً من read_file / write_file / edit_file؟
الردة الأولى لكثيرين: تعديل الحلقة. خطأ. لا تمسّ الحلقة ولا سطراً واحداً منها. ثلاثة أشياء فقط مطلوبة:
- اكتب دالة handler بايثون (
run_read(path, limit)). - سجّلها في جدول التعيين
TOOL_HANDLERS("read_file": lambda **kw: run_read(...)). - أضف تعريف JSON schema في مصفوفة
TOOLS(لتُعلم النموذج باسم الأداة والمعاملات التي تقبلها).
حين ترى الحلقة كتلة tool_use، تبحث بـ block.name في dispatch map عن الدالة، تُنفذها، وتُعيد الإخراج إلى tool_result. المسار طابق تماماً مسار bash.
# Dispatch map: name → handler lambda TOOL_HANDLERS = { "bash": lambda **kw: run_bash(kw["command"]), "read_file": lambda **kw: run_read(kw["path"], kw.get("limit")), "write_file": lambda **kw: run_write(kw["path"], kw["content"]), "edit_file": lambda **kw: run_edit(kw["path"], kw["old_text"], kw["new_text"]), }
شاهد كيف يعمل التوجيه
المكوّن التالي يتيح لك النقر على طلب tool_use قد يُرسله النموذج، ومشاهدة كيف يُوجَّه إلى دالة Python محددة. تذكر: block.name هو الذي يحدد المسار.
safe_path: خط الدفاع الذي لا يمكن تجاهله
حين تمنح الوكيل صلاحية الوصول للملفات، أخطر ثغرة أمنية هي هروب المسار: النموذج المفروض أن يعمل في /home/user/project/، لكنه يُرسل read_file("../../etc/passwd").
في s02 دالة صغيرة تُعالج هذا:
def safe_path(p: str) -> Path: path = (WORKDIR / p).resolve() # 规范化,解析 .. 和软链 if not path.is_relative_to(WORKDIR): raise ValueError(f"Path escapes workspace: {p}") return path
المفتاح في خطوتين: .resolve() + .is_relative_to() — تحليل إلى مسار مطلق ثم التحقق من بقائه داخل sandbox. بدون الأولى، يمكن لـ foo/../../etc العبور؛ بدون الثانية، لا يوجد تحقق أصلاً.
تمييز أمان المسار
المسارات الخمسة التالية مُعاملات read_file قد يُرسلها النموذج. أيها يسمح به safe_path، وأيها يرفضه؟ افترض WORKDIR = /home/user/project.
لا تُضف أدوات خطيرة إلى الوكيل
إضافة الأدوات سهلة، لكن تذكر: كل أداة تُضيفها هي حدود قدرة جديدة للنموذج. في s02 يحتوي bash على قائمة سوداء (rm -rf /، sudo، shutdown)، وwrite_file مقيد بـ safe_path. قبل إضافة أدوات للإنتاج، اسأل نفسك ثلاثة أسئلة:
- هل يمكن لهذه الأداة أن تُمكّن النموذج من أفعال لا رجعة فيها؟ (rm، إرسال بريد إلكتروني، git push)
- ما الذي يمكن أن يتسرب عبرها؟ (متغيرات البيئة، .ssh، ملفات تعريف الارتباط)
- هل يمكن أن تُعامَل مخرجات الخطأ كتعليمات؟ (حقن Prompt عبر مخرجات الأداة)
الدرس s07 سيُضيف «طبقة صلاحيات» لسحب هذه القرارات من الكود وجعلها تصريحية.