Gemini מאפשר לשלב כלים מובנים, כמו google_search, וקריאות לפונקציות (שנקראות גם כלים בהתאמה אישית) ביצירה אחת, על ידי שמירה של היסטוריית ההקשר של קריאות לכלים וחשיפה שלה. שילובים מובנים ומותאמים אישית של כלים מאפשרים תהליכי עבודה מורכבים ודינמיים. לדוגמה, המודל יכול להסתמך על נתונים מהאינטרנט בזמן אמת לפני שהוא מפעיל את הלוגיקה העסקית הספציפית שלכם.
דוגמה שבה מופעלים שילובים מובנים ומותאמים אישית של כלים באמצעות google_search ופונקציה מותאמת אישית getWeather:
Python
from google import genai
from google.genai import types
client = genai.Client()
getWeather = {
"name": "getWeather",
"description": "Gets the weather for a requested city.",
"parameters": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "The city and state, e.g. Utqiaġvik, Alaska",
},
},
"required": ["city"],
},
}
# Turn 1: Initial request with Google Search (built-in) and getWeather (custom) tools enabled
response = client.models.generate_content(
model="gemini-3-flash-preview",
contents="What is the northernmost city in the United States? What's the weather like there today?",
config=types.GenerateContentConfig(
tools=[
types.Tool(
google_search=types.ToolGoogleSearch(), # Built-in tool
function_declarations=[getWeather] # Custom tool
),
],
include_server_side_tool_invocations=True
),
)
for part in response.candidates[0].content.parts:
if part.tool_call:
print(f"Tool call: {part.tool_call.tool_type} (ID: {part.tool_call.id})")
if part.tool_response:
print(f"Tool response: {part.tool_response.tool_type} (ID: {part.tool_response.id})")
if part.function_call:
print(f"Function call: {part.function_call.name} (ID: {part.function_call.id})")
# Turn 2: Manually build history to circulate both tool and function context
history = [
types.Content(
role="user",
parts=[types.Part(text="What is the northernmost city in the United States? What's the weather like there today?")]
),
# Response from Turn 1 includes tool_call, tool_response, and thought_signatures
response.candidates[0].content,
# Return the function_response
types.Content(
role="user",
parts=[types.Part(
function_response=types.FunctionResponse(
name="getWeather",
response={"response": "Very cold. 22 degrees Fahrenheit."},
id=response.candidates[0].content.parts[2].function_call.id # Match the ID from the function_call
)
)]
)
]
response_2 = client.models.generate_content(
model="gemini-3-flash-preview",
contents=history,
config=types.GenerateContentConfig(
tools=[
types.Tool(
google_search=types.ToolGoogleSearch(),
function_declarations=[getWeather]
),
],
# This flag needs to be enabled for built-in tool context circulation and tool combination
include_server_side_tool_invocations=True
),
)
for part in response_2.candidates[0].content.parts:
if part.text:
print(part.text)
JavaScript
import { GoogleGenAI } from '@google/genai';
const client = new GoogleGenAI({});
const getWeather = {
name: "getWeather",
description: "Get the weather in a given location",
parameters: {
type: "OBJECT",
properties: {
location: {
type: "STRING",
description: "The city and state, e.g. San Francisco, CA"
}
},
required: ["location"]
}
};
async function run() {
const model = client.getGenerativeModel({
model: "gemini-3-flash-preview",
});
const tools = [
{ googleSearch: {} },
{ functionDeclarations: [getWeather] }
];
// This flag needs to be enabled for built-in tool context circulation and tool combination
const toolConfig = { includeServerSideToolInvocations: true };
// Turn 1: Initial request with Google Search (built-in) and getWeather (custom) tools enabled
const result1 = await model.generateContent({
contents: [{role: "user", parts: [{text: "What is the northernmost city in the United States? What's the weather like there today?"}]}],
tools: tools,
toolConfig: toolConfig,
});
const response1 = result1.response;
for (const part of response1.candidates[0].content.parts) {
if (part.toolCall) {
console.log(`Tool call: ${part.toolCall.toolType} (ID: ${part.toolCall.id})`);
}
if (part.toolResponse) {
console.log(`Tool response: ${part.toolResponse.toolType} (ID: ${part.toolResponse.id})`);
}
if (part.functionCall) {
console.log(`Function call: ${part.functionCall.name} (ID: ${part.functionCall.id})`);
}
}
const functionCallId = response1.candidates[0].content.parts.find(p => p.functionCall)?.functionCall?.id;
// Turn 2: Manually build history to circulate both tool and function context
const history = [
{
role: "user",
parts:[{text: "What is the northernmost city in the United States? What's the weather like there today?"}]
},
// Response from Turn 1 includes tool_call, tool_response, and thought_signatures
response1.candidates[0].content,
// Return the function_response
{
role: "user",
parts: [{
functionResponse: {
name: "getWeather",
response: {response: "Very cold. 22 degrees Fahrenheit."},
id: functionCallId // Match the ID from the function_call
}
}]
}
];
const result2 = await model.generateContent({
contents: history,
tools: tools,
toolConfig: toolConfig,
});
for (const part of result2.response.candidates[0].content.parts) {
if (part.text) {
console.log(part.text);
}
}
}
run();
Go
package main
import (
"context"
"fmt"
"log"
"os"
"github.com/google/generative-ai-go/genai"
"google.golang.org/api/option"
)
func main() {
ctx := context.Background()
client, err := genai.NewClient(ctx, option.WithAPIKey(os.Getenv("GEMINI_API_KEY")))
if err != nil {
log.Exit(err)
}
defer client.Close()
getWeather := &genai.FunctionDeclaration{
Name: "getWeather",
Description: "Get the weather in a given location",
Parameters: &genai.Schema{
Type: genai.Object,
Properties: map[string]*genai.Schema{
"location": {
Type: genai.String,
Description: "The city and state, e.g. San Francisco, CA",
},
},
Required: []string{"location"},
},
}
model := client.GenerativeModel("gemini-3-flash-preview")
model.Tools = []*genai.Tool{
{GoogleSearch: &genai.GoogleSearch{}}, // Built-in tool
{FunctionDeclarations: []*genai.FunctionDeclaration{getWeather}}, // Custom tool
}
ist := true
model.ToolConfig = &genai.ToolConfig{
IncludeServerSideToolInvocations: &ist, // This flag needs to be enabled for built-in tool context circulation and tool combination
}
chat := model.StartChat()
// Turn 1: Initial request with Google Search (built-in) and getWeather (custom) tools enabled
prompt := genai.Text("What is the northernmost city in the United States? What's the weather like there today?")
resp1, err := chat.SendMessage(ctx, prompt)
if err != nil {
log.Exitf("SendMessage failed: %v", err)
}
if resp1 == nil || len(resp1.Candidates) == 0 || resp1.Candidates[0].Content == nil {
log.Exit("empty response from model")
}
var functionCallID string
for _, part := range resp1.Candidates[0].Content.Parts {
switch p := part.(type) {
case genai.FunctionCall:
fmt.Printf("Function call: %s (ID: %s)\n", p.Name, p.ID)
if p.Name == "getWeather" {
functionCallID = p.ID
}
case genai.ToolCallPart:
fmt.Printf("Tool call: %s (ID: %s)\n", p.ToolType, p.ID)
case genai.ToolResponsePart:
fmt.Printf("Tool response: %s (ID: %s)\n", p.ToolType, p.ID)
}
}
if functionCallID == "" {
log.Exit("no getWeather function call in response")
}
// Turn 2: Provide function result back to model.
// Chat history automatically includes tool_call, tool_response, and thought_signatures from Turn 1.
fr := genai.FunctionResponse{
Name: "getWeather",
ID: functionCallID,
Response: map[string]any{
"response": "Very cold. 22 degrees Fahrenheit.",
},
}
resp2, err := chat.SendMessage(ctx, fr)
if err != nil {
log.Exitf("SendMessage for turn 2 failed: %v", err)
}
if resp2 == nil || len(resp2.Candidates) == 0 || resp2.Candidates[0].Content == nil {
log.Exit("empty response from model in turn 2")
}
for _, part := range resp2.Candidates[0].Content.Parts {
if txt, ok := part.(genai.Text); ok {
fmt.Println(string(txt))
}
}
}
REST
# Turn 1: Initial request with Google Search (built-in) and getWeather (custom) tools enabled
curl -X POST "https://generativelanguage.googleapis.com/v1beta/models/gemini-3-flash-preview:generateContent" \
-H "Content-Type: application/json" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-d '{
"contents": [{
"role": "user",
"parts": [{
"text": "What is the northernmost city in the United States? What'\''s the weather like there today?"
}]
}],
"tools": [{
"googleSearch": {}
}, {
"functionDeclarations": [{
"name": "getWeather",
"description": "Get the weather in a given location",
"parameters": {
"type": "OBJECT",
"properties": {
"location": {
"type": "STRING",
"description": "The city and state, e.g. San Francisco, CA"
}
},
"required": ["location"]
}
}]
}],
"toolConfig": {
"includeServerSideToolInvocations": true
}
}'
# Turn 2: Manually build history to circulate both tool and function context
# The following request assumes you have captured candidates[0].content from Turn 1 response,
# and extracted function_call.id for getWeather.
# Replace FUNCTION_CALL_ID and insert candidate content from turn 1.
curl -X POST "https://generativelanguage.googleapis.com/v1beta/models/gemini-3-flash-preview:generateContent" \
-H "Content-Type: application/json" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-d '{
"contents": [
{
"role": "user",
"parts": [{"text": "What is the northernmost city in the United States? What'\''s the weather like there today?"}]
},
YOUR_CANDIDATE_CONTENT_FROM_TURN_1_RESPONSE,
{
"role": "user",
"parts": [{
"functionResponse": {
"name": "getWeather",
"id": "FUNCTION_CALL_ID",
"response": {"response": "Very cold. 22 degrees Fahrenheit."}
}
}]
}
],
"tools": [{
"googleSearch": {}
}, {
"functionDeclarations": [{
"name": "getWeather",
"description": "Get the weather in a given location",
"parameters": {
"type": "OBJECT",
"properties": {
"location": {
"type": "STRING",
"description": "The city and state, e.g. San Francisco, CA"
}
},
"required": ["location"]
}
}]
}],
"toolConfig": {
"includeServerSideToolInvocations": true
}
}'
איך זה עובד
מודלים של Gemini 3 משתמשים בהעברת הקשר של כלי כדי לאפשר שילובים מובנים ומותאמים אישית של כלים. העברת הקשר של כלי מאפשרת לשמור את ההקשר של כלים מובנים ולחשוף אותו, ולשתף אותו עם כלים מותאמים אישית באותה שיחה, מתור אחד לתור הבא.
הפעלת שילוב של כלים
- כדי להפעיל את ההעברה של הקשר של הכלי, צריך להגדיר את הדגל
include_server_side_tool_invocationsלערךtrue. - כדי להפעיל את ההתנהגות המשולבת, צריך לכלול את
function_declarations, יחד עם הכלים המובנים שרוצים להשתמש בהם.- אם לא תכללו את
function_declarations, עדיין תהיה השפעה של העברת ההקשר של הכלי על הכלים המובנים שכללתם, כל עוד הדגל מוגדר.
- אם לא תכללו את
חלקים שמוחזרים על ידי ה-API
בתשובה אחת, ה-API מחזיר את החלקים toolCall ו-toolResponse של קריאת הפונקציה המובנית. במקרה של קריאה לפונקציה (כלי בהתאמה אישית), ה-API מחזיר את functionCall החלק של הקריאה, והמשתמש מספק את החלק functionResponse בתור הבא.
-
toolCallו-toolResponse: ה-API מחזיר את החלקים האלה כדי לשמור על ההקשר של הכלים שמופעלים בצד השרת, ועל התוצאה של ההרצה שלהם, לתור הבא. -
functionCallו-functionResponse: ה-API שולח את בקשה להפעלת פונקציה למשתמש כדי למלא אותה, והמשתמש שולח את התוצאה בחזרה בתגובה לפונקציה (החלקים האלה הם סטנדרטיים לכל הקריאות לפונקציות ב-Gemini API, ולא ייחודיים לתכונה של שילוב כלים). - (כלי להרצת קוד בלבד)
executableCodeו-codeExecutionResult: כשמשתמשים בכלי להרצת קוד, במקוםfunctionCallו-functionResponse, ה-API מחזירexecutableCode(הקוד שנוצר על ידי המודל שאמור להיות מורץ) ו-codeExecutionResult(התוצאה של הקוד שניתן להרצה).
כדי לשמור על ההקשר ולאפשר שילוב של כלים, צריך להחזיר למודל את כל החלקים, כולל כל השדות שהם מכילים, בכל תור.
שדות קריטיים בחלקים שמוחזרים
חלקים מסוימים שמוחזרים על ידי ה-API יכללו את השדות id, tool_type ו-thought_signature. השדות האלה חשובים לשמירה על ההקשר של הכלי (ולכן חשובים לשילובים של כלים). אתם צריכים להחזיר את כל החלקים כפי שמופיעים בתגובה בבקשות הבאות שלכם.
-
id: מזהה ייחודי שממפה קריאה לתגובה שלה. הערך שלidמוגדר בכל התשובות לבקשות להפעלת פונקציות, ללא קשר להעברת ההקשר של הכלי. חובה לספק את אותוidבתשובת הפונקציה שה-API מספק בבקשה להפעלת פונקציה. הכלים המובנים משתפים באופן אוטומטי אתidבין קריאת הכלי לתגובה של הכלי.- מופיע בכל החלקים שקשורים לכלי:
toolCall,toolResponse,functionCall,functionResponse,executableCode,codeExecutionResult
- מופיע בכל החלקים שקשורים לכלי:
-
tool_type: מזהה את הכלי הספציפי שבו נעשה שימוש; הכלי המובנה המילולי או (לדוגמה,URL_CONTEXT) או שם הפונקציה (לדוגמה,getWeather).- נמצא בחלקים
toolCallו-toolResponse.
- נמצא בחלקים
-
thought_signature: ההקשר המוצפן בפועל שמוטמע בכל חלק שמוחזר על ידי ה-API. אי אפשר לשחזר את ההקשר בלי חתימות מחשבה. אם לא תחזירו את חתימות המחשבה לכל החלקים בכל תור, המודל יחזיר שגיאה.- נמצא בכל החלקים.
נתונים ספציפיים לכלי
חלק מהכלים המובנים מחזירים ארגומנטים של נתונים שגלויים למשתמשים, שספציפיים לסוג הכלי.
| כלי | User visible tool call args (if any) | תגובה של הכלי שגלויה למשתמש (אם יש) |
|---|---|---|
| GOOGLE_SEARCH | queries |
search_suggestions |
| GOOGLE_MAPS | queries |
placesgoogle_maps_widget_context_token |
| URL_CONTEXT | urlsכתובות URL לבדיקה |
urls_metadataretrieved_url: כתובות URL שנבדקוurl_retrieval_status: סטטוס הבדיקה |
| FILE_SEARCH | ללא | ללא |
דוגמה למבנה של בקשה לשילוב כלים
מבנה הבקשה הבא מציג את מבנה הבקשה של ההנחיה: "What
is the northernmost city in the United States? What's the weather like there
today?". הוא משלב שלושה כלים: כלי Gemini המובנים google_search ו-code_execution, ופונקציה בהתאמה אישית get_weather.
{
"model": "models/gemini-3-flash-preview",
"contents": [{
"parts": [{
"text": "What is the northernmost city in the United States? What's the weather like there today?"
}],
"role": "user"
}, {
"parts": [{
"thoughtSignature": "...",
"toolCall": {
"toolType": "GOOGLE_SEARCH_WEB",
"args": {
"queries": ["northernmost city in the United States"]
},
"id": "a7b3k9p2"
}
}, {
"thoughtSignature": "...",
"toolResponse": {
"toolType": "GOOGLE_SEARCH_WEB",
"response": {
"search_suggestions": "..."
},
"id": "a7b3k9p2"
}
}, {
"functionCall": {
"name": "getWeather",
"args": {
"city": "Utqiaġvik, Alaska"
},
"id": "m4q8z1v6"
},
"thoughtSignature": "..."
}],
"role": "model"
}, {
"parts": [{
"functionResponse": {
"name": "getWeather",
"response": {
"response": "Very cold. 22 degrees Fahrenheit."
},
"id": "m4q8z1v6"
}
}],
"role": "user"
}],
"tools": [{
"functionDeclarations": [{
"name": "getWeather"
}]
}, {
"googleSearch": {
}
}, {
"codeExecution": {
}
}],
"toolConfig": {
"includeServerSideToolInvocations": true
}
}
אסימונים ותמחור
שימו לב: חלקי toolCall ו-toolResponse בבקשות נספרים במסגרת prompt_token_count. השלבים האלה של כלי הביניים גלויים לכם עכשיו ומוחזרים לכם, ולכן הם חלק מהיסטוריית השיחה. זה קורה רק בבקשות, ולא בתגובות.
הכלי 'חיפוש Google' הוא חריג לכלל הזה. חיפוש Google כבר מחיל מודל תמחור משלו ברמת השאילתה, כך שלא מתבצע חיוב כפול על טוקנים (אפשר לעיין בדף תמחור).
מידע נוסף זמין בדף אסימונים.
מגבלות
- ברירת המחדל היא מצב
VALIDATED(מצבAUTOלא אפשרי) כשהדגלinclude_server_side_tool_invocationsמופעל - כלים מובנים כמו
google_searchמסתמכים על מידע לגבי המיקום והשעה הנוכחית, ולכן אם יש סתירה במידע לגבי המיקום והשעה ב-system_instructionאו ב-function_declaration.description, יכול להיות שהתכונה של שילוב כלים לא תפעל בצורה טובה.
כלים נתמכים
ההפצה הרגילה של הקשר של הכלי חלה על כלים בצד השרת (מוכללים). הכלי Code Execution הוא גם כלי בצד השרת, אבל יש לו פתרון מובנה משלו להעברת הקשר. השימוש במחשב והפעלת פונקציות הם כלים בצד הלקוח, ויש להם גם פתרונות מובנים להעברת הקשר.
| כלי | צד הביצוע | תמיכה בהעברת הקשר |
|---|---|---|
| חיפוש Google | בצד השרת | נתמך |
| מפות Google | בצד השרת | נתמך |
| הקשר של כתובת ה-URL | בצד השרת | נתמך |
| חיפוש קבצים | בצד השרת | נתמך |
| הרצת קוד | בצד השרת | נתמך (מובנה, משתמש בחלקים executableCode ו-codeExecutionResult) |
| שימוש במחשב | בצד הלקוח | נתמך (מובנה, משתמש בחלקים functionCall ו-functionResponse) |
| פונקציות מותאמות אישית | בצד הלקוח | נתמך (מובנה, משתמש בחלקים functionCall ו-functionResponse) |
המאמרים הבאים
- מידע נוסף על בקשות להפעלת פונקציות ב-Gemini API
- כדאי לעיין ברשימת הכלים הנתמכים: