Gemini umożliwia łączenie wbudowanych narzędzi, takich jak google_search, i wywoływanie funkcji (znanych też jako narzędzia niestandardowe) w ramach jednej generacji przez zachowywanie i udostępnianie historii kontekstu wywołań narzędzi. Wbudowane i niestandardowe kombinacje narzędzi umożliwiają tworzenie złożonych przepływów pracy opartych na agentach, 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 korzystanie z wbudowanych i niestandardowych kombinacji narzędzi z użyciem 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 korzystają z kontekstu narzędzia, aby umożliwić wbudowane i niestandardowe kombinacje narzędzi. Dzięki przekazywaniu kontekstu narzędzia można zachować i udostępnić kontekst wbudowanych narzędzi oraz udostępnić go narzędziom niestandardowym w ramach tego samego wywołania.
Włączanie kombinacji narzędzi
- Aby włączyć przekazywanie kontekstu narzędzia, musisz ustawić flagę
include_server_side_tool_invocationsnatrue. - Dołącz
function_declarationsoraz wbudowane narzędzia, których chcesz używać, aby wywołać kombinację działań.- Jeśli nie uwzględnisz
function_declarations, kontekst narzędzia będzie nadal działać w przypadku wbudowanych narzędzi, o ile flaga jest ustawiona.
- Jeśli nie uwzględnisz
Interfejs API zwraca części
W jednej odpowiedzi interfejs API zwraca części toolCall i toolResponse wywołania wbudowanego narzędzia. W przypadku wywołania funkcji (niestandardowego narzędzia) interfejs API zwraca część functionCall wywołania, do której użytkownik w następnej kolejce dodaje część functionResponse.
toolCallitoolResponse: interfejs API zwraca te części, aby zachować kontekst narzędzi uruchamianych po stronie serwera i wynik ich wykonania na potrzeby następnej tury.functionCallifunctionResponse: interfejs API wysyła do użytkownika wywołanie funkcji, aby mógł ją 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).- (Tylko narzędzie Wykonywanie kodu)
executableCodeicodeExecutionResult: Gdy używasz narzędzia Wykonywanie kodu, zamiastfunctionCallifunctionResponseinterfejs API zwracaexecutableCode(kod wygenerowany przez model, który ma zostać wykonany) icodeExecutionResult(wynik wykonania kodu).
W każdej turze musisz zwrócić do modelu wszystkie części, w tym wszystkie pola, które zawierają, aby zachować kontekst i umożliwić kombinacje narzędzi.
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ą kluczowe dla zachowania kontekstu narzędzia (a tym samym dla kombinacji narzędzi). W kolejnych żądaniach musisz zwracać wszystkie części w formie podanej w odpowiedzi.
id: unikalny identyfikator, który przypisuje wywołanie do jego odpowiedzi.idjest ustawiony we wszystkich odpowiedziach na wywołanie funkcji niezależnie od obiegu kontekstu narzędzia. W odpowiedzi funkcji musisz podać ten sam parametrid, który interfejs API podaje w wywołaniu funkcji. Wbudowane narzędzia automatycznie dzieląidmiędzy wywołanie narzędzia a odpowiedź na nie.- Występuje we wszystkich częściach związanych z narzędziami:
toolCall,toolResponse,functionCall,functionResponse,executableCode,codeExecutionResult
- Występuje we wszystkich częściach związanych z narzędziami:
tool_type: określa konkretne używane narzędzie, czyli wbudowane narzędzie (np.URL_CONTEXT) lub funkcję (np.getWeather).- Znaleziono w
toolCallitoolResponse.
- Znaleziono w
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 nie zwrócisz sygnatur myśli dla wszystkich części w każdej turze, model zwróci błąd.- Znaleziono we wszystkich częściach.
Dane dotyczące narzędzia
Niektóre wbudowane narzędzia zwracają argumenty danych widoczne dla użytkownika, które są specyficzne dla danego 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 kombinacji narzędzi
Poniższa struktura żądania pokazuje strukturę żądania prompta: „What
is the northernmost city in the United States? 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 limitu prompt_token_count. Ponieważ te pośrednie kroki narzędzia są teraz widoczne i zwracane do Ciebie, stanowią część historii rozmowy. Dotyczy to tylko żądań, a nie odpowiedzi.
Wyjątkiem od tej reguły jest narzędzie wyszukiwarki Google. Wyszukiwarka Google stosuje już własny model cenowy na poziomie zapytania, więc tokeny nie są naliczane podwójnie (więcej informacji znajdziesz na stronie Ceny).
Więcej informacji znajdziesz na stronie Tokeny.
Ograniczenia
- Domyślnie tryb
VALIDATED(trybAUTOnie jest obsługiwany), gdy włączona jest flagainclude_server_side_tool_invocations - Wbudowane narzędzia, takie jak
google_search, korzystają z informacji o lokalizacji i bieżącym czasie, więc jeślisystem_instructionlubfunction_declaration.descriptionmają sprzeczne informacje o lokalizacji i czasie, funkcja łączenia narzędzi może nie działać prawidłowo.
Obsługiwane narzędzia
W przypadku narzędzi po stronie serwera (wbudowanych) obowiązuje standardowe przekazywanie kontekstu narzędzia. Wykonywanie kodu to również narzędzie po stronie serwera, ale ma własne wbudowane rozwiązanie do przekazywania kontekstu. Korzystanie z komputera i wywoływanie funkcji to narzędzia po stronie klienta, które mają też wbudowane rozwiązania do przekazywania kontekstu.
| Narzędzie | Strona wykonania | Obsługa rozpowszechniania 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, wykorzystuje części executableCode i codeExecutionResult) |
| Korzystanie z komputera | Po stronie klienta | Obsługiwane (wbudowane, wykorzystuje części functionCall i functionResponse) |
| Funkcje niestandardowe | Po stronie klienta | Obsługiwane (wbudowane, wykorzystuje części functionCall i functionResponse) |
Co dalej?
- Dowiedz się więcej o wywoływaniu funkcji w Gemini API.
- Poznaj obsługiwane narzędzia: