Gemini cho phép kết hợp các công cụ tích hợp, chẳng
hạn 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 giữ nguyên và hiển thị
nhật ký ngữ cảnh của các lệnh gọi công cụ. Các kiểu kết hợp công cụ tích hợp và tuỳ chỉnh cho phép các quy trình công việc phức tạp, có tính đại diện, trong đó, ví dụ: mô hình có thể dựa 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.
Sau đây là ví dụ về cách bật các kiểu kết hợp 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.5-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.5-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 model = client.getGenerativeModel({
model: "gemini-3.5-flash",
});
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.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.5-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.5-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.5-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
}
}'
Cách hoạt động
Các mô hình Gemini 3 sử dụng lưu thông ngữ cảnh công cụ để bật các kiểu kết hợp công cụ tích hợp và tuỳ chỉnh. Lưu thông ngữ cảnh công cụ giúp giữ nguyên 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 thông ngữ cảnh công cụ. - Đưa
function_declarationsvào 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 đưa
function_declarationsvào, tính năng lưu thông ngữ cảnh công cụ vẫn sẽ hoạt động trên các công cụ tích hợp được đưa vào, miễn là bạn đã đặt cờ.
- Nếu bạn không đưa
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ề các phần này để giữ nguyên ngữ cảnh của các công cụ được chạy ở phía máy chủ và kết quả thực thi của các công cụ đó cho lượt tiếp theo.functionCallvàfunctionResponse: API gửi lệnh gọi hàm cho 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 (các phần này là tiêu chuẩn cho 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 để 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à các phần đó chứa, cho mô hình trong mỗi lượt để duy trì ngữ cảnh và bật tính năng kết hợp 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. Các trường này rất quan trọng để duy trì ngữ cảnh công cụ (và do đó, rất quan trọng đối với các kiểu kết hợp công cụ); bạn cần trả về tất cả các phần như 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 ánh xạ một lệnh gọi đến 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ể tính nă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 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ụ tích hợp theo nghĩa đen hoặc tên hàm (ví dụ:URL_CONTEXT) hoặc hàm (ví dụ:getWeather).- Có trong các phần
toolCallvàtoolResponse.
- Có trong các phần
thought_signature: Ngữ cảnh được mã hoá thực tế đượ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ưởng; nếu bạn không trả về chữ ký ý tưởng cho tất cả các phần trong mỗi lượt, mô hình sẽ báo lỗi.- Có trong tất cả các 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ố lệnh gọi công cụ mà người dùng có thể thấy (nếu có) | Phản hồi công cụ mà người dùng có thể 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 |
urls_metadataretrieved_url: URL đã duyệturl_retrieval_status: Trạng thái duyệt |
| FILE_SEARCH | Không có | Không có |
Cấu trúc yêu cầu kết hợp công cụ mẫu
Cấu trúc yêu cầu sau đây cho thấy cấu trúc yêu cầu của lời nhắc: "Thành phố cực bắc ở Hoa Kỳ là gì? Thời tiết ở đó hôm nay như thế nào?". Cấu trúc này kết hợp 3 công cụ: các công cụ Gemini tích hợp google_search và code_execution, cùng với hàm tuỳ chỉnh get_weather.
{
"model": "models/gemini-3.5-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
}
}
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ể thấy và được trả về cho bạn, nên chúng là một phần của nhật ký cuộc trò chuyện. Điều này chỉ áp dụng cho yêu cầu, không áp dụng cho 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 giá riêng ở cấp truy vấn, vì vậy, mã thông báo không bị tính phí gấp đôi (xem trang Giá).
Đọc trang Mã thông báo để biết thêm thông tin.
Các điểm hạn chế
- Mặc định ở chế độ
VALIDATED(AUTOkhông được hỗ trợ) khi bật cờinclude_server_side_tool_invocations - 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ó thông tin về vị trí và thời gian xung đột, 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ợ
Tính năng lưu thông ngữ cảnh công cụ tiêu chuẩn áp dụng cho các công cụ phía máy chủ (tích hợp). 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 cho tính năng lưu thông ngữ cảnh. Sử dụng máy tính và lệnh gọi hàm là các công cụ phía máy khách, đồng thời cũng có các giải pháp tích hợp cho tính năng lưu thông ngữ cảnh.
| Công cụ | Phía thực thi | Hỗ trợ lưu thông ngữ 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ợ |
| Ngữ 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ử 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ử 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ử dụng các phần functionCall và functionResponse) |
Bước tiếp theo
- Tìm hiểu thêm về Lệnh gọi hàm trong Gemini API.
- Khám phá các công cụ được hỗ trợ: