Tool Use ו-Function Calling, מדריך מלא

📚 פיתוח עם Claude, Claude Code & API ⏱️ 7 דק׳ 🎓 בינוני ✓ חינם לגמרי
Tool Use ו-Function Calling, מדריך מלא

מה ההבדל בין chatbot ל-agent?

chatbot עונה מהזיכרון. agent פועל בעולם. Tool Use הוא הגשר בין השניים.

כשאתה שואל את Claude "כמה לקוחות יש לנו היום?", הוא לא יודע. אבל אם תגדיר לו כלי בשם query_database, הוא יחליט לקרוא לו, יחכה לתוצאה, ויענה בדיוק. זה Tool Use (שנקרא גם Function Calling).

הרעיון: Claude מחזיר stop_reason: "tool_use" עם בלוק tool_use שמכיל שם הכלי ופרמטרים. הקוד שלך מבצע את הפעולה, DB query, קריאת API, שליחת מייל, ושולח את התוצאה חזרה. Claude קורא, ממשיך, עד ל-stop_reason: "end_turn".

הגדרת כלי, JSON Schema מלא

כל כלי מורכב משלושה שדות חובה: namedescription, ו-input_schema. ה-description הוא הגורם הכי קריטי לביצועים, תיעוד Anthropic מדגיש: "Provide extremely detailed descriptions. This is by far the most important factor in tool performance."

שדהמה לכלולדוגמה רעהדוגמה טובה
nameמזהה ייחודי, a-z/0-9/_/-tool1search_customers
descriptionמה עושה, מתי לקרוא, מה מחזיר, מגבלות"מחפש לקוחות""מחפש לקוחות לפי שם/מייל/מזהה. השתמש כשמשתמש שואל על לקוח ספציפי. מחזיר מקסימום 20 תוצאות. לא מחזיר פרטי תשלום."
input_schemaJSON Schema מלא עם types, enums, requiredproperties ריקtype, description, enum לכל פרמטר
const tools = [{
  name: "search_customers",
  description: "מחפש לקוחות לפי קריטריונים. השתמש כשנדרש מידע על לקוח ספציפי. מחזיר עד 20 תוצאות עם שם, מייל, וסטטוס. לא מחזיר פרטי אשראי.",
  input_schema: {
    type: "object",
    properties: {
      query: { type: "string", description: "שם, מייל, או מזהה לחיפוש" },
      status: { type: "string", enum: ["active","inactive","all"], description: "סנן לפי סטטוס" },
      limit: { type: "integer", description: "מספר תוצאות, ברירת מחדל 10" }
    },
    required: ["query"]
  }
}];

עדכון 2026: ניתן להוסיף שדה input_examples לtool definition עם מערך דוגמאות schema-validated. זה עוזר לClaude להבין פרמטרים מורכבים ופורמטים ספציפיים, מבלי להכביד על ה-description.

עדכון נוסף: strict: true בהגדרת הכלי מבטיח שClaude תמיד מחזיר inputs שתואמים לschema בדיוק, שימושי כשהקוד שלך לא סובל deviations.

הלולאה האגנטית, הקוד שמחזיק הכל יחד

הלולאה האגנטית היא while loop פשוט: שלח בקשה, בדוק stop_reason, אם tool_use, בצע ושלח תוצאה, אם end_turn, סיים.

import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic();

async function runAgentLoop(userMessage) {
  const messages = [{ role: "user", content: userMessage }];

  while (true) {
    const response = await client.messages.create({
      model: "claude-opus-4-7",
      max_tokens: 4096,
      tools,
      messages
    });

    if (response.stop_reason === "end_turn") {
      const text = response.content.find(b => b.type === "text");
      return text?.text ?? "";
    }

    if (response.stop_reason === "tool_use") {
      // 1. הוסף תשובת Claude להיסטוריה, חובה!
      messages.push({ role: "assistant", content: response.content });

      // 2. בצע את כל הכלים שClaude ביקש
      const toolResults = [];
      for (const block of response.content) {
        if (block.type !== "tool_use") continue;
        let result;
        try {
          result = await executeTool(block.name, block.input);
        } catch (e) {
          result = { error: String(e) };
        }
        toolResults.push({
          type: "tool_result",
          tool_use_id: block.id,
          content: JSON.stringify(result)
        });
      }

      // 3. שלח את כל התוצאות בהודעת user אחת
      messages.push({ role: "user", content: toolResults });
    }
  }
}

3 טעויות קריטיות שמובילות ל-bugs

טעות 1, לא מוסיפים assistant message לפני tool_results: Claude צריך לראות את התשובה שלו עצמו כדי לקשר tool_result לקריאה שעשה. בלי זה, infinite loop או תשובות מבולגנות. כלל: תמיד push את response.content לmessages לפני שאתה מוסיף tool_results.

טעות 2, בדיקה רק על content[0]: Claude יכול להחזיר text block לפני tool_use block. קוד שמסתכל רק על content[0] מפספס את הקריאה לכלי. תמיד iterate על כל response.content ובדוק block.type.

טעות 3, tool_result אחד ל-multiple tool_use: כשClaude קורא לשני כלים במקביל, חייבים להחזיר tool_result נפרד לכל block.id. הכל באותה user message, אבל בנפרד.

tool_choice, שליטה על מתי Claude משתמש בכלים

ה-default הוא auto, Claude מחליט. אבל יש מצבים שצריך שליטה:

tool_choiceמה קורהמתי להשתמש
auto (ברירת מחדל)Claude מחליט אם לקרוא לכלירוב המקרים
anyClaude חייב לקרוא לאחד הכליםכשרוצים תמיד JSON structured output
tool (+ name)Claude חייב לקרוא לכלי הספציפיextraction מאולצת, classification
noneClaude לא יכול לקרוא לשום כליכשמעבירים tools אבל לא רוצים שישתמש

שלב tool_choice: {type: "any"} עם strict: true לקבל JSON מובנה וvalidated בכל קריאה.

דוגמה ישראלית, מערכת CRM לסטארטאפ תל אביבי

סטארטאפ B2B בתל אביב רוצה שClaude יוכל לענות לשאלות של נציגי מכירות על לקוחות. הם מגדירים שני כלים: get_customer ו-list_open_deals. נציג שואל: "מה הסטטוס של Tamar Cohen מחברת BioTech IL?", Claude קורא ל-get_customer עם query="BioTech IL", מקבל ID, אח"כ קורא ל-list_open_deals עם customer_id, ועונה: "יש 2 עסקאות פתוחות ב-BioTech IL, אחת בסך 45K ש"ח בשלב נגוציאציה, השנייה 120K ש"ח ב-Proposal." הנציג לא נגע בCRM.

אנא בדוק אם יש לקוחות פעילים מ-Q4 2025 עם חוזה שמסתיים השנה.
הגדר כלי list_customers עם פרמטרים: status (active/inactive), contract_end_before (date), limit. Claude יקרא לכלי עם הפרמטרים הנכונים, יקבל נתוני DB אמיתיים, ויחזיר רשימה מדויקת, לא ניחושים.
להמתין שניה לפני הקריאה הבאה לAPI
להוסיף את תשובת assistant (response.content) ל-messages, כדי שClaude יקשר בין tool_result ל-tool_use שלו
לנקות את messages ולהתחיל מחדש עם הcontext
לשלוח tool_result ריק עם content: ""

רוצה ללמוד עם מעקב התקדמות, קוויזים ותעודה?

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