Streaming
למה streaming חשוב בסוכן אגנטי
לולאה אגנטיתהמחזור של סוכן: תצפית, תכנון ופעולה, כשה-harness מבצע את הכלי ומוסיף את התוצאה לקונטקסט לפני הסיבוב הבא. מתוך AI Agents, Agents והלולאה האגנטית. יכולה להימשך כמה שניות טובות — כמה קריאות מודל נפרדות, הרצת כלים, ולפעמים גם קריאה חוזרת בגלל פלט מובנהסכימה שמתארת את צורת התשובה הסופית, כך שה-agent מחזיר אובייקט שתואם לה ולא רק טקסט חופשי. מתוך LangChain, Structured Output. שלא תאם את הסכימה. בלי streaming, המשתמש רואה מסך ריק עד שהכול מסתיים; עם streaming, הוא רואה התקדמות בזמן אמת — מילים שמופיעות תוך כדי כתיבה, ואיזה כלי רץ עכשיו.
זמן התגובה הכולל לא משתנה בין שני המצבים — אבל תחושת המהירות (perceived latency) שונה לגמרי: מסך שמתעדכן כל הזמן מרגיש הרבה יותר מהיר ממסך שקט שמתעורר פתאום עם תשובה שלמה.
סוגי אירועים בזרם של agent
זרם של agentLLM שמופעל בלולאה, עם מטרה וסט כלים, ובכל סיבוב מחליט אם להפעיל כלי נוסף או לסיים ולהחזיר תשובה. מתוך AI Agents, Agents והלולאה האגנטית. לא מכיל רק "טקסט שמזרים" — הוא חושף גם אירועים על מה שקורה בתוך הלולאה האגנטיתהמחזור של סוכן: תצפית, תכנון ופעולה, כשה-harness מבצע את הכלי ומוסיף את התוצאה לקונטקסט לפני הסיבוב הבא. מתוך AI Agents, Agents והלולאה האגנטית. עצמה: קטעי טקסט ברמת token (התשובה נכתבת תוך כדי), תחילת קריאה לכלי (איזה כלי, עם אילו פרמטרים), סיום קריאה לכלי (מה התוצאה), וגבולות סיבוב בלולאה (סיבוב חדש התחיל).
רמת הפירוט המדויקת תלויה במצב הסטרימינג (stream mode) שמבקשים — לפעמים מספיק לקבל רק את טקסט התשובה הסופית תוך כדי כתיבה, ולפעמים רוצים לראות את כל אירועי הביצוע הפנימיים כדי להציג "מה ה-agent עושה עכשיו" באופן מפורט.
צריכת סטרים בקוד: async iteration
במקום agent.invoke, קוראים ל-agent.stream עם אותם ארגומנטים בדיוק — הוא מחזיר iterable אסינכרוני שאפשר לעבור עליו עם for await...of, ומקבלים chunk חדש בכל פעם שיש עדכון.
const stream = await agent.stream(
{
messages: [
{ role: "user", content: "מה מזג האוויר בתל אביב, ומה ההזמנות הפתוחות שלי?" },
],
},
{ configurable: { thread_id: "chat-4", userId: "user-42" } }
);
for await (const chunk of stream) {
console.log(chunk);
}דוגמה מלאה: הצגת התקדמות לפי סוג אירוע
בפרקטיקה כדאי לבדוק את סוג ה-chunk (השדה המדויק ומצב הסטרימינג הנכון תלויים בגרסת התיעוד — כדאי לבדוק את הדוקומנטציה הרשמית לפרטים העדכניים) ולהגיב אחרת לכל סוג: טקסט חדש מודפס תוך כדי, ותחילת/סיום קריאה לכלי מוצגים כהודעת סטטוס נפרדת.
for await (const chunk of stream) {
switch (chunk.type) {
case "tool_call_start":
console.log(`🔧 מפעיל כלי: ${chunk.toolName}`);
break;
case "tool_call_end":
console.log(`✅ ${chunk.toolName} הסתיים`);
break;
case "text":
process.stdout.write(chunk.content);
break;
}
}מתי להשתמש ב-stream ומתי ב-invoke
invoke מתאים כשרק התוצאה הסופית מעניינת — קריאה משרת לשרת, job רקע, אוטומציה — ואין מי שמחכה מול מסך תוך כדי הריצה.
stream מתאים בכל מקום שיש משתמש שמחכה מול מסך: צ'אט, כלי CLI אינטראקטיבי, או כל ממשק שרוצה להראות שה-agentLLM שמופעל בלולאה, עם מטרה וסט כלים, ובכל סיבוב מחליט אם להפעיל כלי נוסף או לסיים ולהחזיר תשובה. מתוך AI Agents, Agents והלולאה האגנטית. "חי" ועובד, ולא רק ספינר אילם עד שהתשובה מוכנה.
שאלות נפוצות
איך מעבירים את הסטרים מהשרת לדפדפן?
agent.stream רץ בשרת, ולכן מעבירים את ה-chunks לדפדפן בתגובת HTTP מוזרמת, למשל Server-Sent Events: כל chunk נשלח כאירוע ברגע שהוא מגיע, והדפדפן מציג אותו. כדאי לשלוח לדפדפן רק את מה שהממשק צריך — טקסט וסטטוס של כלים — ולא את כל האירועים הפנימיים, שעלולים לכלול מידע שלא נועד למשתמש.
מה קורה כשהמשתמש סוגר את הדף באמצע ההרצה?
אם לא מטפלים בזה, ה-agent ממשיך לרוץ בשרת, מפעיל כלים וצורך טוקנים בלי שאיש מחכה לתוצאה. כדאי לזהות ניתוק של הלקוח ולבטל את ההרצה, למשל עם AbortSignal שמעבירים בהגדרות ההרצה (בדקו בתיעוד את השם המדויק). אם הפעולה צריכה להסתיים בכל מקרה, עדיף להריץ אותה כ-job רקע ולהציג את התוצאה כשהמשתמש חוזר.
האם streaming עובד יחד עם structured output?
כן, אבל האובייקט המובנה מגיע שלם רק בסוף, אחרי שאומת מול הסכימה, כי אי אפשר לאמת אובייקט חלקי. מה שאפשר להזרים בינתיים הוא אירועי ההתקדמות — אילו כלים רצים ומה הם מחזירים — כדי שהמשתמש יראה שה-agent עובד.