Gemini umożliwia łączenie narzędzi wbudowanych, takich
jak google_search, i wywoływania funkcji
(znanych też jako narzędzia niestandardowe) w ramach jednej generacji poprzez zachowanie i udostępnienie
historii kontekstu wywołań narzędzi. Kombinacje narzędzi wbudowanych i niestandardowych umożliwiają tworzenie złożonych przepływów pracy, w których np. model może opierać się na danych internetowych w czasie rzeczywistym przed wywołaniem konkretnej logiki biznesowej.
Oto przykład, który umożliwia łączenie narzędzi wbudowanych i niestandardowych za pomocą google_search i funkcji niestandardowej 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
}
}'
Jak to działa
Modele Gemini 3 używają cyrkulacji kontekstu narzędzia, aby umożliwić łączenie narzędzi wbudowanych i niestandardowych. Cyrkulacja kontekstu narzędzia umożliwia zachowanie i udostępnienie kontekstu narzędzi wbudowanych oraz udostępnienie go narzędziom niestandardowym w ramach tego samego wywołania.
Włączanie łączenia narzędzi
- Aby włączyć cyrkulację kontekstu narzędzia, musisz ustawić flagę
include_server_side_tool_invocationsnatrue. - Aby wywołać zachowanie kombinacji, dołącz
function_declarationswraz z narzędziami wbudowanymi, których chcesz użyć.- Jeśli nie uwzględnisz
function_declarations, cyrkulacja kontekstu narzędzia nadal będzie działać na uwzględnionych narzędziach wbudowanych, o ile flaga jest ustawiona.
- Jeśli nie uwzględnisz
Części zwracane przez interfejs API
W ramach jednej odpowiedzi interfejs API zwraca części toolCall i toolResponse dla wywołania narzędzia wbudowanego. W przypadku wywołania funkcji (narzędzia niestandardowego) interfejs API zwraca część wywołania functionCall, do której użytkownik w następnej kolejce dostarcza część functionResponse.
toolCallitoolResponse: interfejs API zwraca te części, aby zachować kontekst narzędzi uruchamianych po stronie serwera oraz wynik ich wykonania na potrzeby następnej kolejki.functionCallifunctionResponse: interfejs API wysyła wywołanie funkcji do użytkownika, aby go wypełnił, a użytkownik odsyła wynik w odpowiedzi funkcji (te części są standardowe dla wszystkich wywołań funkcji w interfejsie Gemini API, a nie tylko dla funkcji łączenia narzędzi).- (Narzędzie do wykonywania kodu tylko)
executableCodeicodeExecutionResult: Gdy używasz narzędzia do wykonywania kodu, zamiastfunctionCallifunctionResponse, interfejs API zwracaexecutableCode(kod wygenerowany przez model, który ma zostać wykonany) icodeExecutionResult(wynik wykonania kodu).
Aby zachować kontekst i umożliwić łączenie narzędzi , musisz w każdej kolejce zwracać do modelu wszystkie części, w tym wszystkie pola, które zawierają.
Krytyczne pola w zwracanych częściach
Niektóre części zwracane przez interfejs API będą zawierać pola id,
tool_type, i thought_signature. Te pola są niezbędne do zachowania kontekstu narzędzia (a tym samym do łączenia narzędzi). W kolejnych żądaniach musisz zwracać wszystkie części tak, jak są one podane w odpowiedzi.
id: unikalny identyfikator, który mapuje wywołanie na jego odpowiedź.idjest ustawiany we wszystkich odpowiedziach na wywołanie funkcji, niezależnie od cyrkulacji kontekstu narzędzia. W odpowiedzi funkcji musisz podać to samoid, które interfejs API podaje w wywołaniu funkcji. Narzędzia wbudowane automatycznie udostępniająidmiędzy wywołaniem narzędzia a odpowiedzią narzędzia.- Znajduje się we wszystkich częściach związanych z narzędziami:
toolCall,toolResponse,functionCall,functionResponse,executableCode,codeExecutionResult.
- Znajduje się we wszystkich częściach związanych z narzędziami:
tool_type: identyfikuje konkretne używane narzędzie; literał narzędzia wbudowanego lub (np.URL_CONTEXT) lub nazwa funkcji (np.getWeather).- Znajduje się w częściach
toolCallitoolResponse.
- Znajduje się w częściach
thought_signature: rzeczywisty zaszyfrowany kontekst osadzony w każdej części zwracanej przez interfejs API. Nie można odtworzyć kontekstu bez sygnatur myśli. Jeśli w każdej kolejce nie zwrócisz sygnatur myśli dla wszystkich części, model zwróci błąd.- Znajduje się we wszystkich częściach.
Dane specyficzne dla narzędzia
Niektóre narzędzia wbudowane zwracają argumenty danych widoczne dla użytkownika, które są specyficzne dla typu narzędzia.
| Narzędzie | Argumenty wywołania narzędzia widoczne dla użytkownika (jeśli występują) | Odpowiedź narzędzia widoczna dla użytkownika (jeśli występuje) |
|---|---|---|
| GOOGLE_SEARCH | queries |
search_suggestions |
| GOOGLE_MAPS | queries |
placesgoogle_maps_widget_context_token |
| URL_CONTEXT | urlsAdresy URL do przeglądania |
urls_metadataretrieved_url: przeglądane adresy URLurl_retrieval_status: stan przeglądania |
| FILE_SEARCH | Brak | Brak |
Przykładowa struktura żądania łączenia narzędzi
Poniższa struktura żądania pokazuje strukturę żądania prompta: „Jakie jest najbardziej wysunięte na północ miasto w Stanach Zjednoczonych? Jaka jest tam dzisiaj pogoda?”. Łączy 3 narzędzia: wbudowane narzędzia Gemini google_search i code_execution oraz funkcję niestandardową 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
}
}
Tokeny i ceny
Pamiętaj, że części toolCall i toolResponse w żądaniach są wliczane do prompt_token_count. Ponieważ te pośrednie kroki narzędzia są teraz widoczne i zwracane, stanowią one część historii rozmowy. Dotyczy to tylko
przypadku żądań, a nie odpowiedzi.
Wyjątkiem od tej reguły jest narzędzie Wyszukiwarka Google. Wyszukiwarka Google stosuje już własny model cenowy na poziomie zapytania, więc tokeny nie są naliczane podwójnie (patrz strona Ceny).
Więcej informacji znajdziesz na stronie Tokeny.
Ograniczenia
- Gdy włączona jest flaga
include_server_side_tool_invocations, domyślnie używany jest trybVALIDATED(AUTOnie jest obsługiwany). - Narzędzia wbudowane, takie jak
google_search, korzystają z informacji o lokalizacji i aktualnej godzinie. Jeśli więcsystem_instructionlubfunction_declaration.descriptionzawierają sprzeczne informacje o lokalizacji i czasie, funkcja łączenia narzędzi może nie działać prawidłowo.
Obsługiwane narzędzia
Standardowa cyrkulacja kontekstu narzędzia dotyczy narzędzi po stronie serwera (wbudowanych). Wykonywanie kodu to też narzędzie po stronie serwera, ale ma własne wbudowane rozwiązanie do cyrkulacji kontekstu. Korzystanie z komputera i wywoływanie funkcji to narzędzia po stronie klienta, które też mają wbudowane rozwiązania do cyrkulacji kontekstu.
| Narzędzie | Strona wykonania | Obsługa cyrkulacji kontekstu |
|---|---|---|
| Wyszukiwarka Google | Po stronie serwera | Obsługiwane |
| Mapy Google | Po stronie serwera | Obsługiwane |
| Kontekst adresu URL | Po stronie serwera | Obsługiwane |
| Wyszukiwanie plików | Po stronie serwera | Obsługiwane |
| Wykonywanie kodu | Po stronie serwera | Obsługiwane (wbudowane, używa części executableCode i codeExecutionResult) |
| Korzystanie z komputera | Po stronie klienta | Obsługiwane (wbudowane, używa części functionCall i functionResponse) |
| Funkcje niestandardowe | Po stronie klienta | Obsługiwane (wbudowane, używa części functionCall i functionResponse) |
Co dalej?
- Dowiedz się więcej o wywoływaniu funkcji w interfejsie Gemini API.
- Poznaj obsługiwane narzędzia: