يتيح 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)
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 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();
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.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، سيستمر تداول سياق الأداة في الأدوات المضمّنة، طالما تم ضبط العلامة.
- في حال عدم تضمين
الأجزاء التي تعرضها واجهة برمجة التطبيقات
في ردّ واحد، تعرض واجهة برمجة التطبيقات الجزءَين toolCall وtoolResponse
لطلب الأداة المضمّنة. بالنسبة إلى طلب البيانات من الوظيفة (الأداة المخصّصة)، تعرض واجهة برمجة التطبيقات جزء طلب البيانات functionCall، والذي يقدّم المستخدم جزء functionResponse الخاص به في الجولة التالية.
-
toolCallوtoolResponse: تعرض واجهة برمجة التطبيقات هذين الجزأين للحفاظ على سياق الأدوات التي يتم تشغيلها من جهة الخادم ونتيجة تنفيذها في الجولة التالية. -
functionCallوfunctionResponse: ترسل واجهة برمجة التطبيقات استدعاء الدالة إلى المستخدم لملئه، ويرسل المستخدم النتيجة في استجابة الدالة (هذه الأجزاء عادية لجميع استدعاءات الدوال في Gemini API، وليست فريدة لميزة دمج الأدوات). - (أداة تنفيذ الرموز البرمجية فقط)
executableCodeوcodeExecutionResult: عند استخدام أداة تنفيذ الرموز البرمجية، بدلاً منfunctionCallوfunctionResponse، تعرض واجهة برمجة التطبيقاتexecutableCode(الرمز البرمجي الذي أنشأه النموذج والمطلوب تنفيذه) وcodeExecutionResult(نتيجة الرمز البرمجي القابل للتنفيذ).
يجب إعادة جميع الأجزاء، بما في ذلك جميع الحقول التي تحتوي عليها، إلى النموذج في كل دورة للحفاظ على السياق وتفعيل مجموعات الأدوات.
الحقول المهمة في الأجزاء التي تم إرجاعها
ستتضمّن بعض الأجزاء التي تعرضها واجهة برمجة التطبيقات الحقول id وtool_type وthought_signature. هذه الحقول ضرورية للحفاظ على سياق الأداة (وبالتالي ضرورية لمجموعات الأدوات)، لذا عليك عرض جميع الأجزاء كما هي في الردّ في طلباتك اللاحقة.
-
id: معرّف فريد يربط طلبًا باستجابته يتم ضبطidعلى جميع ردود استدعاء الدوال، بغض النظر عن تداول سياق الأداة. يجب تقديمidنفسه في ردّ الدالة الذي توفّره واجهة برمجة التطبيقات في استدعاء الدالة. تشارك الأدوات المضمّنة تلقائيًاidبين طلب الأداة وردّ الأداة.- تم العثور على هذه الميزة في جميع الأجزاء المتعلّقة بالأدوات:
toolCallوtoolResponseوfunctionCallوfunctionResponseوexecutableCodeوcodeExecutionResult
- تم العثور على هذه الميزة في جميع الأجزاء المتعلّقة بالأدوات:
tool_type: تحدّد الأداة المحدّدة المستخدَمة، أي الأداة الحرفية المضمّنة أو (مثلURL_CONTEXT) أو اسم الدالة (مثلgetWeather).- تم العثور عليه في
toolCallوtoolResponseجزءًا.
- تم العثور عليه في
-
thought_signature: السياق المشفّر الفعلي المضمّن في كل جزء تعرضه واجهة برمجة التطبيقات لا يمكن إعادة إنشاء السياق بدون توقيعات الأفكار، وإذا لم يتم عرض توقيعات الأفكار لجميع الأجزاء في كل دور، سيظهر خطأ في النموذج.- تم العثور على هذا النص في جميع الأجزاء.
البيانات الخاصة بالأداة
تعرض بعض الأدوات المضمّنة وسيطات البيانات المرئية للمستخدمين الخاصة بنوع الأداة.
| الأداة | وسيطات طلب استخدام الأداة المرئية للمستخدم (إن وُجدت) | ردّ الأداة المرئي للمستخدم (إن وُجد) |
|---|---|---|
| GOOGLE_SEARCH | queries |
search_suggestions |
| GOOGLE_MAPS | queries |
placesgoogle_maps_widget_context_token |
| URL_CONTEXT | urlsعناوين URL التي سيتم تصفّحها |
url_metadataretrieved_url: عناوين URL التي تم تصفّحهاurl_retrieval_status: حالة التصفّح |
| FILE_SEARCH | بدون | بدون |
مثال على بنية طلب مجموعة أدوات
تعرض بنية الطلب التالية بنية الطلب: "ما هي المدينة الواقعة في أقصى شمال الولايات المتحدة؟ ما هي حالة الطقس هناك اليوم؟" تجمع هذه الإضافة بين ثلاث أدوات: أدوات 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" حاليًا نموذج التسعير الخاص به على مستوى طلب البحث، لذا لا يتم تحصيل رسوم الرموز المميّزة مرّتين (راجِع صفحة الأسعار).
يمكنك الاطّلاع على صفحة الرموز المميزة للحصول على مزيد من المعلومات.
القيود
- يتم ضبط الوضع التلقائي على
VALIDATED(الوضعAUTOغير متاح) عند تفعيل العلامةinclude_server_side_tool_invocations - تعتمد الأدوات المضمّنة، مثل
google_search، على معلومات الموقع الجغرافي والوقت الحالي، لذا إذا كانsystem_instructionأوfunction_declaration.descriptionيتضمّن معلومات متضاربة حول الموقع الجغرافي والوقت، قد لا تعمل ميزة دمج الأدوات بشكل جيد.
الأدوات المتوافقة
يتم تطبيق تداول سياق الأداة العادي على الأدوات من جهة الخادم (المضمّنة). "تنفيذ التعليمات البرمجية" هي أيضًا أداة من جهة الخادم، ولكنّها تتضمّن حلاً مدمجًا خاصًا بها لتداول السياق. أداتا "استخدام الكمبيوتر" و"استدعاء الدوال" هما أداتان من جهة العميل، وتتضمّنان أيضًا حلولاً مدمجة لتداول السياق.
| الأداة | جهة التنفيذ | دعم تداول السياق |
|---|---|---|
| بحث Google | من جهة الخادم | متاح |
| خرائط Google | من جهة الخادم | متاح |
| سياق عنوان URL | من جهة الخادم | متاح |
| البحث عن الملفات | من جهة الخادم | متاح |
| تنفيذ الرموز البرمجية | من جهة الخادم | متوافقة (مدمجة، وتستخدم أجزاء executableCode وcodeExecutionResult) |
| استخدام الكمبيوتر | من جهة العميل | متوافق (مضمّن، يستخدم الأجزاء functionCall وfunctionResponse) |
| الدوال المخصّصة | من جهة العميل | متوافق (مضمّن، يستخدم الأجزاء functionCall وfunctionResponse) |
الخطوات التالية
- مزيد من المعلومات حول ميزة "استدعاء الدوال" في Gemini API
- استكشاف الأدوات المتوافقة: