3. כתיבת משימות

"סוכן בלי תוכנית נסחף"

20 דקות קריאה
💡חדש בנושא?

מה זה TodoManager?

מחלקה פשוטה שמנהלת רשימת משימות עם סטטוסים (pending, in_progress, done). היא מאלצת את המודל לכתוב את התוכנית שלו לפני הביצוע, כדי שלא יאבד עקב מה שצריך לעשות אחר כך.

למה רק משימה אחת in_progress בו-זמנית?

זה מאלץ מיקוד עוקב. המודל חייב לסיים או לעדכן את המשימה הנוכחית לפני שיעבור הלאה. זה מונע מהסוכן להתחיל 5 דברים ולא לסיים אף אחד.

מה זה nag reminder?

הזרקת טקסט קטנה (<reminder>) שמתווספת לשיחה אם המודל לא עדכן את רשימת המשימות ב-3+ סיבובים. היא דוחפת את המודל לשמור על מסלול מבלי שהמשתמש צריך להתערב.

במה זה שונה מרשימת תיוגים רגילה?

רשימת תיוגים רגילה היא טקסט סטטי שהמודל עשוי להתעלם ממנו. TodoWrite הוא כלי שהמודל קורא לו באופן אקטיבי כדי לעדכן סטטוסים. ה-harness עוקב אחר סיבובים ומזריק תזכורות, מה שהופך אותו ללולאת משוב, לא רק הערה.

הבעיה

במשימות מרובות שלבים, המודל מאבד עקב. הוא חוזר על עבודה, מדלג על שלבים, או סוטה ממסלול. שיחות ארוכות מחמירות את המצב — הפרומפט של המערכת מתמעט כשתוצאות הכלים ממלאות את ה-context. רפקטורינג של 10 שלבים עשוי להשלים שלבים 1-3, ואז המודל מתחיל לאלתר כי שכח את שלבים 4-10.

הפתרון

+--------+      +-------+      +---------+
|  User  | ---> |  LLM  | ---> | Tools   |
| prompt |      |       |      | + todo  |
+--------+      +---+---+      +----+----+
                    ^                |
                    |   tool_result  |
                    +----------------+
                          |
              +-----------+-----------+
              | TodoManager state     |
              | [ ] task A            |
              | [>] task B  <- doing  |
              | [x] task C            |
              +-----------------------+
                          |
              if rounds_since_todo >= 3:
                inject <reminder> into tool_result

איך זה עובד

  1. TodoManager שומר פריטים עם סטטוסים. רק פריט אחד יכול להיות in_progress בכל עת.
class TodoManager:
    def update(self, items: list) -> str:
        validated, in_progress_count = [], 0
        for item in items:
            status = item.get("status", "pending")
            if status == "in_progress":
                in_progress_count += 1
            validated.append({"id": item["id"], "text": item["text"],
                              "status": status})
        if in_progress_count > 1:
            raise ValueError("Only one task can be in_progress")
        self.items = validated
        return self.render()
  1. הכלי todo נכנס למפת ה-dispatch כמו כל כלי אחר.
TOOL_HANDLERS = {
    # ...base tools...
    "todo": lambda **kw: TODO.update(kw["items"]),
}
  1. ה-nag reminder מזריק דחיפה אם המודל עובר 3+ סיבובים מבלי לקרוא ל-todo.
if rounds_since_todo >= 3 and messages:
    last = messages[-1]
    if last["role"] == "user" and isinstance(last.get("content"), list):
        last["content"].insert(0, {
            "type": "text",
            "text": "<reminder>Update your todos.</reminder>",
        })

האילוץ של “in_progress אחד בכל עת” מאלץ מיקוד עוקב. ה-nag reminder יוצר אחריות.

מה השתנה מ-שימוש בכלים

רכיבלפני (שימוש בכלים)אחרי (TodoWrite)
כלים45 (+todo)
תכנוןאיןTodoManager עם סטטוסים
הזרקת תזכורתאין<reminder> אחרי 3 סיבובים
לולאת הסוכןdispatch פשוט+ מונה rounds_since_todo

מסקנה מרכזית

תכנון הוא לא אופציונלי לעבודה מרובת שלבים. תבנית TodoWrite נותנת למודל דרך מובנית לעקוב אחר ההתקדמות שלו עצמו, כשה-harness אוכף אחריות דרך תזכורות. הלולאה כמעט לא משתנה — כלי חדש אחד, מונה אחד, נקודת הזרקה אחת.

מדריך קוד אינטראקטיבי

מחלקת TodoManager
1class TodoManager:
2 def update(self, items: list) -> str:
3 validated, in_progress_count = [], 0
4 for item in items:
5 status = item.get("status", "pending")
6 if status == "in_progress":
7 in_progress_count += 1
8 validated.append({"id": item["id"], "text": item["text"],
9 "status": status})
10 if in_progress_count > 1:
11 raise ValueError("Only one task can be in_progress")
12 self.items = validated
13 return self.render()
14 
15if rounds_since_todo >= 3 and messages:
16 last = messages[-1]
17 if last["role"] == "user" and isinstance(last.get("content"), list):
18 last["content"].insert(0, {
19 "type": "text",
20 "text": "<reminder>Update your todos.</reminder>",
21 })
22 
TodoManager הוא מחלקה פשוטה. מתודת update() היא פעולת הכתיבה היחידה — המודל קורא לה עם הרשימה המלאה של פריטים בכל פעם שהוא רוצה לשנות משהו.
שלב 1 מתוך 5
🧪 נסו בעצמכם

הריצו python agents/s03_todo_write.py ותנו לו משימה מרובת שלבים. צפו איך הוא יוצר רשימת משימות לפני שהוא פועל.

רמז

נסו: "צרו פרויקט Python עם טסטים, README, ו-CLI"

מצאתם טעות? דווחו ←