Middleware
Middleware הוא המימוש הקונקרטי של ה-Harness
בפרק הראשון בנושא הזה קבענו ש-createAgent בונה בפועל את אותו "הארנסהתוכנה שמריצה את הלולאה: שולחת את הקונטקסט למודל, מבצעת (או מסרבת לבצע) את מה שביקש, ומחזירה את התוצאה. מתוך AI Agents, מבוא לאקוסיסטם: מה יש מסביב ל-LLM." שנלמד בנושא AI Agents — model, tools, ו-middleware. middleware הוא בדיוק החלק השלישי הזה: המנגנון שמאפשר להתערב בלולאה האגנטיתהמחזור של סוכן: תצפית, תכנון ופעולה, כשה-harness מבצע את הכלי ומוסיף את התוצאה לקונטקסט לפני הסיבוב הבא. מתוך AI Agents, Agents והלולאה האגנטית. עצמה, לא רק לספק לה כלים או מודל.
כל מה שראינו בפרק ה-Harness (הרשאות, sandboxingהגבלה מראש של מה שהסוכן יכול לעשות, למשל סביבה מבודדת בלי גישה לרשת, כך שפעולות מסוימות בלתי אפשריות מלכתחילה. מתוך AI Agents, The Harness — מי בפועל מריץ את הסוכן., תקציבים, לוגים) הוא דוגמה קונקרטית למה ש-middleware יכול לממש בקוד LangChainפריימוורק בקוד פתוח לבניית אפליקציות מבוססות LLM ו-agents, שעוטף רכיבים חוזרים בממשק אחיד. מתוך LangChain, מבוא ל-LangChain. אמיתי.
ה-hook lifecycle: איפה middleware מתערב
middlewareהמנגנון ב-LangChain שמאפשר להתערב בלולאה האגנטית עצמה; המימוש הקונקרטי של ה-harness. מתוך LangChain, Middleware. נתלה בנקודות קבועות לאורך הלולאה האגנטיתהמחזור של סוכן: תצפית, תכנון ופעולה, כשה-harness מבצע את הכלי ומוסיף את התוצאה לקונטקסט לפני הסיבוב הבא. מתוך AI Agents, Agents והלולאה האגנטית.: לפני שקוראים למודל, אחרי שהמודל מחזיר תשובה, לפני שמפעילים כלי, ואחרי שהכלי מחזיר תוצאה. בכל נקודה כזו middleware יכול לקרוא את המצב הנוכחי, לשנות אותו, או — כפי שנראה בהמשך — לעצור את הפעולה לגמרי.
שמות ה-hooks המדויקים והחתימה שלהם תלויים בגרסת LangChainפריימוורק בקוד פתוח לבניית אפליקציות מבוססות LLM ו-agents, שעוטף רכיבים חוזרים בממשק אחיד. מתוך LangChain, מבוא ל-LangChain. שבה אתם משתמשים — כדאי לבדוק את התיעוד הרשמי לפרטים העדכניים; הדוגמאות בפרק הזה ממחישות את העיקרון, לא מצטטות API קפוא בזמן.
Middleware מובנה מראש
LangChainפריימוורק בקוד פתוח לבניית אפליקציות מבוססות LLM ו-agents, שעוטף רכיבים חוזרים בממשק אחיד. מתוך LangChain, מבוא ל-LangChain. מגיע עם קטגוריות שלמות של middlewareהמנגנון ב-LangChain שמאפשר להתערב בלולאה האגנטית עצמה; המימוש הקונקרטי של ה-harness. מתוך LangChain, Middleware. מוכן לשימוש, בלי לכתוב אותו בעצמכם: guardrails לזיהוי מידע רגיש (PIIמידע אישי מזהה, שדורש החלטה כבר בשלב ה-ingestion: להסיר, להחליף במזהים או לאנדקס עם הרשאות מחמירות. מתוך RAG, הערכה ו-RAG בפרודקשן.) וסינון תוכן, fault tolerance עם retries ו-fallbacks כשקריאה למודל נכשלת, וsteering ל-human-in-the-loopמעורבות אנושית כסקאלה, מאוטונומיה מלאה ועד אישור על כל פעולה, עם נקודות אישור רק איפה שהן באמת חשובות. מתוך AI Agents, הרשאות ובטיחות — סיכום הנושא. — עצירה לאישור אנושי לפני פעולה מסוימת, בדיוק כמו שראינו ברמת העיקרון בפרק ה-Harnessהתוכנה שמריצה את הלולאה: שולחת את הקונטקסט למודל, מבצעת (או מסרבת לבצע) את מה שביקש, ומחזירה את התוצאה. מתוך AI Agents, מבוא לאקוסיסטם: מה יש מסביב ל-LLM..
היתרון של middleware מובנה מראש הוא שאין צורך לממש מחדש לוגיקה גנרית כמו retry-with-backoff או זיהוי PII בכל פרויקט — מוסיפים אותו לרשימת ה-middleware ומקבלים את ההתנהגות מוכנה.
כתיבת middleware מותאם אישית
כשצריך התנהגות ספציפית לפרויקט — לוגים בפורמט מסוים, מדדים, או כלל עסקי ייחודי — כותבים middlewareהמנגנון ב-LangChain שמאפשר להתערב בלולאה האגנטית עצמה; המימוש הקונקרטי של ה-harness. מתוך LangChain, Middleware. משלכם: אובייקט עם פונקציות ל-hooks הרלוונטיים, שמועבר לרשימת middleware ב-createAgent.
const loggingMiddleware = {
beforeModel: async ({ messages }: { messages: Message[] }) => {
console.log(`שולח ${messages.length} הודעות למודל`);
},
afterToolCall: async ({ toolName, result }: { toolName: string; result: unknown }) => {
console.log(`כלי ${toolName} החזיר:`, result);
},
};
const agent = createAgent({
model: "anthropic:claude-sonnet-5",
tools: [getWeather],
middleware: [loggingMiddleware],
});דוגמה מלאה: חסימת כלי מסוכן בלי אישור
בפרק ה-Harnessהתוכנה שמריצה את הלולאה: שולחת את הקונטקסט למודל, מבצעת (או מסרבת לבצע) את מה שביקש, ומחזירה את התוצאה. מתוך AI Agents, מבוא לאקוסיסטם: מה יש מסביב ל-LLM. בנושא AI Agents ראינו דוגמת JSON של agentLLM שמופעל בלולאה, עם מטרה וסט כלים, ובכל סיבוב מחליט אם להפעיל כלי נוסף או לסיים ולהחזיר תשובה. מתוך AI Agents, Agents והלולאה האגנטית. עם הרשאות מוגבלות (code-review-worker עם scope שאוסר כתיבה ורשת). middlewareהמנגנון ב-LangChain שמאפשר להתערב בלולאה האגנטית עצמה; המימוש הקונקרטי של ה-harness. מתוך LangChain, Middleware. הוא המקום שבו אכיפה כזו קורית בפועל בקוד: לפני שכלי רץ, ה-middleware יכול לבדוק את הפרמטרים שלו ולחסום את הקריאה אם היא חורגת מהמדיניות שהוגדרה — בלי לסמוך על כך שהמודל 'יבחר' לא לקרוא לכלי.
בדוגמה הבאה beforeToolCall בודק בקשת זיכוי גדולה מדי, וזורק שגיאה במקום לתת לכלי לרוץ — בדיוק אותו עקרון של least privilegeלתת לכל סוכן רק את ההרשאות שהוא צריך למשימה הנוכחית, ולא גישה רחבה "ליתר ביטחון". מתוך AI Agents, הרשאות ובטיחות — סיכום הנושא. ו-approval gatesנקודה שבה ה-harness עוצר לפני פעולה רגישה ומבקש אישור מפורש מהמשתמש. מתוך AI Agents, The Harness — מי בפועל מריץ את הסוכן. שכבר נלמד, רק הפעם אכוף ב-middleware אמיתי.
const approvalMiddleware = {
beforeToolCall: async ({
toolName,
args,
}: {
toolName: string;
args: Record<string, unknown>;
}) => {
if (toolName === "issue_refund" && Number(args.amount) > 1000) {
throw new Error("זיכוי מעל 1000 ש\"ח דורש אישור אנושי לפני ביצוע");
}
},
};
const agent = createAgent({
model: "anthropic:claude-sonnet-5",
tools: [getWeather, issueRefundTool],
middleware: [approvalMiddleware],
});שאלות נפוצות
באיזה סדר רצים כמה middleware?
לפי הסדר ברשימה שמעבירים ל-createAgent, אבל הכיוון יכול להיות שונה בין hooks שלפני פעולה לבין hooks שאחריה: בדרך כלל ה"לפני" רצים לפי סדר הרשימה וה"אחרי" בסדר הפוך, כמו שכבות שעוטפות זו את זו. הפרטים המדויקים תלויים בגרסה, ולכן כשהסדר חשוב (למשל סינון PII לפני לוגים) כדאי לבדוק בתיעוד.
מה ההבדל בין חסימה ב-middleware לבין בדיקה בתוך הכלי עצמו?
שתיהן עובדות, אבל middleware מתאים למדיניות שחלה על כמה כלים או על כל ה-agent — PII, תקציב, אישור אנושי — ומרכז אותה במקום אחד. בדיקה בתוך הכלי מתאימה לחוקים שהם חלק מהלוגיקה העסקית שלו. בכלים רגישים כדאי את שתיהן: גם אם middleware יוסר בטעות, הכלי עדיין לא יבצע פעולה אסורה.
האם middleware מאט את ה-agent?
middleware שעושה בדיקה מקומית, כמו השוואת סכום, מוסיף זמן זניח. middleware שקורא למודל או לשירות חיצוני — למשל זיהוי תוכן עם מודל נוסף או סיכום היסטוריה — מוסיף קריאה בכל סיבוב, ולכן כדאי למדוד את ההשפעה שלו ב-traces (פרק 10).