الدرس 11 · تعاون

وكيل يبحث عن العمل بنفسه

«الوكيل يجد عمله بنفسه.» لا يحتاج لمن يُحيل إليه المهام، بل يأخذها من لوحة المهام.

⏱ ~12 د · 📝 3 مكونات تفاعلية · 🧑‍💻 مبني على shareAI-lab · s11_autonomous_agents.py

من «الانتظار حتى الاستدعاء» إلى «البحث الذاتي»

teammates في s09 / s10 سلبيون: لا يبدؤون العمل إلا بعد وصول رسالة عبر صندوق البريد؛ ينتهون وينتظرون الاستدعاء مجدداً.

autonomous teammate في s11 نشط: حتى بلا عمل لا يتوقف حقاً، بل يفحص دليل .tasks/ كل 5 ثوانٍ — إن وجد مهمة بلا مالك يستدعي claim_task ويبدأ العمل.

Teammate lifecycle:
  +-------+
  | spawn |
  +---+---+
      |
      v
  +-------+
  | WORK  | <-- LLM tool_use 循环
  +---+---+
      |
      | stop_reason != tool_use OR tool_use("idle")
      v
  +-------+
  | IDLE  | poll 每 5s,共 12 次 = 60s 超时
  +---+---+
      |
      +--> inbox 有新消息?  → resume WORK
      |
      +--> scan .tasks/,发现未认领 → claim → resume WORK
      |
      +--> 60s 什么都没等到 → status = shutdown,线程退出

Auto-claim · «انتزاع» المهمة من اللوحة

الدالة الجوهرية:

def scan_unclaimed_tasks() -> list:
    unclaimed = []
    for f in sorted(TASKS_DIR.glob("task_*.json")):
        task = json.loads(f.read_text())
        if (task.get("status") == "pending"
                and not task.get("owner")
                and not task.get("blockedBy")):
            unclaimed.append(task)
    return unclaimed

ثلاثة فلاتر = pending + بلا مالك + بلا تبعيات. بدون أي منها تسقط المنطق.

عملية المطالبة محمية بقفل (_claim_lock) لمنع وكيلين من رؤية نفس المهمة غير المُستلَمة وانتزاعها معاً — داخل القفل: إعادة قراءة، التحقق من أن المالك لا يزال فارغاً، ثم تحديث الحالة إلى «in_progress» مع كتابة المالك على القرص.

محاكاة وكلاء متعددين يفحصون اللوحة في آنٍ واحد

3 teammates في حالة idle، و3 مهام تنتظر الاستلام. اضغط «الفحص التالي» وشاهد من يسبق إلى المطالبة.

إعادة حقن Identity · بعد الضغط هل يتذكر الوكيل نفسه؟

s06 شرح أن auto_compact تستبدل messages بملخص. الـ autonomous agent الذي يعمل ساعات طويلة يُطلق هذا بسهولة — وبعد الضغط يجهل النموذج اسمه ودوره.

أسلوب s11: عند المطالبة بمهمة جديدة، إن كان len(messages) ≤ 3 (دليل على حدوث ضغط للتو)، تُحقن تلقائياً كتلة identity في البداية:

if len(messages) <= 3:
    messages.insert(0, {
        "role": "user",
        "content": f"<identity>You are 'alice', role: coder, team: my-team. Continue your work.</identity>",
    })
    messages.insert(1, {"role":"assistant", "content": f"I am alice. Continuing."})

يُسمى هذا النمط identity reinjection — محادثة مُنشأة صناعياً تُخبر النموذج بهويته وتُعيد إليه الإحساس بدوره.

تفاعلي

Widget 1 · Task Scanner · 3 وكلاء يتنافسون على 3 مهام

alice وbob وcharlie في وضع idle. اضغط للفحص وشاهد من يسبق أبجدياً للمطالبة بأول مهمة غير مُستلَمة.

دليل .tasks/
حالة Teammates
الجميع في وضع idle، ينتظرون الفحص
تفاعلي

Widget 2 · Identity Drift · هل يتذكر الوكيل نفسه بعد الضغط؟

محاكاة مقارنة: ماذا يُجيب الوكيل على «من أنت؟» قبل الضغط وبعده — مع إعادة حقن identity ودونها.

بدون إعادة حقن identity
مع إعادة حقن identity
تفاعلي

Widget 3 · Autonomous vs Assisted · أي الأدوار تناسب الاستقلالية؟

قرّر هل تُشغّل هذا الدور في حلقة ذاتية أم تنتظر الأوامر. فكّر في «تكلفة الخطأ» و«تكرار التدخل البشري».

أصبت في 0 / 5