Gemini cho phép kết hợp các công cụ tích hợp, chẳng hạn như google_search và lệnh gọi hàm (còn gọi là công cụ tuỳ chỉnh) trong một lần tạo bằng cách duy trì và hiển thị nhật ký ngữ cảnh của các lệnh gọi công cụ. Các tổ hợp công cụ tích hợp và tuỳ chỉnh cho phép các quy trình làm việc phức tạp, dựa trên tác nhân, trong đó, chẳng hạn như mô hình có thể tự căn cứ vào dữ liệu web theo thời gian thực trước khi gọi logic kinh doanh cụ thể của bạn.
Dưới đây là ví dụ cho phép kết hợp các công cụ tích hợp và tuỳ chỉnh bằng google_search và hàm tuỳ chỉnh 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
}
}'
Cách hoạt động
Các mô hình Gemini 3 sử dụng vòng tuần hoàn ngữ cảnh công cụ để cho phép kết hợp các công cụ tuỳ chỉnh và công cụ tích hợp. Tính năng lưu thông ngữ cảnh công cụ giúp duy trì và hiển thị ngữ cảnh của các công cụ tích hợp, đồng thời chia sẻ ngữ cảnh đó với các công cụ tuỳ chỉnh trong cùng một lệnh gọi từ lượt này sang lượt khác.
Bật tính năng kết hợp công cụ
- Bạn phải đặt cờ
include_server_side_tool_invocationsthànhtrueđể bật tính năng lưu chuyển ngữ cảnh công cụ. - Bao gồm
function_declarations, cùng với các công cụ tích hợp mà bạn muốn sử dụng, để kích hoạt hành vi kết hợp.- Nếu bạn không thêm
function_declarations, hoạt động lưu thông bối cảnh công cụ vẫn sẽ tác động đến các công cụ tích hợp sẵn được thêm, miễn là bạn đặt cờ này.
- Nếu bạn không thêm
API trả về các phần
Trong một phản hồi duy nhất, API sẽ trả về các phần toolCall và toolResponse cho lệnh gọi công cụ tích hợp. Đối với lệnh gọi hàm (công cụ tuỳ chỉnh), API sẽ trả về phần lệnh gọi functionCall, mà người dùng cung cấp phần functionResponse trong lượt tiếp theo.
toolCallvàtoolResponse: API trả về những phần này để duy trì ngữ cảnh về những công cụ được chạy ở phía máy chủ và kết quả thực thi của chúng cho lượt tiếp theo.functionCallvàfunctionResponse: API gửi lệnh gọi hàm đến người dùng để điền thông tin và người dùng gửi kết quả trở lại trong phản hồi hàm (những phần này là tiêu chuẩn đối với tất cả lệnh gọi hàm trong Gemini API, không chỉ dành riêng cho tính năng kết hợp công cụ).- (Chỉ công cụ Thực thi mã)
executableCodevàcodeExecutionResult: Khi sử dụng công cụ Thực thi mã, thay vìfunctionCallvàfunctionResponse, API sẽ trả vềexecutableCode(mã do mô hình tạo ra nhằm mục đích thực thi) vàcodeExecutionResult(kết quả của mã thực thi).
Bạn phải trả về tất cả các phần, bao gồm cả tất cả các trường mà chúng chứa, cho mô hình ở mỗi lượt để duy trì ngữ cảnh và cho phép kết hợp các công cụ.
Các trường quan trọng trong các phần được trả về
Một số phần do API trả về sẽ bao gồm các trường id, tool_type và thought_signature. Những trường này rất quan trọng để duy trì ngữ cảnh của công cụ (do đó, rất quan trọng đối với việc kết hợp các công cụ); bạn cần trả về tất cả các phần như được cung cấp trong phản hồi trong các yêu cầu tiếp theo.
id: Giá trị nhận dạng duy nhất liên kết một lệnh gọi với phản hồi của lệnh gọi đó.idđược đặt trên tất cả các phản hồi lệnh gọi hàm, bất kể hoạt động lưu thông ngữ cảnh công cụ. Bạn phải cung cấp cùng mộtidtrong phản hồi của hàm mà API cung cấp trong lệnh gọi hàm. Các công cụ tích hợp sẽ tự động chia sẻidgiữa lệnh gọi công cụ và phản hồi công cụ.- Có trong tất cả các phần liên quan đến công cụ:
toolCall,toolResponse,functionCall,functionResponse,executableCode,codeExecutionResult
- Có trong tất cả các phần liên quan đến công cụ:
tool_type: Xác định công cụ cụ thể đang được sử dụng; công cụ hoặc tên hàm (ví dụ:getWeather) hoặc công cụ (ví dụ:URL_CONTEXT) theo nghĩa đen được tích hợp sẵn.- Có trong phần
toolCallvàtoolResponse.
- Có trong phần
thought_signature: Nội dung thực tế đã mã hoá được nhúng trong mỗi phần do API trả về. Không thể tái tạo ngữ cảnh nếu không có chữ ký tư duy; nếu bạn không trả về chữ ký tư duy cho tất cả các phần trong mỗi lượt, mô hình sẽ gặp lỗi.- Có ở tất cả các bộ phận.
Dữ liệu dành riêng cho công cụ
Một số công cụ tích hợp trả về các đối số dữ liệu mà người dùng có thể thấy, dành riêng cho loại công cụ.
| Công cụ | Đối số gọi công cụ mà người dùng nhìn thấy (nếu có) | Phản hồi của công cụ mà người dùng nhìn thấy (nếu có) |
|---|---|---|
| GOOGLE_SEARCH | queries |
search_suggestions |
| GOOGLE_MAPS | queries |
placesgoogle_maps_widget_context_token |
| URL_CONTEXT | urlsURL cần duyệt xem |
urls_metadataretrieved_url: URL được duyệt quaurl_retrieval_status: Trạng thái duyệt qua |
| FILE_SEARCH | Không có | Không có |
Ví dụ về cấu trúc yêu cầu kết hợp công cụ
Cấu trúc yêu cầu sau đây cho thấy cấu trúc yêu cầu của câu lệnh: "Thành phố nào ở cực bắc của Hoa Kỳ? Thời tiết ở đó hôm nay thế nào?". Tiện ích này kết hợp 3 công cụ: các công cụ tích hợp của Gemini google_search và code_execution, cùng một hàm tuỳ chỉnh 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
}
}
Mã thông báo và giá
Xin lưu ý rằng các phần toolCall và toolResponse trong yêu cầu được tính vào prompt_token_count. Vì các bước công cụ trung gian này hiện có thể nhìn thấy và được trả về cho bạn, nên chúng là một phần của nhật ký trò chuyện. Đây chỉ là trường hợp đối với yêu cầu, chứ không phải phản hồi.
Công cụ Google Tìm kiếm là một trường hợp ngoại lệ đối với quy tắc này. Google Tìm kiếm đã áp dụng mô hình định giá riêng ở cấp truy vấn, vì vậy, các mã thông báo sẽ không bị tính phí gấp đôi (xem trang Định giá).
Hãy đọc trang Mã thông báo để biết thêm thông tin.
Các điểm hạn chế
- Chuyển về chế độ
VALIDATEDtheo mặc định (chế độAUTOkhông được hỗ trợ) khi cờinclude_server_side_tool_invocationsđược bật - Các công cụ tích hợp như
google_searchdựa vào thông tin về vị trí và thời gian hiện tại. Vì vậy, nếusystem_instructionhoặcfunction_declaration.descriptioncủa bạn có thông tin về vị trí và thời gian mâu thuẫn với nhau, thì tính năng kết hợp công cụ có thể hoạt động không hiệu quả.
Các công cụ được hỗ trợ
Hoạt động lưu thông bối cảnh công cụ tiêu chuẩn áp dụng cho các công cụ phía máy chủ (được tích hợp sẵn). Thực thi mã cũng là một công cụ phía máy chủ, nhưng có giải pháp tích hợp riêng để lưu hành bối cảnh. Computer Use và function calling là các công cụ phía máy khách, đồng thời có các giải pháp tích hợp để lưu thông ngữ cảnh.
| Công cụ | Bên thực thi | Hỗ trợ lưu thông theo bối cảnh |
|---|---|---|
| Google Tìm kiếm | Phía máy chủ | Được hỗ trợ |
| Google Maps | Phía máy chủ | Được hỗ trợ |
| Bối cảnh URL | Phía máy chủ | Được hỗ trợ |
| Tìm kiếm tệp | Phía máy chủ | Được hỗ trợ |
| Thực thi mã | Phía máy chủ | Được hỗ trợ (tích hợp sẵn, sử dụng các phần executableCode và codeExecutionResult) |
| Sử dụng máy tính | Phía máy khách | Được hỗ trợ (tích hợp sẵn, sử dụng các phần functionCall và functionResponse) |
| Hàm tuỳ chỉnh | Phía máy khách | Được hỗ trợ (tích hợp sẵn, sử dụng các phần functionCall và functionResponse) |
Bước tiếp theo
- Tìm hiểu thêm về tính năng Gọi hàm trong Gemini API.
- Khám phá các công cụ được hỗ trợ: