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.8-flash",
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.GoogleSearch(), # Built-in tool
function_declarations=[getWeather], # Custom tool
),
],
tool_config=types.ToolConfig(
include_server_side_tool_invocations=True
)
),
)
function_call_id = None
for part in response.candidates[0].content.parts:
if part.function_call:
print(f"Function call: {part.function_call.name} (ID: {part.function_call.id})")
function_call_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=function_call_id # Match the ID from the function_call
)
)]
)
]
response_2 = client.models.generate_content(
model="gemini-3.8-flash",
contents=history,
config=types.GenerateContentConfig(
tools=[
types.Tool(
google_search=types.GoogleSearch(),
function_declarations=[getWeather]
),
],
# This flag needs to be enabled for built-in tool context circulation and tool combination
tool_config=types.ToolConfig(
include_server_side_tool_invocations=True
)
),
)
for part in response_2.candidates[0].content.parts:
if part.text:
print(part.text)
جاوا اسکریپت
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 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 response1 = await client.models.generateContent({
model: "gemini-3.8-flash",
contents: [{role: "user", parts: [{text: "What is the northernmost city in the United States? What's the weather like there today?"}]}],
config: {
tools: tools,
toolConfig: toolConfig,
},
});
for (const part of response1.candidates[0].content.parts) {
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 response2 = await client.models.generateContent({
model: "gemini-3.8-flash",
contents: history,
config: {
tools: tools,
toolConfig: toolConfig,
},
});
for (const part of response2.candidates[0].content.parts) {
if (part.text) {
console.log(part.text);
}
}
}
run();
رفتن
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.8-flash")
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
}
}
}
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.8-flash: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.8-flash: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 بخشهای toolCall و toolResponse
را برای فراخوانی ابزار داخلی برمیگرداند. برای تماس تابع (ابزار سفارشی)، API بخش تماس functionCall را برمیگرداند که کاربر در نوبت بعدی بخش functionResponse را ارائه میکند.
-
toolCallوtoolResponse: این API این بخشها را برمیگرداند تا زمینه ابزارهایی که در سمت سرور اجرا میشوند و نتیجه اجرای آنها برای نوبت بعدی حفظ شود. functionCallوfunctionResponse: API فراخوانی تابع را برای کاربر ارسال میکند تا آن را تکمیل کند، و کاربر نتیجه را در پاسخ تابع برمیگرداند (این بخشها برای همه فراخوانی تابع در Gemini API استاندارد است و مختص ویژگی ترکیب ابزار نیست).- (فقط ابزار اجرای کد)
executableCodeوcodeExecutionResult: هنگام استفاده از ابزار «اجرای کد»، بهجایfunctionCallوfunctionResponse، این APIexecutableCode(کد تولیدشده توسط مدلی که قرار است اجرا شود) وcodeExecutionResult(نتیجه کد اجرایی) را برمیگرداند.
باید همه بخشها، ازجمله همه فیلدهایی که دربردارند، را در هر نوبت به مدل برگردانید تا بافت حفظ شود و ترکیب ابزارها امکانپذیر شود.
فیلدهای مهم در بخشهای برگشتی
بخشهای خاصی که توسط API برگردانده میشوند شامل id،
tool_type، و thought_signature فیلد خواهند بود. این فیلدها برای حفظ بافتار ابزار بسیار مهم هستند (و بنابراین برای ترکیب ابزارها بسیار مهم هستند)؛ باید همه بخشها را همانطور که در پاسخ داده شده است در درخواستهای بعدیتان برگردانید.
id: شناسه یکتایی که تماس را به پاسخ آن نگاشت میکند.idدر همه پاسخهای فراخوانی تابع تنظیم شده است، صرفنظر از گردش زمینه ابزار. باید همانidرا که میانای برنامهسازی کاربردی در فراخوانی تابع ارائه میدهد در پاسخ تابع ارائه دهید. ابزارهای داخلی بهطور خودکارidرا بین فراخوانی ابزار و پاسخ ابزار همرسانی میکنند.- در همه بخشهای مربوط به ابزار پیدا شد:
toolCall،toolResponse،functionCall،functionResponse،executableCode،codeExecutionResult
- در همه بخشهای مربوط به ابزار پیدا شد:
tool_type: ابزار خاصی را که استفاده میشود شناسایی میکند؛ ابزار داخلی حرفی یا (مثلاًURL_CONTEXT) یا نام تابع (مثلاًgetWeather).- در
toolCallوtoolResponseبخش پیدا شد.
- در
thought_signature: زمینه رمزگذاریشده واقعی که در هر بخش برگشتی ازسوی API جاسازی شده است. بدون امضاهای فکری نمیتوان بافت را بازسازی کرد؛ اگر امضاهای فکری را برای همه بخشها در هر نوبت برنگردانید، مدل خطا خواهد داد.- در همه بخشها پیدا شد.
دادههای مختص ابزار
برخیاز ابزارهای داخلی آرگومانهای داده قابلمشاهده برای کاربر را که مختص نوع ابزار است برمیگردانند.
| ابزار | آرگومانهای فراخوانی ابزار قابلمشاهده کاربر (درصورت وجود) | پاسخ ابزار نمایان برای کاربر (درصورت وجود) |
|---|---|---|
| GOOGLE_SEARCH | queries |
search_suggestions |
| GOOGLE_MAPS | queries |
placesgoogle_maps_widget_context_token |
| URL_CONTEXT | urlsنشانی وب برای مرور شدن |
url_metadataretrieved_url: نشانیهای وب مرور شدurl_retrieval_status: وضعیت مرور |
| FILE_SEARCH | خالی | خالی |
ساختار درخواست ترکیب ابزار نمونه
ساختار درخواست زیر ساختار درخواست پیامواره را نشان میدهد: «What
is the northernmost city in the United States?» (شمالیترین شهر ایالات متحده کدام است؟) امروز هوا در آنجا چطور است؟». این مهارت سه ابزار را ترکیب میکند: ابزارهای داخلی Gemini google_search
و code_execution، و یک تابع سفارشی get_weather.
{
"model": "models/gemini-3.8-flash",
"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» ازقبل مدل قیمتگذاری خود را در سطح پُرسمان اعمال میکند، بنابراین هزینه توکنها دوبرابر نمیشود (صفحه قیمتگذاری را ببینید).
برای اطلاعات بیشتر، صفحه نشانها را بخوانید.
محدودیتها
- وقتی پرچم
include_server_side_tool_invocationsفعال باشد، بهطور پیشفرض روی حالتVALIDATEDتنظیم میشود (از حالتAUTOپشتیبانی نمیشود) - ابزارهای داخلی مثل
google_searchبه مکان و زمان فعلی اطلاعات متکی هستند، بنابراین اگرsystem_instructionیاfunction_declaration.descriptionشما اطلاعات مکان و زمان متعارضی داشته باشد، ویژگی ترکیب ابزار ممکن است خوب کار نکند.
ابزارهای پشتیبانیشده
گردش بافتار ابزار استاندارد برای ابزارهای سمت سرور (درونساخت) اعمال میشود. «اجرای کد» نیز ابزاری سمت سرور است، اما راهحل داخلی خود را برای گردش زمینهای دارد. «استفاده از رایانه» و «فراخوانی تابع» ابزارهای سمت مشتری هستند و همچنین راهحلهای داخلی برای گردش زمینهای دارند.
| ابزار | طرف اجرا | پشتیبانی گردش زمینهای |
|---|---|---|
| جستجوی Google | سمت سرور | پشتیبانی میشود |
| Google Maps | سمت سرور | پشتیبانی میشود |
| بافت نشانی وب | سمت سرور | پشتیبانی میشود |
| جستجوی فایل | سمت سرور | پشتیبانی میشود |
| اجرای کد | سمت سرور | پشتیبانی میشود (درونساخت، از قطعات executableCode و codeExecutionResult استفاده میکند) |
| استفاده از رایانه | سمت کارخواه | پشتیبانی میشود (درونساخت، از قطعات functionCall و functionResponse استفاده میکند) |
| توابع سفارشی | سمت کارخواه | پشتیبانی میشود (درونساخت، از قطعات functionCall و functionResponse استفاده میکند) |
قدم بعدی چیست
- درباره فراخوانی تابع در Gemini API بیشتر بدانید.
- ابزارهای پشتیبانیشده را کاوش کنید: