• בלוג
  • יום 14 - העברת שליטה לסוכן אחר handoff

יום 14 - העברת שליטה לסוכן אחר handoff

13/10/2025

העברת שליטה היא סוג מיוחד של הפעלת כלי בה סוכן אחד מזהה שיש סוכן אחר שיהיה יותר מיומן ממנו לפתור בעיה ספציפית ולכן מעביר את השליטה לסוכן השני. בואו נראה איך זה מוגדר ב Agents SDK ולמה חשוב לשים לב.

1. למה צריך מספר סוכנים

לפני שנגיע לקוד של handoff כדאי לעצור ולשאול - למה צריך מספר סוכנים? האם הסוכן הראשי לא יכול לבצע את כל המשימות? הנה כמה רעיונות לתרחישים בהם מספר סוכנים יכולים לעזור:

  1. אם אנחנו יכולים לזהות סוג מסוים של בקשות שיקבלו טיפול טוב יותר ממודל אחר - לדוגמה רוב הבקשות שלי מטופלות בצורה טובה על ידי gpt-4.1-mini אבל יש בקשות מסובכות במיוחד שכדאי לי להעביר למודל יותר גדול. או אולי יש לי סט של בקשות שאני יכול לפתור בעזרת מודל זול יותר וכך להוריד עלויות.

  2. אם אנחנו מזהים סוג מסוים של בקשות עבורן סט הוראות (instructions) שונה ייתן תוצאות טובות יותר.

  3. אם אנחנו רוצים לשלוט טוב יותר בקונטקסט, כלומר להעביר בקשה מסוימת בלי ההיסטוריה שלה או עם היסטוריה חלקית למודל אחר לטיפול.

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

2. דוגמה - סוכני תרגום

בדוגמה הראשונה אני מגדיר שלושה סוכנים: סוכן אחד יודע לתרגם דברים לצרפתית, סוכן שני מתרגם לספרדית וסוכן שלישי אחראי על רוב השיחה. אם הסוכן הראשי מזהה בקשה לתרגום הוא יעביר את הבקשה לסוכן המתאים:

french_agent = Agent(
    name="French Translator",
    instructions="Translate everything to french"
)
spanish_agent = Agent(
    name="Spanish Translator",
    instructions="Translate everything to Spanish")

triage_agent = Agent(name="Triage agent", handoffs=[french_agent, spanish_agent])

async def main():
    session = SQLiteSession("handoffs", "handoffs.db")
    result = await Runner.run(triage_agent, "translate to French: 'hello world'", session=session)
    print(result.final_output)

if __name__ == "__main__":
    asyncio.run(main())

הפעלת הקוד מדפיסה bonjour le monde שזה התרגום לצרפתית של hello world.

בחינת רשימת ההודעות אחרי הפעלת התוכנית מציגה את הרשימה הבאה:

1|handoffs|{"content": "translate to French: 'hello world'", "role": "user"}|2025-08-17 11:49:06
2|handoffs|{"arguments": "{}", "call_id": "call_Abq5WDOv6C1RZVKNsCg4WO0F", "name": "transfer_to_french_translator", "type": "function_call", "id": "fc_68a1c1b13b8081988a6174005b308dd20e79e771496ac495", "status": "completed"}|2025-08-17 11:49:06
3|handoffs|{"call_id": "call_Abq5WDOv6C1RZVKNsCg4WO0F", "output": "{\"assistant\": \"French Translator\"}", "type": "function_call_output"}|2025-08-17 11:49:06
4|handoffs|{"id": "msg_68a1c1b27324819892a9f00a9d0b95f50e79e771496ac495", "content": [{"annotations": [], "text": "'hello world' se traduit par 'bonjour le monde'.", "type": "output_text", "logprobs": []}], "role": "assistant", "status": "completed", "type": "message"}|2025-08-17 11:49:06

אנחנו רואים בפלט:

  1. הודעה ראשונה מהמשתמש עם בקשה לתרגם לצרפתית.

  2. הודעה על Tool Call של העברת שליטה לסוכן שני.

  3. סיום Tool Call עם הפלט "{\"assistant\": \"French Translator\"}".

  4. פניה של ה Runner לסוכן התרגום לצרפתית והודעה ממנו עם הטקסט המתורגם.

3. למה לשים לב כשמבצעים Handoff

כמה נקודות שכדאי לזכור לגבי Handoff וטיפים לשימוש יעיל בפיצ'ר:

  1. אם אתם מעבירים שליטה לסוכן שצריך להמשיך לתקשר עם המשתמש שימו לב שתצטרכו בעצמכם להעביר את הסוכן החדש ל Runner.run בהודעה הבאה (אחרת הוא ירוץ עם הסוכן שעובר בתור פרמטר ראשון).

  2. מבחינת המודל Handoff הוא בסך הכל Tool Calling. שם הכלי כברירת מחדל הוא transfer_to_. שימו לב לא להתנגש עם כלים קיימים שאתם מגדירים לסוכן.

  3. אם יש לכם קוד ממשק משתמש שמציג היסטוריית שיחה כדאי לזהות Handoff ולתת לו ייצוג ויזואלי שונה מ Tool Calling רגיל כדי להתאים לציפיות המשתמשים.

סך הכל Handoff הוא קונספט נחמד אבל הרבה פעמים יהיה לנו יותר קל לממש אותו בעצמנו עם הגדרת כלים במיוחד לדברים לא טריוויאליים. בתוך לולאת ה Runner של Agents SDK התבנית המרכזית בה נרצה להשתמש ב Handoff היא סוכן ראשי שממיין פניות וסוכנים ספציפיים שמטפלים בסוגי הפניות כאשר הטיפול לא דורש המשך אינטרקציה עם המשתמש.