10. פרוטוקולי צוות

"חברי צוות צריכים כללי תקשורת משותפים"

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

מה זה פרוטוקול בתקשורת סוכנים?

לחיצת יד מובנית — צד אחד שולח בקשה עם מזהה ייחודי, השני מגיב תוך הפניה למזהה הזה. פרוטוקולים מונעים אי הבנות: 'האם סיימת משימה X?' / 'כן, הנה תוצאה X.' במקום הודעות חופשיות.

מה זה פרוטוקול כיבוי (shutdown)?

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

מה זה אישור תוכנית?

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

הבעיה

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

כיבוי: הריגת thread משאירה קבצים חצי-כתובים ו-config.json מיושן. צריך לחיצת יד: המוביל מבקש, חבר הצוות מאשר (מסיים ויוצא) או דוחה (ממשיך לעבוד).

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

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

הפתרון

Shutdown Protocol            Plan Approval Protocol
==================           ======================

Lead             Teammate    Teammate           Lead
  |                 |           |                 |
  |--shutdown_req-->|           |--plan_req------>|
  | {req_id:"abc"}  |           | {req_id:"xyz"}  |
  |                 |           |                 |
  |<--shutdown_resp-|           |<--plan_resp-----|
  | {req_id:"abc",  |           | {req_id:"xyz",  |
  |  approved:true} |           |  approved:false,|
  |                 |           |  feedback:"..."}|

איך זה עובד

  1. מזהי בקשות הם UUIDs קצרים. הבקשה והתגובה נושאות את אותו המזהה.
import uuid

def new_req_id() -> str:
    return uuid.uuid4().hex[:8]

def send_shutdown_request(teammate_name: str) -> str:
    req_id = new_req_id()
    send_message(teammate_name, "lead", json.dumps({
        "type": "shutdown_req",
        "req_id": req_id,
    }))
    return req_id  # caller stores this to match the response

def handle_shutdown_request(msg: dict, name: str) -> None:
    req_id = msg["req_id"]
    # Teammate decides: approve if idle, reject if mid-task
    currently_working = get_status(name) == "WORKING"
    send_message("lead", name, json.dumps({
        "type": "shutdown_resp",
        "req_id": req_id,
        "approved": not currently_working,
        "reason": "finishing current task" if currently_working else "ready to shutdown",
    }))
    if not currently_working:
        update_status(name, "SHUTDOWN")
  1. אישור תוכנית משתמש באותה התבנית, מורחב עם תוכן תוכנית מובנה.
def request_plan_approval(plan: str, task_id: int) -> str:
    req_id = new_req_id()
    send_message("lead", "self", json.dumps({
        "type": "plan_req",
        "req_id": req_id,
        "task_id": task_id,
        "plan": plan,
    }))
    return req_id

def handle_plan_request(msg: dict) -> dict:
    """Lead reviews and approves/rejects the plan."""
    # Lead's agent loop sees this in its inbox and decides
    req_id = msg["req_id"]
    teammate = msg.get("from")
    # The LLM reviews the plan and calls approve_plan or reject_plan tool
    return {"req_id": req_id, "teammate": teammate, "plan": msg["plan"]}
  1. הלולאה של חבר הצוות בודקת סוגי הודעות לפני פעולה.
def process_inbox(name: str) -> None:
    messages = drain_inbox(name)
    for msg_raw in messages:
        try:
            msg = json.loads(msg_raw["content"])
            msg_type = msg.get("type", "plain")
        except (json.JSONDecodeError, KeyError):
            msg_type = "plain"
            msg = msg_raw

        if msg_type == "shutdown_req":
            handle_shutdown_request(msg, name)
        elif msg_type == "plan_resp":
            handle_plan_response(msg, name)
        else:
            # Plain task assignment — start working
            start_task(msg_raw["content"], name)

מה השתנה מ-צוותי סוכנים

רכיבלפני (צוותי סוכנים)אחרי (פרוטוקולי צוות)
כיבויהרג threadלחיצת יד req/resp מסודרת
סקירת תוכניתאיןבקשת תוכנית + אישור מוביל
פורמט הודעותטקסט חופשיJSON מוקלד עם req_id
בטיחותנמוכהנקודות בדיקה מפורשות לסיכון

מסקנה מרכזית

פרוטוקולים הופכים תקשורת חופשית למשא ומתן מובנה. תבנית req_id היא המפתח — היא מאפשרת לך להתאים תגובה לבקשה שגרמה לה, גם כשהודעות מגיעות שלא בסדר או עם עיכובים. אותה תבנית דו-שלבית (שלח בקשה, המתן לתגובה עם מזהה תואם) עובדת עבור כל צורך תיאום.

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

פרוטוקול בקשה-תשובה
1def new_req_id() -> str:
2 return uuid.uuid4().hex[:8]
3 
4def send_shutdown_request(teammate_name: str) -> str:
5 req_id = new_req_id()
6 send_message(teammate_name, "lead", json.dumps({
7 "type": "shutdown_req",
8 "req_id": req_id,
9 }))
10 return req_id
11 
12def handle_shutdown_request(msg: dict, name: str) -> None:
13 req_id = msg["req_id"]
14 currently_working = get_status(name) == "WORKING"
15 send_message("lead", name, json.dumps({
16 "type": "shutdown_resp",
17 "req_id": req_id,
18 "approved": not currently_working,
19 "reason": "finishing current task" if currently_working else "ready to shutdown",
20 }))
21 if not currently_working:
22 update_status(name, "SHUTDOWN")
23 
24def process_inbox(name: str) -> None:
25 messages = drain_inbox(name)
26 for msg_raw in messages:
27 try:
28 msg = json.loads(msg_raw["content"])
29 msg_type = msg.get("type", "plain")
30 except (json.JSONDecodeError, KeyError):
31 msg_type = "plain"
32 if msg_type == "shutdown_req":
33 handle_shutdown_request(msg, name)
34 else:
35 start_task(msg_raw["content"], name)
36 
new_req_id() מייצרת מחרוזת hex בת 8 תווים מ-UUID. קצרה מספיק לכלול בהודעות מבלי להפריח אותן, ייחודית מספיק כדי להימנע מהתנגשויות בין סוכנים מקבילים.
שלב 1 מתוך 4
🧪 נסו בעצמכם

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

רמז

השתמשו בסוגי הודעות REQUEST/RESPONSE עם שדה "plan"

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