Mit Gemini können integrierte Tools wie google_search und Funktionsaufrufe (auch benutzerdefinierte Tools genannt) in einer einzigen Generierung kombiniert werden, indem der Kontextverlauf von Tool-Aufrufen beibehalten und verfügbar gemacht wird. Mit integrierten und benutzerdefinierten Tool-Kombinationen lassen sich komplexe, agentenbasierte Workflows erstellen. Das Modell kann sich beispielsweise auf Echtzeit-Webdaten stützen, bevor es Ihre spezifische Geschäftslogik aufruft.
Hier ist ein Beispiel, in dem integrierte und benutzerdefinierte Toolkombinationen mit google_search und einer benutzerdefinierten Funktion getWeather aktiviert werden:
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();
Ok
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
}
}'
Funktionsweise
Gemini 3-Modelle verwenden Tool-Kontext-Zirkulation, um integrierte und benutzerdefinierte Tool-Kombinationen zu ermöglichen. Durch die Weitergabe des Tool-Kontexts kann der Kontext integrierter Tools beibehalten und verfügbar gemacht werden. Außerdem kann er in demselben Aufruf von Runde zu Runde mit benutzerdefinierten Tools geteilt werden.
Tool-Kombination aktivieren
- Sie müssen das Flag
include_server_side_tool_invocationsauftruesetzen, um die Weitergabe des Tool-Kontexts zu aktivieren. - Fügen Sie
function_declarationszusammen mit den integrierten Tools ein, die Sie verwenden möchten, um das Kombinationsverhalten auszulösen.- Wenn Sie
function_declarationsnicht angeben, wird der Toolkontext trotzdem für die integrierten Tools verwendet, sofern das Flag gesetzt ist.
- Wenn Sie
API gibt Teile zurück
In einer einzigen Antwort gibt die API die Teile toolCall und toolResponse für den integrierten Tool-Aufruf zurück. Für den Funktionsaufruf (benutzerdefiniertes Tool) gibt die API den functionCall-Aufruf zurück, für den der Nutzer im nächsten Schritt den functionResponse-Teil bereitstellt.
toolCallundtoolResponse: Die API gibt diese Teile zurück, um den Kontext beizubehalten, welche Tools serverseitig ausgeführt werden, und das Ergebnis ihrer Ausführung für den nächsten Zug.functionCallundfunctionResponse: Die API sendet den Funktionsaufruf an den Nutzer, damit er ihn ausfüllt. Der Nutzer sendet das Ergebnis in der Funktionsantwort zurück. Diese Teile sind für alle Funktionsaufrufe in der Gemini API Standard und nicht nur für die Funktion zur Kombination von Tools.- (Nur Tool Codeausführung)
executableCodeundcodeExecutionResult: Wenn Sie das Tool „Codeausführung“ verwenden, gibt die API anstelle vonfunctionCallundfunctionResponsedie WerteexecutableCode(der vom Modell generierte Code, der ausgeführt werden soll) undcodeExecutionResult(das Ergebnis des ausführbaren Codes) zurück.
Sie müssen alle Teile, einschließlich aller darin enthaltenen Felder, bei jedem Zug an das Modell zurückgeben, um den Kontext beizubehalten und Toolkombinationen zu ermöglichen.
Wichtige Felder in zurückgegebenen Teilen
Bestimmte von der API zurückgegebene Teile enthalten die Felder id, tool_type und thought_signature. Diese Felder sind wichtig, um den Tool-Kontext beizubehalten (und daher auch für Tool-Kombinationen). Sie müssen alle Teile wie in der Antwort angegeben in Ihren nachfolgenden Anfragen zurückgeben.
id: Eine eindeutige Kennung, die einen Aufruf seiner Antwort zuordnet.idwird für alle Antworten auf Funktionsaufrufe festgelegt, unabhängig von der Weitergabe des Toolkontexts. Sie müssen in der Funktionsantwort dieselbeidangeben, die die API im Funktionsaufruf bereitstellt. Integrierte Tools geben dieidautomatisch zwischen Toolaufruf und Toolantwort weiter.- In allen toolbezogenen Teilen zu finden:
toolCall,toolResponse,functionCall,functionResponse,executableCode,codeExecutionResult
- In allen toolbezogenen Teilen zu finden:
tool_type: Gibt das verwendete Tool an, entweder das integrierte Tool (z.B.URL_CONTEXT) oder den Funktionsnamen (z.B.getWeather).- Gefunden in den Teilen
toolCallundtoolResponse.
- Gefunden in den Teilen
thought_signature: Der tatsächliche verschlüsselte Kontext, der in jedem von der API zurückgegebenen Teil eingebettet ist. Der Kontext kann ohne Gedanken-Signaturen nicht rekonstruiert werden. Wenn Sie die Gedanken-Signaturen für alle Teile in jeder Runde nicht zurückgeben, gibt das Modell einen Fehler aus.- In allen Teilen gefunden.
Tool-spezifische Daten
Einige integrierte Tools geben nutzersichtbare Datenargumente zurück, die für den jeweiligen Tooltyp spezifisch sind.
| Tool | Für Nutzer sichtbare Toolaufrufargumente (falls vorhanden) | Für Nutzer sichtbare Tool-Antwort (falls vorhanden) |
|---|---|---|
| GOOGLE_SEARCH | queries |
search_suggestions |
| GOOGLE_MAPS | queries |
placesgoogle_maps_widget_context_token |
| URL_CONTEXT | urlsURLs, die durchsucht werden sollen |
urls_metadataretrieved_url: Durchsuchte URLsurl_retrieval_status: Durchsuchungsstatus |
| FILE_SEARCH | Keine | Keine |
Beispiel für die Struktur einer Anfrage zur Kombination von Tools
Die folgende Anfragestruktur zeigt die Anfragestruktur des Prompts: „What is the northernmost city in the United States? Wie ist das Wetter dort heute?“. Es kombiniert drei Tools: die integrierten Gemini-Tools google_search und code_execution sowie eine benutzerdefinierte Funktion 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
}
}
Tokens und Preise
Beachten Sie, dass toolCall- und toolResponse-Teile in Anfragen auf prompt_token_count angerechnet werden. Da diese Zwischenschritte des Tools jetzt sichtbar sind und an Sie zurückgegeben werden, sind sie Teil des Unterhaltungsverlaufs. Das ist nur bei Anfragen der Fall, nicht bei Antworten.
Das Google Suche-Tool ist eine Ausnahme von dieser Regel. Die Google Suche wendet bereits ein eigenes Preismodell auf Abfrageebene an. Daher werden Tokens nicht doppelt berechnet (siehe Seite „Preise“).
Weitere Informationen finden Sie auf der Seite Tokens.
Beschränkungen
- Standardmäßig wird der Modus
VALIDATEDverwendet (der ModusAUTOwird nicht unterstützt), wenn das Flaginclude_server_side_tool_invocationsaktiviert ist. - Integrierte Tools wie
google_searchbasieren auf Standort- und Uhrzeitinformationen. Wenn Ihrsystem_instructionoderfunction_declaration.descriptionwidersprüchliche Standort- und Uhrzeitinformationen enthält, funktioniert die Funktion für die Kombination von Tools möglicherweise nicht richtig.
Unterstützte Tools
Die standardmäßige Weitergabe des Tool-Kontexts gilt für serverseitige (integrierte) Tools. Die Codeausführung ist ebenfalls ein serverseitiges Tool, hat aber eine eigene integrierte Lösung für die Kontextweitergabe. Die Tool-Nutzung und Funktionsaufrufe sind clientseitige Tools und bieten auch integrierte Lösungen für die Kontextweitergabe.
| Tool | Ausführungsseite | Unterstützung für die Kontextübertragung |
|---|---|---|
| Google Suche | Serverseitig | Unterstützt |
| Google Maps | Serverseitig | Unterstützt |
| URL-Kontext | Serverseitig | Unterstützt |
| Dateisuche | Serverseitig | Unterstützt |
| Codeausführung | Serverseitig | Unterstützt (integriert, verwendet executableCode- und codeExecutionResult-Teile) |
| Computer Use | Clientseitig | Unterstützt (integriert, verwendet functionCall- und functionResponse-Teile) |
| Benutzerdefinierte Funktionen | Clientseitig | Unterstützt (integriert, verwendet functionCall- und functionResponse-Teile) |