Gemini API와 함수 호출(Function calling)
Gemini API와 함수 호출(Function calling)
함수 호출(Function calling)은 모델을 외부 도구와 API에 연결할 수 있게 해 줘요. 텍스트 응답을 생성하는 대신, 모델은 특정 함수를 호출할지 결정하고 실제 세계의 동작을 실행하는 데 필요한 매개변수를 제공해요. 이 덕분에 모델은 자연어와 실제 세계의 동작·데이터 사이의 다리 역할을 할 수 있어요. 함수 호출에는 세 가지 주요 사용 사례가 있어요.
- 동작 수행: 예약 잡기, 인보이스 만들기, 이메일 보내기, 스마트 홈 기기 제어처럼 API를 사용해 외부 시스템과 상호작용해요.
- 지식 보강: 데이터베이스, API, 지식 베이스 같은 외부 소스의 정보에 접근해요.
- 기능 확장: 계산기 사용이나 차트 만들기처럼 외부 도구를 사용해 계산을 수행하고 모델의 한계를 확장해요.
이 사용 사례들의 예시를 아래에서 살펴볼 수 있어요.
출처: 문서
본문
회의 예약(Schedule Meeting)
이 예시는 특정 시간에 참석자와 회의를 예약하는 함수를 정의해, 모델이 사용자 요청을 파싱하고 외부 시스템에서 동작을 트리거하는 구조화된 인자를 반환할 수 있게 하는 방법을 보여줘요.
Python
from google import genai
from google.genai import types
# Define the function declaration for the model
schedule_meeting_function = {
"name": "schedule_meeting",
"description": "Schedules a meeting with specified attendees at a given time and date.",
"parameters": {
"type": "object",
"properties": {
"attendees": {
"type": "array",
"items": {"type": "string"},
"description": "List of people attending the meeting.",
},
"date": {
"type": "string",
"description": "Date of the meeting (e.g., '2024-07-29')",
},
"time": {
"type": "string",
"description": "Time of the meeting (e.g., '15:00')",
},
"topic": {
"type": "string",
"description": "The subject or topic of the meeting.",
},
},
"required": ["attendees", "date", "time", "topic"],
},
}
# Configure the client and tools
client = genai.Client()
tools = types.Tool(function_declarations=[schedule_meeting_function])
config = types.GenerateContentConfig(tools=[tools])
# Send request with function declarations
response = client.models.generate_content(
model="gemini-3.8-flash",
contents="Schedule a meeting with Bob and Alice for 03/14/2025 at 10:00 AM about the Q3 planning.",
config=config,
)
# Check for a function call
if response.candidates[0].content.parts[0].function_call:
function_call = response.candidates[0].content.parts[0].function_call
print(f"Function to call: {function_call.name}")
print(f"ID: {function_call.id}")
print(f"Arguments: {function_call.args}")
# In a real app, you would call your function here:
# result = schedule_meeting(**function_call.args)
else:
print("No function call found in the response.")
print(response.text)
JavaScript
import { GoogleGenAI, Type } from '@google/genai';
// Configure the client
const ai = new GoogleGenAI({});
// Define the function declaration for the model
const scheduleMeetingFunctionDeclaration = {
name: 'schedule_meeting',
description: 'Schedules a meeting with specified attendees at a given time and date.',
parameters: {
type: Type.OBJECT,
properties: {
attendees: {
type: Type.ARRAY,
items: { type: Type.STRING },
description: 'List of people attending the meeting.',
},
date: {
type: Type.STRING,
description: 'Date of the meeting (e.g., "2024-07-29")',
},
time: {
type: Type.STRING,
description: 'Time of the meeting (e.g., "15:00")',
},
topic: {
type: Type.STRING,
description: 'The subject or topic of the meeting.',
},
},
required: ['attendees', 'date', 'time', 'topic'],
},
};
// Send request with function declarations
const response = await ai.models.generateContent({
model: 'gemini-3.8-flash',
contents: 'Schedule a meeting with Bob and Alice for 03/27/2025 at 10:00 AM about the Q3 planning.',
config: {
tools: [{
functionDeclarations: [scheduleMeetingFunctionDeclaration]
}],
},
});
// Check for function calls in the response
if (response.functionCalls && response.functionCalls.length > 0) {
const functionCall = response.functionCalls[0]; // Assuming one function call
console.log(`Function to call: ${functionCall.name}`);
console.log(`ID: ${functionCall.id}`);
console.log(`Arguments: ${JSON.stringify(functionCall.args)}`);
// In a real app, you would call your actual function here:
// const result = await scheduleMeeting(functionCall.args);
} else {
console.log("No function call found in the response.");
console.log(response.text);
}
Go
package main
import (
"context"
"fmt"
"log"
"google.golang.org/genai"
)
func main() {
ctx := context.Background()
client, err := genai.NewClient(ctx, nil)
if err != nil {
log.Fatal(err)
}
// Define the function declaration for the model
scheduleMeetingFunc := &genai.FunctionDeclaration{
Name: "schedule_meeting",
Description: "Schedules a meeting with specified attendees at a given time and date.",
Parameters: &genai.Schema{
Type: genai.TypeObject,
Properties: map[string]*genai.Schema{
"attendees": {
Type: genai.TypeArray,
Items: &genai.Schema{Type: genai.TypeString},
Description: "List of people attending the meeting.",
},
"date": {
Type: genai.TypeString,
Description: "Date of the meeting (e.g., '2024-07-29')",
},
"time": {
Type: genai.TypeString,
Description: "Time of the meeting (e.g., '15:00')",
},
"topic": {
Type: genai.TypeString,
Description: "The subject or topic of the meeting.",
},
},
Required: []string{"attendees", "date", "time", "topic"},
},
}
config := &genai.GenerateContentConfig{
Tools: []*genai.Tool{
{FunctionDeclarations: []*genai.FunctionDeclaration{scheduleMeetingFunc}},
},
}
// Send request with function declarations
response, err := client.Models.GenerateContent(
ctx,
"gemini-3.8-flash",
genai.Text("Schedule a meeting with Bob and Alice for 03/14/2025 at 10:00 AM about the Q3 planning."),
config,
)
if err != nil {
log.Fatal(err)
}
// Check for a function call
if len(response.FunctionCalls()) > 0 {
functionCall := response.FunctionCalls()[0]
fmt.Printf("Function to call: %s\n", functionCall.Name)
fmt.Printf("ID: %s\n", functionCall.ID)
fmt.Printf("Arguments: %v\n", functionCall.Args)
// In a real app, you would call your function here:
// result := scheduleMeeting(functionCall.Args)
} else {
fmt.Println("No function call found in the response.")
fmt.Println(response.Text())
}
}
REST
curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-3.8-flash:generateContent" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-H 'Content-Type: application/json' \
-X POST \
-d '{
"contents": [
{
"role": "user",
"parts": [
{
"text": "Schedule a meeting with Bob and Alice for 03/27/2025 at 10:00 AM about the Q3 planning."
}
]
}
],
"tools": [
{
"functionDeclarations": [
{
"name": "schedule_meeting",
"description": "Schedules a meeting with specified attendees at a given time and date.",
"parameters": {
"type": "object",
"properties": {
"attendees": {
"type": "array",
"items": {"type": "string"},
"description": "List of people attending the meeting."
},
"date": {
"type": "string",
"description": "Date of the meeting (e.g., '2024-07-29')"
},
"time": {
"type": "string",
"description": "Time of the meeting (e.g., '15:00')"
},
"topic": {
"type": "string",
"description": "The subject or topic of the meeting."
}
},
"required": ["attendees", "date", "time", "topic"]
}
}
]
}
]
}'
날씨 가져오기(Get Weather)
이 예시는 위치에 대한 온도 데이터를 가져오는 함수를 정의해, 모델이 실시간 또는 외부 정보가 필요한 쿼리에 답하기 위해 외부 API를 호출할 수 있게 하는 방법을 보여줘요.
Python
from google import genai
from google.genai import types
# Define the function declaration for the model
weather_function = {
"name": "get_current_temperature",
"description": "Gets the current temperature for a given location.",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city name, e.g. San Francisco",
},
},
"required": ["location"],
},
}
# Configure the client and tools
client = genai.Client()
tools = types.Tool(function_declarations=[weather_function])
config = types.GenerateContentConfig(tools=[tools])
# Send request with function declarations
response = client.models.generate_content(
model="gemini-3.8-flash",
contents="What's the temperature in London?",
config=config,
)
# Check for a function call
if response.candidates[0].content.parts[0].function_call:
function_call = response.candidates[0].content.parts[0].function_call
print(f"Function to call: {function_call.name}")
print(f"ID: {function_call.id}")
print(f"Arguments: {function_call.args}")
# In a real app, you would call your function here:
# result = get_current_temperature(**function_call.args)
else:
print("No function call found in the response.")
print(response.text)
JavaScript
import { GoogleGenAI, Type } from '@google/genai';
// Configure the client
const ai = new GoogleGenAI({});
// Define the function declaration for the model
const weatherFunctionDeclaration = {
name: 'get_current_temperature',
description: 'Gets the current temperature for a given location.',
parameters: {
type: Type.OBJECT,
properties: {
location: {
type: Type.STRING,
description: 'The city name, e.g. San Francisco',
},
},
required: ['location'],
},
};
// Send request with function declarations
const response = await ai.models.generateContent({
model: 'gemini-3.8-flash',
contents: "What's the temperature in London?",
config: {
tools: [{
functionDeclarations: [weatherFunctionDeclaration]
}],
},
});
// Check for function calls in the response
if (response.functionCalls && response.functionCalls.length > 0) {
const functionCall = response.functionCalls[0]; // Assuming one function call
console.log(`Function to call: ${functionCall.name}`);
console.log(`ID: ${functionCall.id}`);
console.log(`Arguments: ${JSON.stringify(functionCall.args)}`);
// In a real app, you would call your actual function here:
// const result = await getCurrentTemperature(functionCall.args);
} else {
console.log("No function call found in the response.");
console.log(response.text);
}
Go
package main
import (
"context"
"fmt"
"log"
"google.golang.org/genai"
)
func main() {
ctx := context.Background()
client, err := genai.NewClient(ctx, nil)
if err != nil {
log.Fatal(err)
}
// Define the function declaration for the model
weatherFunc := &genai.FunctionDeclaration{
Name: "get_current_temperature",
Description: "Gets the current temperature for a given location.",
Parameters: &genai.Schema{
Type: genai.TypeObject,
Properties: map[string]*genai.Schema{
"location": {
Type: genai.TypeString,
Description: "The city name, e.g. San Francisco",
},
},
Required: []string{"location"},
},
}
config := &genai.GenerateContentConfig{
Tools: []*genai.Tool{
{FunctionDeclarations: []*genai.FunctionDeclaration{weatherFunc}},
},
}
// Send request with function declarations
response, err := client.Models.GenerateContent(
ctx,
"gemini-3.8-flash",
genai.Text("What's the temperature in London?"),
config,
)
if err != nil {
log.Fatal(err)
}
// Check for a function call
if len(response.FunctionCalls()) > 0 {
functionCall := response.FunctionCalls()[0]
fmt.Printf("Function to call: %s\n", functionCall.Name)
fmt.Printf("ID: %s\n", functionCall.ID)
fmt.Printf("Arguments: %v\n", functionCall.Args)
// In a real app, you would call your function here:
// result := getCurrentTemperature(functionCall.Args)
} else {
fmt.Println("No function call found in the response.")
fmt.Println(response.Text())
}
}
REST
curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-3.8-flash:generateContent" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-H 'Content-Type: application/json' \
-X POST \
-d '{
"contents": [
{
"role": "user",
"parts": [
{
"text": "What'\''s the temperature in London?"
}
]
}
],
"tools": [
{
"functionDeclarations": [
{
"name": "get_current_temperature",
"description": "Gets the current temperature for a given location.",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city name, e.g. San Francisco"
}
},
"required": ["location"]
}
}
]
}
]
}'
차트 만들기(Create Chart)
이 예시는 구조화된 데이터에서 막대 차트를 생성하는 함수를 정의해, 모델이 외부 도구를 사용해 계산을 수행하거나 시각 자산을 만들 수 있음을 보여줘요.
Python
import os
from google import genai
from google.genai import types
# Define the function declaration for the model
create_chart_function = {
"name": "create_bar_chart",
"description": "Creates a bar chart given a title, labels, and corresponding values.",
"parameters": {
"type": "object",
"properties": {
"title": {
"type": "string",
"description": "The title for the chart.",
},
"labels": {
"type": "array",
"items": {"type": "string"},
"description": "List of labels for the data points (e.g., ['Q1', 'Q2', 'Q3']).",
},
"values": {
"type": "array",
"items": {"type": "number"},
"description": "List of numerical values corresponding to the labels (e.g., [50000, 75000, 60000]).",
},
},
"required": ["title", "labels", "values"],
},
}
# Configure the client and tools
client = genai.Client()
tools = types.Tool(function_declarations=[create_chart_function])
config = types.GenerateContentConfig(tools=[tools])
# Send request with function declarations
response = client.models.generate_content(
model="gemini-3.8-flash",
contents="Create a bar chart titled 'Quarterly Sales' with data: Q1: 50000, Q2: 75000, Q3: 60000.",
config=config,
)
# Check for a function call
if response.candidates[0].content.parts[0].function_call:
function_call = response.candidates[0].content.parts[0].function_call
print(f"Function to call: {function_call.name}")
print(f"ID: {function_call.id}")
print(f"Arguments: {function_call.args}")
# In a real app, you would call your function here using a charting library:
# result = create_bar_chart(**function_call.args)
else:
print("No function call found in the response.")
print(response.text)
JavaScript
import { GoogleGenAI, Type } from '@google/genai';
// Configure the client
const ai = new GoogleGenAI({});
// Define the function declaration for the model
const createChartFunctionDeclaration = {
name: 'create_bar_chart',
description: 'Creates a bar chart given a title, labels, and corresponding values.',
parameters: {
type: Type.OBJECT,
properties: {
title: {
type: Type.STRING,
description: 'The title for the chart.',
},
labels: {
type: Type.ARRAY,
items: { type: Type.STRING },
description: 'List of labels for the data points (e.g., ["Q1", "Q2", "Q3"]).',
},
values: {
type: Type.ARRAY,
items: { type: Type.NUMBER },
description: 'List of numerical values corresponding to the labels (e.g., [50000, 75000, 60000]).',
},
},
required: ['title', 'labels', 'values'],
},
};
// Send request with function declarations
const response = await ai.models.generateContent({
model: 'gemini-3.8-flash',
contents: "Create a bar chart titled 'Quarterly Sales' with data: Q1: 50000, Q2: 75000, Q3: 60000.",
config: {
tools: [{
functionDeclarations: [createChartFunctionDeclaration]
}],
},
});
// Check for function calls in the response
if (response.functionCalls && response.functionCalls.length > 0) {
const functionCall = response.functionCalls[0]; // Assuming one function call
console.log(`Function to call: ${functionCall.name}`);
console.log(`ID: ${functionCall.id}`);
console.log(`Arguments: ${JSON.stringify(functionCall.args)}`);
// In a real app, you would call your actual function here:
// const result = await createBarChart(functionCall.args);
} else {
console.log("No function call found in the response.");
console.log(response.text);
}
Go
package main
import (
"context"
"fmt"
"log"
"google.golang.org/genai"
)
func main() {
ctx := context.Background()
client, err := genai.NewClient(ctx, nil)
if err != nil {
log.Fatal(err)
}
// Define the function declaration for the model
createChartFunc := &genai.FunctionDeclaration{
Name: "create_bar_chart",
Description: "Creates a bar chart given a title, labels, and corresponding values.",
Parameters: &genai.Schema{
Type: genai.TypeObject,
Properties: map[string]*genai.Schema{
"title": {
Type: genai.TypeString,
Description: "The title for the chart.",
},
"labels": {
Type: genai.TypeArray,
Items: &genai.Schema{Type: genai.TypeString},
Description: "List of labels for the data points (e.g., ['Q1', 'Q2', 'Q3']).",
},
"values": {
Type: genai.TypeArray,
Items: &genai.Schema{Type: genai.TypeNumber},
Description: "List of numerical values corresponding to the labels (e.g., [50000, 75000, 60000]).",
},
},
Required: []string{"title", "labels", "values"},
},
}
config := &genai.GenerateContentConfig{
Tools: []*genai.Tool{
{FunctionDeclarations: []*genai.FunctionDeclaration{createChartFunc}},
},
}
// Send request with function declarations
response, err := client.Models.GenerateContent(
ctx,
"gemini-3.8-flash",
genai.Text("Create a bar chart titled 'Quarterly Sales' with data: Q1: 50000, Q2: 75000, Q3: 60000."),
config,
)
if err != nil {
log.Fatal(err)
}
// Check for a function call
if len(response.FunctionCalls()) > 0 {
functionCall := response.FunctionCalls()[0]
fmt.Printf("Function to call: %s\n", functionCall.Name)
fmt.Printf("ID: %s\n", functionCall.ID)
fmt.Printf("Arguments: %v\n", functionCall.Args)
// In a real app, you would call your function here using a charting library:
// result := createBarChart(functionCall.Args)
} else {
fmt.Println("No function call found in the response.")
fmt.Println(response.Text())
}
}
REST
curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-3.8-flash:generateContent" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-H 'Content-Type: application/json' \
-X POST \
-d '{
"contents": [
{
"role": "user",
"parts": [
{
"text": "Create a bar chart titled ''Quarterly Sales'' with data: Q1: 50000, Q2: 75000, Q3: 60000."
}
]
}
],
"tools": [
{
"functionDeclarations": [
{
"name": "create_bar_chart",
"description": "Creates a bar chart given a title, labels, and corresponding values.",
"parameters": {
"type": "object",
"properties": {
"title": {
"type": "string",
"description": "The title for the chart."
},
"labels": {
"type": "array",
"items": {"type": "string"},
"description": "List of labels for the data points (e.g., [''Q1'', ''Q2'', ''Q3''])."
},
"values": {
"type": "array",
"items": {"type": "number"},
"description": "List of numerical values corresponding to the labels (e.g., [50000, 75000, 60000])."
}
},
"required": ["title", "labels", "values"]
}
}
]
}
]
}'
함수 호출 작동 방식
*함수 호출은 애플리케이션, 모델, 외부 함수 사이의 구조화된 상호작용을 수반해요. 과정을 분석하면 다음과 같아요:
함수 선언 정의: 애플리케이션 코드에서 함수 선언을 정의해요. Function Declarations는 함수의 이름, 매개변수, 목적을 모델에 설명해요. 함수 선언과 함께 API 호출: 사용자 프롬프트와 함수 선언(들)을 모델에 보내요. 모델이 요청을 분석하고 함수 호출이 도움이 될지 결정해요. 그렇다면 함수 이름, 인자, 고유한 id를 포함하는 구조화된 JSON 객체로 응답해요(Gemini 3 모델의 경우 이 id가 이제 항상 API에서 반환돼요*). 함수 코드 실행(사용자의 책임): 모델은 함수 자체를 실행하지 않아요*. 응답을 처리하고 함수 호출이 있는지 확인하는 것은 애플리케이션의 책임이에요. 만약
-
있음(YES): 함수의 name, args,
id를 추출해 애플리케이션에서 해당 함수를 실행해요. -
없음(NO): 모델이 프롬프트에 직접 텍스트 응답을 제공했어요(이 흐름은 예시에서 덜 강조되지만 가능한 결과예요).
-
사용자 친화적 응답 만들기: 함수가 실행되었다면 결과를 캡처하고, 일치하는
id를 포함시켜 대화의 후속 턴에서 모델에 다시 보내요. 모델은 이 결과를 사용해 함수 호출의 정보를 통합한 최종의 사용자 친화적 응답을 생성해요.
이 과정은 여러 턴에 걸쳐 반복될 수 있어 복잡한 상호작용과 워크플로를 만들 수 있어요. 모델은 한 턴에서 여러 함수 호출(병렬 함수 호출), 순차 호출(복합 함수 호출), 그리고 내장 Gemini 도구와의 결합(다중 도구 사용)도 지원해요.
- 항상 함수 ID를 매핑하세요: Gemini 3은 이제 모든
functionCall과 함께 고유한id를 항상 반환해요. 이 정확한id를functionResponse에 포함해 모델이 결과를 원래 요청에 정확히 매핑할 수 있게 하세요.
1단계: 함수 선언 정의
사용자가 조명 값을 설정하고 API 요청을 할 수 있게 하는 함수와 그 선언을 애플리케이션 코드 안에 정의해요. 이 함수는 외부 서비스나 API를 호출할 수 있어요.
Python
# Define a function that the model can call to control smart lights
set_light_values_declaration = {
"name": "set_light_values",
"description": "Sets the brightness and color temperature of a light.",
"parameters": {
"type": "object",
"properties": {
"brightness": {
"type": "integer",
"description": "Light level from 0 to 100. Zero is off and 100 is full brightness",
},
"color_temp": {
"type": "string",
"enum": ["daylight", "cool", "warm"],
"description": "Color temperature of the light fixture, which can be `daylight`, `cool` or `warm`.",
},
},
"required": ["brightness", "color_temp"],
},
}
# This is the actual function that would be called based on the model's suggestion
def set_light_values(brightness: int, color_temp: str) -> dict[str, int | str]:
"""Set the brightness and color temperature of a room light. (mock API).
Args:
brightness: Light level from 0 to 100. Zero is off and 100 is full brightness
color_temp: Color temperature of the light fixture, which can be `daylight`, `cool` or `warm`.
Returns:
A dictionary containing the set brightness and color temperature.
"""
return {"brightness": brightness, "colorTemperature": color_temp}
JavaScript
import { Type } from '@google/genai';
// Define a function that the model can call to control smart lights
const setLightValuesFunctionDeclaration = {
name: 'set_light_values',
description: 'Sets the brightness and color temperature of a light.',
parameters: {
type: Type.OBJECT,
properties: {
brightness: {
type: Type.NUMBER,
description: 'Light level from 0 to 100. Zero is off and 100 is full brightness',
},
color_temp: {
type: Type.STRING,
enum: ['daylight', 'cool', 'warm'],
description: 'Color temperature of the light fixture, which can be `daylight`, `cool` or `warm`.',
},
},
required: ['brightness', 'color_temp'],
},
};
/**
* Set the brightness and color temperature of a room light. (mock API)
* @param {number} brightness - Light level from 0 to 100. Zero is off and 100 is full brightness
* @param {string} color_temp - Color temperature of the light fixture, which can be `daylight`, `cool` or `warm`.
* @return {Object} A dictionary containing the set brightness and color temperature.
*/
function setLightValues(brightness, color_temp) {
return {
brightness: brightness,
colorTemperature: color_temp
};
}
Go
package main
import "google.golang.org/genai"
// Define a function declaration that the model can call to control smart lights
var setLightValuesDeclaration = &genai.FunctionDeclaration{
Name: "set_light_values",
Description: "Sets the brightness and color temperature of a light.",
Parameters: &genai.Schema{
Type: genai.TypeObject,
Properties: map[string]*genai.Schema{
"brightness": {
Type: genai.TypeInteger,
Description: "Light level from 0 to 100. Zero is off and 100 is full brightness",
},
"color_temp": {
Type: genai.TypeString,
Enum: []string{"daylight", "cool", "warm"},
Description: "Color temperature of the light fixture, which can be `daylight`, `cool` or `warm`.",
},
},
Required: []string{"brightness", "color_temp"},
},
}
// This is the actual function that would be called based on the model's suggestion
func setLightValues(brightness int, colorTemp string) map[string]any {
return map[string]any{
"brightness": brightness,
"colorTemperature": colorTemp,
}
}
2단계: 함수 선언과 함께 모델 호출
함수 선언을 정의했다면, 이를 사용하도록 모델에 프롬프트할 수 있어요. 모델이 프롬프트와 함수 선언을 분석해 직접 응답할지 함수를 호출할지 결정해요. 함수가 호출되면 응답 객체에 함수 호출 제안이 포함돼요.
Python
from google.genai import types
# Configure the client and tools
client = genai.Client()
tools = types.Tool(function_declarations=[set_light_values_declaration])
config = types.GenerateContentConfig(tools=[tools])
# Define user prompt
contents = [
types.Content(
role="user", parts=[types.Part(text="Turn the lights down to a romantic level")]
)
]
# Send request with function declarations
response = client.models.generate_content(
model="gemini-3.8-flash",
contents=contents,
config=config,
)
print(response.candidates[0].content.parts[0].function_call)
JavaScript
import { GoogleGenAI } from '@google/genai';
// Generation config with function declaration
const config = {
tools: [{
functionDeclarations: [setLightValuesFunctionDeclaration]
}]
};
// Configure the client
const ai = new GoogleGenAI({});
// Define user prompt
const contents = [
{
role: 'user',
parts: [{ text: 'Turn the lights down to a romantic level' }]
}
];
// Send request with function declarations
const response = await ai.models.generateContent({
model: 'gemini-3.8-flash',
contents: contents,
config: config
});
console.log(response.functionCalls[0]);
Go
ctx := context.Background()
client, err := genai.NewClient(ctx, nil)
if err != nil {
log.Fatal(err)
}
// Generation config with function declaration
config := &genai.GenerateContentConfig{
Tools: []*genai.Tool{
{FunctionDeclarations: []*genai.FunctionDeclaration{setLightValuesDeclaration}},
},
}
// Define user prompt
contents := []*genai.Content{
genai.NewContentFromText("Turn the lights down to a romantic level", genai.RoleUser),
}
// Send request with function declarations
response, err := client.Models.GenerateContent(ctx, "gemini-3.8-flash", contents, config)
if err != nil {
log.Fatal(err)
}
fmt.Println(response.FunctionCalls()[0])
그런 다음 모델은 사용자의 질문에 응답하기 위해 선언된 함수 중 하나 이상을 호출하는 방법을 지정하는 OpenAPI 호환 스키마의 functionCall 객체를 반환해요.
Python
id='8f2b1a3c' args={'color_temp': 'warm', 'brightness': 25} name='set_light_values'
JavaScript
{
id: '8f2b1a3c',
name: 'set_light_values',
args: { brightness: 25, color_temp: 'warm' }
}
Go
&{ID:8f2b1a3c Args:map[brightness:25 color_temp:warm] Name:set_light_values}
3단계: set_light_values 함수 코드 실행
모델 응답에서 함수 호출 세부 정보를 추출하고, 인자를 파싱하고, set_light_values 함수를 실행해요.
Python
# Extract tool call details, it may not be in the first part.
tool_call = response.candidates[0].content.parts[0].function_call
if tool_call.name == "set_light_values":
result = set_light_values(**tool_call.args)
print(f"Function execution result: {result}")
JavaScript
// Extract tool call details
const tool_call = response.functionCalls[0]
let result;
if (tool_call.name === 'set_light_values') {
result = setLightValues(tool_call.args.brightness, tool_call.args.color_temp);
console.log(`Function execution result: ${JSON.stringify(result)}`);
}
Go
// Extract tool call details
toolCall := response.FunctionCalls()[0]
var result map[string]any
if toolCall.Name == "set_light_values" {
brightness := int(toolCall.Args["brightness"].(float64))
colorTemp := toolCall.Args["color_temp"].(string)
result = setLightValues(brightness, colorTemp)
fmt.Printf("Function execution result: %v\n", result)
}
4단계: 함수 결과로 사용자 친화적 응답 만들고 다시 모델 호출
마지막으로, 함수 실행 결과를 모델에 다시 보내 모델이 이 정보를 최종 응답에 통합해 사용자에게 보여줄 수 있게 해요.
Python
from google import genai
from google.genai import types
# Create a function response part
function_response_part = types.Part.from_function_response(
name=tool_call.name,
response={"result": result},
id=tool_call.id,
)
# Append function call and result of the function execution to contents
contents.append(response.candidates[0].content) # Append the content from the model's response.
contents.append(types.Content(role="user", parts=[function_response_part])) # Append the function response
client = genai.Client()
final_response = client.models.generate_content(
model="gemini-3.8-flash",
config=config,
contents=contents,
)
print(final_response.text)
JavaScript
// Create a function response part
const function_response_part = {
name: tool_call.name,
response: { result },
id: tool_call.id
}
// Append function call and result of the function execution to contents
contents.push(response.candidates[0].content);
contents.push({ role: 'user', parts: [{ functionResponse: function_response_part }] });
// Get the final response from the model
const final_response = await ai.models.generateContent({
model: 'gemini-3.8-flash',
contents: contents,
config: config
});
console.log(final_response.text);
Go
// Create a function response part
functionResponsePart := &genai.Part{
FunctionResponse: &genai.FunctionResponse{
ID: toolCall.ID,
Name: toolCall.Name,
Response: result,
},
}
// Append function call and result of the function execution to contents
contents = append(contents, response.Candidates[0].Content)
contents = append(contents, &genai.Content{
Role: genai.RoleUser,
Parts: []*genai.Part{functionResponsePart},
})
// Get the final response from the model
finalResponse, err := client.Models.GenerateContent(ctx, "gemini-3.8-flash", contents, config)
if err != nil {
log.Fatal(err)
}
fmt.Println(finalResponse.Text())
이것으로 함수 호출 흐름이 완성돼요. 모델은 set_light_values 함수를 성공적으로 사용해 사용자가 요청한 동작을 수행했어요.
함수 선언
프롬프트에서 함수 호출을 구현할 때, 하나 이상의 function declarations이 포함된 tools 객체를 만들어요. JSON으로, 구체적으로는 OpenAPI 스키마 형식의 선택된 하위 집합을 사용해 함수를 정의해요. 단일 함수 선언에는 다음 매개변수가 포함될 수 있어요.
name(string): 함수의 고유 이름(get_weather_forecast,send_email). 공백이나 특수 문자 없는 설명적인 이름을 사용하세요(밑줄이나 camelCase 사용).description(string): 함수의 목적과 기능에 대한 명확하고 상세한 설명. 모델이 함수를 언제 사용할지 이해하는 데 중요해요. 구체적으로 작성하고 도움이 되면 예시를 제공하세요("현재 상영 중인 영화의 위치와 선택적으로 영화 제목을 기준으로 극장을 찾습니다.").parameters(object): 함수가 기대하는 입력 매개변수를 정의해요.type(string):object같은 전체 데이터 타입을 지정해요.properties(object): 개별 매개변수를 나열하며, 각각 다음을 가져요.type(string):string,integer,boolean, array같은 매개변수의 데이터 타입.description(string): 매개변수의 목적과 형식에 대한 설명. 예시와 제약을 제공하세요("도시와 주, 예: 'San Francisco, CA' 또는 우편번호, 예: '95616'").enum(array, 선택): 매개변수 값이 고정 집합에서 온다면, description에 설명하는 대신 "enum"을 사용해 허용 값을 나열하세요. 정확도가 향상돼요("enum": ["daylight", "cool", "warm"]).
required(array): 함수가 작동하기 위해 필수인 매개변수 이름을 나열하는 문자열 배열.
types.FunctionDeclaration.from_callable(client=client, callable=your_function)을 사용해 Python 함수에서 직접 FunctionDeclarations을 구성할 수도 있어요.
생각(thinking) 모델과 함수 호출
Gemini 3과 2.5 시리즈 모델은 요청을 추론하기 위해 내부 "thinking" 프로세스를 사용해요. 이는 함수 호출 성능을 크게 향상시켜, 모델이 언제 함수를 호출하고 어떤 매개변수를 사용할지 더 잘 결정할 수 있게 해요. Gemini API는 상태가 없기 때문에 모델은 멀티 턴 대화 전체에 걸쳐 컨텍스트를 유지하기 위해 생각 서명(thought signatures)을 사용해요.
이 섹션은 생각 서명의 고급 관리를 다루며, 수동으로 API 요청(예: REST)을 구성하거나 대화 히스토리를 조작하는 경우에만 필요해요.
Google GenAI SDK(공식 라이브러리)를 사용한다면 이 과정을 관리할 필요가 없어요. SDK가 앞선 예시에서 보여준 것처럼 필요한 단계를 자동으로 처리해요.
대화 히스토리 수동 관리
대화 히스토리를 수동으로 수정하는 경우, 완전한 이전 응답을 보내는 대신 모델 턴에 포함된 thought_signature를 올바르게 처리해야 해요.
모델의 컨텍스트가 보존되도록 다음 규칙을 따르세요.
thought_signature를 원래의Part안에 넣어 항상 모델로 다시 보내요.function_call의 정확한id를function_response에 항상 포함시켜 API가 결과를 올바른 요청에 매핑할 수 있게 하세요.- 서명이 있는
Part와 없는Part를 병합하지 마세요. 결론의 위치 컨텍스트를 깨뜨려요. - 둘 다 서명을 포함하는 두
Part를 결합하지 마세요. 서명 문자열은 병합할 수 없기 때문이에요.
Gemini 3 생각 서명
Gemini 3에서 모델 응답의 어떤 Part든 생각 서명을 포함할 수 있어요. 일반적으로 모든 Part 유형에서 서명을 반환할 것을 권장하지만, 생각 서명을 다시 전달하는 것은 함수 호출에 필수예요. 대화 히스토리를 수동으로 조작하지 않는 한 Google GenAI SDK가 생각 서명을 자동으로 처리해요.
대화 히스토리를 수동으로 조작한다면, Gemini 3의 생각 서명 처리에 대한 완전한 지침과 세부 사항은 Thoughts Signatures 페이지를 참조하세요.
생각 서명 검사
구현에 필요하지는 않지만, 디버깅이나 교육 목적으로 응답을 검사해 thought_signature를 볼 수 있어요.
Python
import base64
# After receiving a response from a model with thinking enabled
# response = client.models.generate_content(...)
# The signature is attached to the response part containing the function call
part = response.candidates[0].content.parts[0]
if part.thought_signature:
print(base64.b64encode(part.thought_signature).decode("utf-8"))
JavaScript
// After receiving a response from a model with thinking enabled
// const response = await ai.models.generateContent(...)
// The signature is attached to the response part containing the function call
const part = response.candidates[0].content.parts[0];
if (part.thoughtSignature) {
console.log(part.thoughtSignature);
}
Go
// After receiving a response from a model with thinking enabled
// response, err := client.Models.GenerateContent(...)
// The signature is attached to the response part containing the function call
part := response.Candidates[0].Content.Parts[0]
if len(part.ThoughtSignature) > 0 {
fmt.Println(string(part.ThoughtSignature))
}
생각 서명의 제한 사항과 사용, 그리고 일반적인 thinking 모델에 대해 더 알아보려면 Thinking 페이지를 참조하세요.
병렬 함수 호출
단일 턴 함수 호출 외에도 한 번에 여러 함수를 호출할 수 있어요. 병렬 함수 호출은 여러 함수를 동시에 실행할 수 있게 해 주며, 함수들이 서로 의존하지 않을 때 사용돼요. 이는 여러 독립 소스에서 데이터를 수집하거나(다른 데이터베이스에서 고객 세부 정보 가져오기, 여러 창고의 재고 수준 확인), 여러 동작을 수행할 때(아파트를 디스코로 변환하기) 유용해요.
모델이 단일 턴에서 여러 함수 호출을 시작하면, function_call 객체를 받은 순서와 같은 순서로 function_result 객체를 반환할 필요가 없어요. Gemini API는 모델 출력의 id를 사용해 각 결과를 해당 호출에 매핑해요. 이 덕분에 함수를 비동기로 실행하고 완료될 때 결과를 목록에 추가할 수 있어요.
Python
power_disco_ball = {
"name": "power_disco_ball",
"description": "Powers the spinning disco ball.",
"parameters": {
"type": "object",
"properties": {
"power": {
"type": "boolean",
"description": "Whether to turn the disco ball on or off.",
}
},
"required": ["power"],
},
}
start_music = {
"name": "start_music",
"description": "Play some music matching the specified parameters.",
"parameters": {
"type": "object",
"properties": {
"energetic": {
"type": "boolean",
"description": "Whether the music is energetic or not.",
},
"loud": {
"type": "boolean",
"description": "Whether the music is loud or not.",
},
},
"required": ["energetic", "loud"],
},
}
dim_lights = {
"name": "dim_lights",
"description": "Dim the lights.",
"parameters": {
"type": "object",
"properties": {
"brightness": {
"type": "number",
"description": "The brightness of the lights, 0.0 is off, 1.0 is full.",
}
},
"required": ["brightness"],
},
}
JavaScript
import { Type } from '@google/genai';
const powerDiscoBall = {
name: 'power_disco_ball',
description: 'Powers the spinning disco ball.',
parameters: {
type: Type.OBJECT,
properties: {
power: {
type: Type.BOOLEAN,
description: 'Whether to turn the disco ball on or off.'
}
},
required: ['power']
}
};
const startMusic = {
name: 'start_music',
description: 'Play some music matching the specified parameters.',
parameters: {
type: Type.OBJECT,
properties: {
energetic: {
type: Type.BOOLEAN,
description: 'Whether the music is energetic or not.'
},
loud: {
type: Type.BOOLEAN,
description: 'Whether the music is loud or not.'
}
},
required: ['energetic', 'loud']
}
};
const dimLights = {
name: 'dim_lights',
description: 'Dim the lights.',
parameters: {
type: Type.OBJECT,
properties: {
brightness: {
type: Type.NUMBER,
description: 'The brightness of the lights, 0.0 is off, 1.0 is full.'
}
},
required: ['brightness']
}
};
Go
package main
import "google.golang.org/genai"
var powerDiscoBall = &genai.FunctionDeclaration{
Name: "power_disco_ball",
Description: "Powers the spinning disco ball.",
Parameters: &genai.Schema{
Type: genai.TypeObject,
Properties: map[string]*genai.Schema{
"power": {
Type: genai.TypeBoolean,
Description: "Whether to turn the disco ball on or off.",
},
},
Required: []string{"power"},
},
}
var startMusic = &genai.FunctionDeclaration{
Name: "start_music",
Description: "Play some music matching the specified parameters.",
Parameters: &genai.Schema{
Type: genai.TypeObject,
Properties: map[string]*genai.Schema{
"energetic": {
Type: genai.TypeBoolean,
Description: "Whether the music is energetic or not.",
},
"loud": {
Type: genai.TypeBoolean,
Description: "Whether the music is loud or not.",
},
},
Required: []string{"energetic", "loud"},
},
}
var dimLights = &genai.FunctionDeclaration{
Name: "dim_lights",
Description: "Dim the lights.",
Parameters: &genai.Schema{
Type: genai.TypeObject,
Properties: map[string]*genai.Schema{
"brightness": {
Type: genai.TypeNumber,
Description: "The brightness of the lights, 0.0 is off, 1.0 is full.",
},
},
Required: []string{"brightness"},
},
}
지정된 모든 도구의 사용을 허용하도록 함수 호출 모드를 구성하세요. 자세한 내용은 함수 호출 구성을 참조할 수 있어요.
Python
from google import genai
from google.genai import types
# Configure the client and tools
client = genai.Client()
house_tools = [
types.Tool(function_declarations=[power_disco_ball, start_music, dim_lights])
]
config = types.GenerateContentConfig(
tools=house_tools,
automatic_function_calling=types.AutomaticFunctionCallingConfig(
disable=True
),
# Force the model to call 'any' function, instead of chatting.
tool_config=types.ToolConfig(
function_calling_config=types.FunctionCallingConfig(mode='ANY')
),
)
chat = client.chats.create(model="gemini-3.8-flash", config=config)
response = chat.send_message("Turn this place into a party!")
# Print out each of the function calls requested from this single call
print("Example 1: Forced function calling")
for fn in response.function_calls:
args = ", ".join(f"{key}={val}" for key, val in fn.args.items())
print(f"{fn.name}({args}) - ID: {fn.id}")
JavaScript
import { GoogleGenAI } from '@google/genai';
// Set up function declarations
const houseFns = [powerDiscoBall, startMusic, dimLights];
const config = {
tools: [{
functionDeclarations: houseFns
}],
// Force the model to call 'any' function, instead of chatting.
toolConfig: {
functionCallingConfig: {
mode: 'any'
}
}
};
// Configure the client
const ai = new GoogleGenAI({});
// Create a chat session
const chat = ai.chats.create({
model: 'gemini-3.8-flash',
config: config
});
const response = await chat.sendMessage({message: 'Turn this place into a party!'});
// Print out each of the function calls requested from this single call
console.log("Example 1: Forced function calling");
for (const fn of response.functionCalls) {
const args = Object.entries(fn.args)
.map(([key, val]) => `${key}=${val}`)
.join(', ');
console.log(`${fn.name}(${args}) - ID: ${fn.id}`);
}
Go
ctx := context.Background()
client, err := genai.NewClient(ctx, nil)
if err != nil {
log.Fatal(err)
}
houseTools := []*genai.Tool{
{FunctionDeclarations: []*genai.FunctionDeclaration{powerDiscoBall, startMusic, dimLights}},
}
config := &genai.GenerateContentConfig{
Tools: houseTools,
// Force the model to call 'any' function, instead of chatting.
ToolConfig: &genai.ToolConfig{
FunctionCallingConfig: &genai.FunctionCallingConfig{
Mode: genai.FunctionCallingConfigModeAny,
},
},
}
response, err := client.Models.GenerateContent(
ctx,
"gemini-3.8-flash",
genai.Text("Turn this place into a party!"),
config,
)
if err != nil {
log.Fatal(err)
}
// Print out each of the function calls requested from this single call
fmt.Println("Example 1: Forced function calling")
for _, fn := range response.FunctionCalls() {
fmt.Printf("%s(%v) - ID: %s\n", fn.Name, fn.Args, fn.ID)
}
각 출력 결과는 모델이 요청한 단일 함수 호출을 반영해요. 결과를 다시 보내려면 요청된 순서와 같은 순서로 응답을 포함하세요.
Python SDK는 자동 함수 호출을 지원하며, Python 함수를 자동으로 선언으로 변환하고, 함수 호출 실행과 응답 주기를 처리해 줘요. 다음은 디스코 사용 사례의 예시예요.
참고: 자동 함수 호출(Automatic Function Calling)은 현재 Python SDK 전용 기능이에요.
Python
from google import genai
from google.genai import types
# Actual function implementations
def power_disco_ball_impl(power: bool) -> dict:
"""Powers the spinning disco ball.
Args:
power: Whether to turn the disco ball on or off.
Returns:
A status dictionary indicating the current state.
"""
return {"status": f"Disco ball powered {'on' if power else 'off'}"}
def start_music_impl(energetic: bool, loud: bool) -> dict:
"""Play some music matching the specified parameters.
Args:
energetic: Whether the music is energetic or not.
loud: Whether the music is loud or not.
Returns:
A dictionary containing the music settings.
"""
music_type = "energetic" if energetic else "chill"
volume = "loud" if loud else "quiet"
return {"music_type": music_type, "volume": volume}
def dim_lights_impl(brightness: float) -> dict:
"""Dim the lights.
Args:
brightness: The brightness of the lights, 0.0 is off, 1.0 is full.
Returns:
A dictionary containing the new brightness setting.
"""
return {"brightness": brightness}
# Configure the client
client = genai.Client()
config = types.GenerateContentConfig(
tools=[power_disco_ball_impl, start_music_impl, dim_lights_impl]
)
# Make the request
response = client.models.generate_content(
model="gemini-3.8-flash",
contents="Do everything you need to this place into party!",
config=config,
)
print("\nExample 2: Automatic function calling")
print(response.text)
# I've turned on the disco ball, started playing loud and energetic music, and dimmed the lights to 50% brightness. Let's get this party started!
복합(순차) 함수 호출
복합 또는 순차 함수 호출은 Gemini가 여러 함수 호출을 연결해 복잡한 요청을 처리할 수 있게 해 줘요. 예를 들어 "내 현재 위치의 온도를 가져와 줘"에 답하기 위해 Gemini API는 먼저 get_current_location() 함수를 호출한 다음, 위치를 매개변수로 받는 get_weather() 함수를 호출할 수 있어요.
다음 예시는 Python SDK와 자동 함수 호출을 사용해 복합 함수 호출을 구현하는 방법을 보여줘요.
Python
이 예시는 google-genai Python SDK의 자동 함수 호출 기능을 사용해요. SDK가 Python 함수를 필요한 스키마로 자동 변환하고, 모델이 요청하면 함수 호출을 실행하며, 결과를 모델로 다시 보내 작업을 완료해요.
import os
from google import genai
from google.genai import types
# Example Functions
def get_weather_forecast(location: str) -> dict:
"""Gets the current weather temperature for a given location."""
print(f"Tool Call: get_weather_forecast(location={location})")
# TODO: Make API call
print("Tool Response: {'temperature': 25, 'unit': 'celsius'}")
return {"temperature": 25, "unit": "celsius"} # Dummy response
def set_thermostat_temperature(temperature: int) -> dict:
"""Sets the thermostat to a desired temperature."""
print(f"Tool Call: set_thermostat_temperature(temperature={temperature})")
# TODO: Interact with a thermostat API
print("Tool Response: {'status': 'success'}")
return {"status": "success"}
# Configure the client and model
client = genai.Client()
config = types.GenerateContentConfig(
tools=[get_weather_forecast, set_thermostat_temperature]
)
# Make the request
response = client.models.generate_content(
model="gemini-3.8-flash",
contents="If it's warmer than 20°C in London, set the thermostat to 20°C, otherwise set it to 18°C.",
config=config,
)
# Print the final, user-facing response
print(response.text)
예상 출력
코드를 실행하면 SDK가 함수 호출을 조정하는 것을 볼 수 있어요. 모델이 먼저 get_weather_forecast를 호출해 온도를 받은 다음, 프롬프트의 로직에 따라 올바른 값으로 set_thermostat_temperature를 호출해요.
Tool Call: get_weather_forecast(location=London)
Tool Response: {'temperature': 25, 'unit': 'celsius'}
Tool Call: set_thermostat_temperature(temperature=20)
Tool Response: {'status': 'success'}
OK. I've set the thermostat to 20°C.
JavaScript
이 예시는 JavaScript/TypeScript SDK를 사용해 수동 실행 루프로 복합 함수 호출을 하는 방법을 보여줘요.
import { GoogleGenAI, Type } from "@google/genai";
// Configure the client
const ai = new GoogleGenAI({});
// Example Functions
function get_weather_forecast({ location }) {
console.log(`Tool Call: get_weather_forecast(location=${location})`);
// TODO: Make API call
console.log("Tool Response: {'temperature': 25, 'unit': 'celsius'}");
return { temperature: 25, unit: "celsius" };
}
function set_thermostat_temperature({ temperature }) {
console.log(
`Tool Call: set_thermostat_temperature(temperature=${temperature})`,
);
// TODO: Make API call
console.log("Tool Response: {'status': 'success'}");
return { status: "success" };
}
const toolFunctions = {
get_weather_forecast,
set_thermostat_temperature,
};
const tools = [
{
functionDeclarations: [
{
name: "get_weather_forecast",
description:
"Gets the current weather temperature for a given location.",
parameters: {
type: Type.OBJECT,
properties: {
location: {
type: Type.STRING,
},
},
required: ["location"],
},
},
{
name: "set_thermostat_temperature",
description: "Sets the thermostat to a desired temperature.",
parameters: {
type: Type.OBJECT,
properties: {
temperature: {
type: Type.NUMBER,
},
},
required: ["temperature"],
},
},
],
},
];
// Prompt for the model
let contents = [
{
role: "user",
parts: [
{
text: "If it's warmer than 20°C in London, set the thermostat to 20°C, otherwise set it to 18°C.",
},
],
},
];
// Loop until the model has no more function calls to make
while (true) {
const result = await ai.models.generateContent({
model: "gemini-3.8-flash",
contents,
config: { tools },
});
if (result.functionCalls && result.functionCalls.length > 0) {
const functionCall = result.functionCalls[0];
const { name, args } = functionCall;
if (!toolFunctions[name]) {
throw new Error(`Unknown function call: ${name}`);
}
// Call the function and get the response.
const toolResponse = toolFunctions[name](args);
const functionResponsePart = {
name: functionCall.name,
response: {
result: toolResponse,
},
id: functionCall.id,
};
// Send the function response back to the model.
contents.push({
role: "model",
parts: [
{
functionCall: functionCall,
},
],
});
contents.push({
role: "user",
parts: [
{
functionResponse: functionResponsePart,
},
],
});
} else {
// No more function calls, break the loop.
console.log(result.text);
break;
}
}
예상 출력
코드를 실행하면 SDK가 함수 호출을 조정하는 것을 볼 수 있어요. 모델이 먼저 get_weather_forecast를 호출해 온도를 받은 다음, 프롬프트의 로직에 따라 올바른 값으로 set_thermostat_temperature를 호출해요.
Tool Call: get_weather_forecast(location=London)
Tool Response: {'temperature': 25, 'unit': 'celsius'}
Tool Call: set_thermostat_temperature(temperature=20)
Tool Response: {'status': 'success'}
OK. It's 25°C in London, so I've set the thermostat to 20°C.
Go
이 예시는 Go SDK를 사용해 수동 실행 루프로 복합 함수 호출을 하는 방법을 보여줘요.
package main
import (
"context"
"fmt"
"log"
"google.golang.org/genai"
)
func getWeatherForecast(location string) map[string]any {
fmt.Printf("Tool Call: get_weather_forecast(location=%s)\n", location)
fmt.Println("Tool Response: map[temperature:25 unit:celsius]")
return map[string]any{"temperature": 25, "unit": "celsius"}
}
func setThermostatTemperature(temperature float64) map[string]any {
fmt.Printf("Tool Call: set_thermostat_temperature(temperature=%v)\n", temperature)
fmt.Println("Tool Response: map[status:success]")
return map[string]any{"status": "success"}
}
func main() {
ctx := context.Background()
client, err := genai.NewClient(ctx, nil)
if err != nil {
log.Fatal(err)
}
tools := []*genai.Tool{
{
FunctionDeclarations: []*genai.FunctionDeclaration{
{
Name: "get_weather_forecast",
Description: "Gets the current weather temperature for a given location.",
Parameters: &genai.Schema{
Type: genai.TypeObject,
Properties: map[string]*genai.Schema{
"location": {Type: genai.TypeString},
},
Required: []string{"location"},
},
},
{
Name: "set_thermostat_temperature",
Description: "Sets the thermostat to a desired temperature.",
Parameters: &genai.Schema{
Type: genai.TypeObject,
Properties: map[string]*genai.Schema{
"temperature": {Type: genai.TypeNumber},
},
Required: []string{"temperature"},
},
},
},
},
}
config := &genai.GenerateContentConfig{Tools: tools}
contents := []*genai.Content{
genai.NewContentFromText("If it's warmer than 20°C in London, set the thermostat to 20°C, otherwise set it to 18°C.", genai.RoleUser),
}
for {
result, err := client.Models.GenerateContent(ctx, "gemini-3.8-flash", contents, config)
if err != nil {
log.Fatal(err)
}
if len(result.FunctionCalls()) > 0 {
functionCall := result.FunctionCalls()[0]
var toolResponse map[string]any
switch functionCall.Name {
case "get_weather_forecast":
location := functionCall.Args["location"].(string)
toolResponse = getWeatherForecast(location)
case "set_thermostat_temperature":
temperature := functionCall.Args["temperature"].(float64)
toolResponse = setThermostatTemperature(temperature)
default:
log.Fatalf("Unknown function call: %s", functionCall.Name)
}
contents = append(contents, result.Candidates[0].Content)
contents = append(contents, &genai.Content{
Role: genai.RoleUser,
Parts: []*genai.Part{
{
FunctionResponse: &genai.FunctionResponse{
ID: functionCall.ID,
Name: functionCall.Name,
Response: toolResponse,
},
},
},
})
} else {
fmt.Println(result.Text())
break
}
}
}
예상 출력
Tool Call: get_weather_forecast(location=London)
Tool Response: map[temperature:25 unit:celsius]
Tool Call: set_thermostat_temperature(temperature=20)
Tool Response: map[status:success]
OK. It's 25°C in London, so I've set the thermostat to 20°C.
복합 함수 호출은 기본 Live API 기능이에요. 즉 Live API가 Python SDK와 유사하게 함수 호출을 처리할 수 있어요.
Python
# Light control schemas
turn_on_the_lights_schema = {'name': 'turn_on_the_lights'}
turn_off_the_lights_schema = {'name': 'turn_off_the_lights'}
prompt = """
Hey, can you write run some python code to turn on the lights, wait 10s and then turn off the lights?
"""
tools = [
{'code_execution': {}},
{'function_declarations': [turn_on_the_lights_schema, turn_off_the_lights_schema]}
]
await run(prompt, tools=tools, modality="AUDIO")
JavaScript
// Light control schemas
const turnOnTheLightsSchema = { name: 'turn_on_the_lights' };
const turnOffTheLightsSchema = { name: 'turn_off_the_lights' };
const prompt = `
Hey, can you write run some python code to turn on the lights, wait 10s and then turn off the lights?
`;
const tools = [
{ codeExecution: {} },
{ functionDeclarations: [turnOnTheLightsSchema, turnOffTheLightsSchema] }
];
await run(prompt, tools=tools, modality="AUDIO")
함수 호출 모드
Gemini API는 모델이 제공된 도구(함수 선언)를 사용하는 방법을 제어할 수 있게 해 줘요. 구체적으로, function_calling_config 안에서 모드를 설정할 수 있어요.
VALIDATED: 도구 조합의 기본 모드(내장 도구나 구조화된 출력이 활성화된 경우). 모델은 함수 호출이나 자연어 중 하나를 예측하도록 제약되며, 함수 스키마 준수를 보장해요.allowed_function_names가 제공되지 않으면 모델은 사용 가능한 모든 함수 선언에서 선택해요.allowed_function_names가 제공되면 모델은 허용된 함수 집합에서 선택해요. 이 모드는AUTO모드와 비교해 잘못된 함수 호출을 줄여요.AUTO:function_declarations도구만 활성화된 기본 모드. 모델은 프롬프트와 컨텍스트에 따라 자연어 응답을 생성할지 함수 호출을 제안할지 결정해요.ANY: 모델은 항상 함수 호출을 예측하도록 제약되며 함수 스키마 준수를 보장해요.allowed_function_names가 지정되지 않으면 모델은 제공된 함수 선언 중에서 선택할 수 있어요.allowed_function_names가 목록으로 제공되면 모델은 그 목록의 함수에서만 선택할 수 있어요. 가능하다면 매 프롬프트에 함수 호출 응답이 필요할 때 이 모드를 사용하세요.NONE: 모델은 함수 호출을 만드는 것이 금지돼요. 함수 선언 없이 요청을 보내는 것과 동일해요. 도구 정의를 제거하지 않고 함수 호출을 일시적으로 비활성화하려면 이 옵션을 사용하세요.
Python
from google.genai import types
# Configure function calling mode
tool_config = types.ToolConfig(
function_calling_config=types.FunctionCallingConfig(
mode="ANY", allowed_function_names=["get_current_temperature"]
)
)
# Create the generation config
config = types.GenerateContentConfig(
tools=[tools], # not defined here.
tool_config=tool_config,
)
JavaScript
import { FunctionCallingConfigMode } from '@google/genai';
// Configure function calling mode
const toolConfig = {
functionCallingConfig: {
mode: FunctionCallingConfigMode.ANY,
allowedFunctionNames: ['get_current_temperature']
}
};
// Create the generation config
const config = {
tools: tools, // not defined here.
toolConfig: toolConfig,
};
Go
// Configure function calling mode
toolConfig := &genai.ToolConfig{
FunctionCallingConfig: &genai.FunctionCallingConfig{
Mode: genai.FunctionCallingConfigModeAny,
AllowedFunctionNames: []string{"get_current_temperature"},
},
}
// Create the generation config
config := &genai.GenerateContentConfig{
Tools: tools, // not defined here.
ToolConfig: toolConfig,
}
자동 함수 호출(Python 전용)
Python SDK를 사용할 때 Python 함수를 도구로 직접 제공할 수 있어요. SDK가 이 함수를 선언으로 변환하고, 함수 호출 실행을 관리하며, 응답 주기를 처리해 줘요. 타입 힌트와 docstring으로 함수를 정의하세요. 최적의 결과를 위해 Google 스타일 docstring을 사용하는 것이 좋아요. 그러면 SDK가 자동으로:
- 모델의 함수 호출 응답을 감지해요.
- 코드에서 해당 Python 함수를 호출해요.
- 함수의 응답을 모델로 다시 보내요.
- 모델의 최종 텍스트 응답을 반환해요.
SDK는 현재 인자 설명을 생성된 함수 선언의 속성 설명 슬롯에 파싱하지 않아요. 대신 전체 docstring을 최상위 함수 설명으로 보내요.
Python
from google import genai
from google.genai import types
# Define the function with type hints and docstring
def get_current_temperature(location: str) -> dict:
"""Gets the current temperature for a given location.
Args:
location: The city and state, e.g. San Francisco, CA
Returns:
A dictionary containing the temperature and unit.
"""
# ... (implementation) ...
return {"temperature": 25, "unit": "Celsius"}
# Configure the client
client = genai.Client()
config = types.GenerateContentConfig(
tools=[get_current_temperature]
) # Pass the function itself
# Make the request
response = client.models.generate_content(
model="gemini-3.8-flash",
contents="What's the temperature in Boston?",
config=config,
)
print(response.text) # The SDK handles the function call and returns the final text
자동 함수 호출을 비활성화하려면:
Python
config = types.GenerateContentConfig(
tools=[get_current_temperature],
automatic_function_calling=types.AutomaticFunctionCallingConfig(disable=True)
)
자동 함수 스키마 선언
API는 다음 유형 중 하나를 설명할 수 있어요. Pydantic 유형도, 정의된 필드가 허용된 유형으로 구성되는 한 허용돼요. dict[str: int] 같은 Dict 유형은 여기서 잘 지원되지 않으니 사용하지 마세요.
Python
AllowedType = (
int | float | bool | str | list['AllowedType'] | pydantic.BaseModel)
추론된 스키마가 어떻게 생겼는지 보려면 from_callable을 사용해 변환할 수 있어요.
Python
from google import genai
from google.genai import types
def multiply(a: float, b: float):
"""Returns a * b."""
return a * b
client = genai.Client()
fn_decl = types.FunctionDeclaration.from_callable(callable=multiply, client=client)
# to_json_dict() provides a clean JSON representation.
print(fn_decl.to_json_dict())
다중 도구 사용: 내장 도구를 함수 호출과 결합
같은 요청에서 내장 도구와 함수 호출을 결합해 여러 도구를 활성화할 수 있어요.
Gemini 3 모델은 도구 컨텍스트 순환 기능 덕분에 내장 도구와 함수 호출을 바로 결합할 수 있어요. 자세한 내용은 내장 도구와 함수 호출 결합 페이지를 참조하세요.
미리보기: 내장 도구와 함수 호출 결합, 그리고 도구 컨텍스트 순환 기능은 Gemini 3 모델에서 Preview 상태예요.
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"],
},
}
response = client.models.generate_content(
model="gemini-3.8-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.ToolGoogleSearch(), # Built-in tool
function_declarations=[getWeather] # Custom tool
),
],
include_server_side_tool_invocations=True
),
)
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.candidates[0].content,
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
)
)]
)
]
response_2 = client.models.generate_content(
model="gemini-3.8-flash",
contents=history,
config=types.GenerateContentConfig(
tools=[
types.Tool(
google_search=types.ToolGoogleSearch(),
function_declarations=[getWeather]
),
],
include_server_side_tool_invocations=True
),
)
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 tools = [
{ googleSearch: {} },
{ functionDeclarations: [getWeather] }
];
const toolConfig = { includeServerSideToolInvocations: true };
const response1 = await client.models.generateContent({
model: "gemini-3.8-flash",
contents: [{role: "user", parts: [{text: "What is the northernmost city in the United States? What's the weather like there today?"}]}],
config: {
tools: tools,
toolConfig: toolConfig,
},
});
const functionCallId = response1.candidates[0].content.parts.find(p => p.functionCall)?.functionCall?.id;
const history = [
{
role: "user",
parts:[{text: "What is the northernmost city in the United States? What's the weather like there today?"}]
},
response1.candidates[0].content,
{
role: "user",
parts: [{
functionResponse: {
name: "getWeather",
response: {response: "Very cold. 22 degrees Fahrenheit."},
id: functionCallId
}
}]
}
];
const response2 = await client.models.generateContent({
model: "gemini-3.8-flash",
contents: history,
config: {
tools: tools,
toolConfig: toolConfig,
},
});
}
run();
Go
package main
import (
"context"
"fmt"
"log"
"google.golang.org/genai"
)
func main() {
ctx := context.Background()
client, err := genai.NewClient(ctx, nil)
if err != nil {
log.Fatal(err)
}
getWeather := &genai.FunctionDeclaration{
Name: "getWeather",
Description: "Get the weather in a given location",
Parameters: &genai.Schema{
Type: genai.TypeObject,
Properties: map[string]*genai.Schema{
"location": {
Type: genai.TypeString,
Description: "The city and state, e.g. San Francisco, CA",
},
},
Required: []string{"location"},
},
}
tools := []*genai.Tool{
{GoogleSearch: &genai.GoogleSearch{}},
{FunctionDeclarations: []*genai.FunctionDeclaration{getWeather}},
}
config := &genai.GenerateContentConfig{
Tools: tools,
}
prompt := "What is the northernmost city in the United States? What's the weather like there today?"
response1, err := client.Models.GenerateContent(ctx, "gemini-3.8-flash", genai.Text(prompt), config)
if err != nil {
log.Fatal(err)
}
toolCall := response1.FunctionCalls()[0]
history := []*genai.Content{
genai.NewContentFromText(prompt, genai.RoleUser),
response1.Candidates[0].Content,
{
Role: genai.RoleUser,
Parts: []*genai.Part{
{
FunctionResponse: &genai.FunctionResponse{
ID: toolCall.ID,
Name: toolCall.Name,
Response: map[string]any{"response": "Very cold. 22 degrees Fahrenheit."},
},
},
},
},
}
response2, err := client.Models.GenerateContent(ctx, "gemini-3.8-flash", history, config)
if err != nil {
log.Fatal(err)
}
fmt.Println(response2.Text())
}
Gemini 3 시리즈 이전 모델의 경우 Live API를 사용하세요.
멀티모달 함수 응답
참고: 이 기능은 Gemini 3 시리즈 모델에서 사용할 수 있어요.
Gemini 3 시리즈 모델의 경우 모델에 보내는 함수 응답 부분에 멀티모달 콘텐츠를 포함할 수 있어요. 모델은 다음 턴에서 이 멀티모달 콘텐츠를 처리해 더 잘 이해한 응답을 생성할 수 있어요. 함수 응답의 멀티모달 콘텐츠에는 다음 MIME 타입이 지원돼요.
- 이미지:
image/png,image/jpeg,image/webp - 문서:
application/pdf,text/plain
함수 응답에 멀티모달 데이터를 포함하려면 functionResponse 부분 안에 중첩된 하나 이상의 부분으로 포함하세요. 각 멀티모달 부분은 inlineData를 포함해야 해요. 구조화된 response 필드 안에서 멀티모달 부분을 참조하려면 고유한 displayName을 포함해야 해요.
또한 JSON 참조 형식 {"$ref": "<displayName>"}을 사용해 구조화된 response 필드 안에서 functionResponse 부분의 멀티모달 부분을 참조할 수 있어요. 모델은 응답을 처리할 때 참조를 멀티모달 콘텐츠로 대체해요. 각 displayName은 구조화된 response 필드에서 한 번만 참조될 수 있어요.
다음 예시는 get_image라는 함수에 대한 functionResponse와, displayName: "instrument.jpg"가 있는 이미지 데이터를 포함하는 중첩 부분을 담은 메시지를 보여줘요. functionResponse의 response 필드가 이 이미지 부분을 참조해요.
Python
from google import genai
from google.genai import types
import requests
client = genai.Client()
# This is a manual, two turn multimodal function calling workflow:
# 1. Define the function tool
get_image_declaration = types.FunctionDeclaration(
name="get_image",
description="Retrieves the image file reference for a specific order item.",
parameters={
"type": "object",
"properties": {
"item_name": {
"type": "string",
"description": "The name or description of the item ordered (e.g., 'instrument')."
}
},
"required": ["item_name"],
},
)
tool_config = types.Tool(function_declarations=[get_image_declaration])
# 2. Send a message that triggers the tool
prompt = "Show me the instrument I ordered last month."
response_1 = client.models.generate_content(
model="gemini-3.8-flash",
contents=[prompt],
config=types.GenerateContentConfig(
tools=[tool_config],
)
)
# 3. Handle the function call
function_call = response_1.function_calls[0]
requested_item = function_call.args["item_name"]
print(f"Model wants to call: {function_call.name}")
# Execute your tool (e.g., call an API)
# (This is a mock response for the example)
print(f"Calling external tool for: {requested_item}")
function_response_data = {
"image_ref": {"$ref": "instrument.jpg"},
}
image_path = "https://goo.gle/instrument-img"
image_bytes = requests.get(image_path).content
function_response_multimodal_data = types.FunctionResponsePart(
inline_data=types.FunctionResponseBlob(
mime_type="image/jpeg",
display_name="instrument.jpg",
data=image_bytes,
)
)
# 4. Send the tool's result back
# Append this turn's messages to history for a final response.
history = [
types.Content(role="user", parts=[types.Part(text=prompt)]),
response_1.candidates[0].content,
types.Content(
role="user",
parts=[
types.Part.from_function_response(
id=function_call.id,
name=function_call.name,
response=function_response_data,
parts=[function_response_multimodal_data]
)
],
)
]
response_2 = client.models.generate_content(
model="gemini-3.8-flash",
contents=history,
config=types.GenerateContentConfig(
tools=[tool_config],
thinking_config=types.ThinkingConfig(include_thoughts=True)
),
)
print(f"\nFinal model response: {response_2.text}")
JavaScript
import { GoogleGenAI, Type } from '@google/genai';
const client = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY });
// This is a manual, two turn multimodal function calling workflow:
// 1. Define the function tool
const getImageDeclaration = {
name: 'get_image',
description: 'Retrieves the image file reference for a specific order item.',
parameters: {
type: Type.OBJECT,
properties: {
item_name: {
type: Type.STRING,
description: "The name or description of the item ordered (e.g., 'instrument').",
},
},
required: ['item_name'],
},
};
const toolConfig = {
functionDeclarations: [getImageDeclaration],
};
// 2. Send a message that triggers the tool
const prompt = 'Show me the instrument I ordered last month.';
const response1 = await client.models.generateContent({
model: 'gemini-3.8-flash',
contents: prompt,
config: {
tools: [toolConfig],
},
});
// 3. Handle the function call
const functionCall = response1.functionCalls[0];
const requestedItem = functionCall.args.item_name;
console.log(`Model wants to call: ${functionCall.name}`);
// Execute your tool (e.g., call an API)
// (This is a mock response for the example)
console.log(`Calling external tool for: ${requestedItem}`);
const functionResponseData = {
image_ref: { $ref: 'instrument.jpg' },
};
const imageUrl = "https://goo.gle/instrument-img";
const response = await fetch(imageUrl);
const imageArrayBuffer = await response.arrayBuffer();
const base64ImageData = Buffer.from(imageArrayBuffer).toString('base64');
const functionResponseMultimodalData = {
inlineData: {
mimeType: 'image/jpeg',
displayName: 'instrument.jpg',
data: base64ImageData,
},
};
// 4. Send the tool's result back
// Append this turn's messages to history for a final response.
const history = [
{ role: 'user', parts: [{ text: prompt }] },
response1.candidates[0].content,
{
role: 'user',
parts: [
{
functionResponse: {
id: functionCall.id,
name: functionCall.name,
response: functionResponseData,
parts: [functionResponseMultimodalData]
},
},
],
},
];
const response2 = await client.models.generateContent({
model: 'gemini-3.8-flash',
contents: history,
config: {
tools: [toolConfig],
thinkingConfig: { includeThoughts: true },
},
});
console.log(`\nFinal model response: ${response2.text}`);
Go
package main
import (
"context"
"fmt"
"io"
"log"
"net/http"
"google.golang.org/genai"
)
func main() {
ctx := context.Background()
client, err := genai.NewClient(ctx, nil)
if err != nil {
log.Fatal(err)
}
// 1. Define the function tool
getImageDeclaration := &genai.FunctionDeclaration{
Name: "get_image",
Description: "Retrieves the image file reference for a specific order item.",
Parameters: &genai.Schema{
Type: genai.TypeObject,
Properties: map[string]*genai.Schema{
"item_name": {
Type: genai.TypeString,
Description: "The name or description of the item ordered (e.g., 'instrument').",
},
},
Required: []string{"item_name"},
},
}
tools := []*genai.Tool{
{FunctionDeclarations: []*genai.FunctionDeclaration{getImageDeclaration}},
}
// 2. Send a message that triggers the tool
prompt := "Show me the instrument I ordered last month."
response1, err := client.Models.GenerateContent(ctx, "gemini-3.8-flash", genai.Text(prompt), &genai.GenerateContentConfig{
Tools: tools,
})
if err != nil {
log.Fatal(err)
}
// 3. Handle the function call
functionCall := response1.FunctionCalls()[0]
requestedItem := functionCall.Args["item_name"]
fmt.Printf("Model wants to call: %s\n", functionCall.Name)
fmt.Printf("Calling external tool for: %v\n", requestedItem)
resp, err := http.Get("https://goo.gle/instrument-img")
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
imageBytes, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
functionResponseData := map[string]any{
"image_ref": map[string]any{"$ref": "instrument.jpg"},
}
functionResponseMultimodalData := &genai.FunctionResponsePart{
InlineData: &genai.FunctionResponseBlob{
MIMEType: "image/jpeg",
DisplayName: "instrument.jpg",
Data: imageBytes,
},
}
// 4. Send the tool's result back
history := []*genai.Content{
genai.NewContentFromText(prompt, genai.RoleUser),
response1.Candidates[0].Content,
{
Role: genai.RoleUser,
Parts: []*genai.Part{
{
FunctionResponse: &genai.FunctionResponse{
ID: functionCall.ID,
Name: functionCall.Name,
Response: functionResponseData,
Parts: []*genai.FunctionResponsePart{functionResponseMultimodalData},
},
},
},
},
}
response2, err := client.Models.GenerateContent(ctx, "gemini-3.8-flash", history, &genai.GenerateContentConfig{
Tools: tools,
ThinkingConfig: &genai.ThinkingConfig{
IncludeThoughts: true,
},
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("\nFinal model response: %s\n", response2.Text())
}
REST
IMG_URL="https://goo.gle/instrument-img"
MIME_TYPE=$(curl -sIL "$IMG_URL" | grep -i '^content-type:' | awk -F ': ' '{print $2}' | sed 's/\r$//' | head -n 1)
if [[ -z "$MIME_TYPE" || ! "$MIME_TYPE" == image/* ]]; then
MIME_TYPE="image/jpeg"
fi
# Check for macOS
if [[ "$(uname)" == "Darwin" ]]; then
IMAGE_B64=$(curl -sL "$IMG_URL" | base64 -b 0)
elif [[ "$(base64 --version 2>&1)" = *"FreeBSD"* ]]; then
IMAGE_B64=$(curl -sL "$IMG_URL" | base64)
else
IMAGE_B64=$(curl -sL "$IMG_URL" | base64 -w0)
fi
curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-3.8-flash:generateContent" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-H 'Content-Type: application/json' \
-X POST \
-d '{
"contents": [
...,
{
"role": "user",
"parts": [
{
"functionResponse": {
"name": "get_image",
"id": "UNIQUE_CALL_ID_HERE",
"response": {
"image_ref": {
"$ref": "instrument.jpg"
}
},
"parts": [
{
"inlineData": {
"displayName": "instrument.jpg",
"mimeType":"'"$MIME_TYPE"'",
"data": "'"$IMAGE_B64"'"
}
}
]
}
}
]
}
]
}'
구조화된 출력과 함수 호출
참고: 이 기능은 Gemini 3 시리즈 모델에서 사용할 수 있어요.
Gemini 3 시리즈 모델의 경우 함수 호출을 구조화된 출력과 함께 사용할 수 있어요. 이렇게 하면 모델이 특정 스키마를 준수하는 함수 호출이나 출력을 예측할 수 있어요. 결과적으로 모델이 함수 호출을 생성하지 않을 때에도 일관된 형식의 응답을 받을 수 있어요.
모델 컨텍스트 프로토콜(MCP)
Model Context Protocol(MCP)은 AI 애플리케이션을 외부 도구와 데이터에 연결하기 위한 개방형 표준이에요. MCP는 모델이 함수(도구), 데이터 소스(리소스), 미리 정의된 프롬프트 같은 컨텍스트에 접근하기 위한 공통 프로토콜을 제공해요.
Gemini SDK에는 MCP에 대한 내장 지원이 있어 보일러플레이트 코드를 줄이고 MCP 도구에 대한 자동 도구 호출을 제공해요. 모델이 MCP 도구 호출을 생성하면 Python과 JavaScript 클라이언트 SDK가 MCP 도구를 자동으로 실행하고 응답을 후속 요청에서 모델로 다시 보내며, 모델이 더 이상 도구 호출을 하지 않을 때까지 이 루프를 계속해요.
여기에서 Gemini와 mcp SDK로 로컬 MCP 서버를 사용하는 예시를 찾을 수 있어요.
Python
선택한 플랫폼에 최신 버전의 mcp SDK가 설치되어 있는지 확인하세요.
pip install mcp
참고: Python은 ClientSession을 tools 매개변수에 전달해 자동 도구 호출을 지원해요. 비활성화하려면 automatic_function_calling에 True로 비활성화된 값을 제공할 수 있어요.
import os
import asyncio
from datetime import datetime
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
from google import genai
client = genai.Client()
# Create server parameters for stdio connection
server_params = StdioServerParameters(
command="npx", # Executable
args=["-y", "@philschmid/weather-mcp"], # MCP Server
env=None, # Optional environment variables
)
async def run():
async with stdio_client(server_params) as (read, write):
async with ClientSession(read, write) as session:
# Prompt to get the weather for the current day in London.
prompt = f"What is the weather in London in {datetime.now().strftime('%Y-%m-%d')}?"
# Initialize the connection between client and server
await session.initialize()
# Send request to the model with MCP function declarations
response = await client.aio.models.generate_content(
model="gemini-3.8-flash",
contents=prompt,
config=genai.types.GenerateContentConfig(
temperature=0,
tools=[session], # uses the session, will automatically call the tool
# Uncomment if you **don't** want the SDK to automatically call the tool
# automatic_function_calling=genai.types.AutomaticFunctionCallingConfig(
# disable=True
# ),
),
)
print(response.text)
# Start the asyncio event loop and run the main function
asyncio.run(run())
JavaScript
선택한 플랫폼에 최신 버전의 mcp SDK가 설치되어 있는지 확인하세요.
npm install @modelcontextprotocol/sdk
참고: JavaScript는 client를 mcpToTool로 감싸 자동 도구 호출을 지원해요. 비활성화하려면 automaticFunctionCalling에 true로 비활성화된 값을 제공할 수 있어요.
import { GoogleGenAI, FunctionCallingConfigMode , mcpToTool} from '@google/genai';
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
// Create server parameters for stdio connection
const serverParams = new StdioClientTransport({
command: "npx", // Executable
args: ["-y", "@philschmid/weather-mcp"] // MCP Server
});
const client = new Client(
{
name: "example-client",
version: "1.0.0"
}
);
// Configure the client
const ai = new GoogleGenAI({});
// Initialize the connection between client and server
await client.connect(serverParams);
// Send request to the model with MCP tools
const response = await ai.models.generateContent({
model: "gemini-3.8-flash",
contents: `What is the weather in London in ${new Date().toLocaleDateString()}?`,
config: {
tools: [mcpToTool(client)], // uses the session, will automatically call the tool
// Uncomment if you **don't** want the sdk to automatically call the tool
// automaticFunctionCalling: {
// disable: true,
// },
},
});
console.log(response.text)
// Close the connection
await client.close();
내장 MCP 지원의 한계
내장 MCP 지원은 SDK의 실험적 기능이며 다음과 같은 한계가 있어요.
- 도구만 지원하고 리소스나 프롬프트는 지원하지 않아요.
- Python과 JavaScript/TypeScript SDK에서 사용할 수 있어요.
- 향후 릴리스에서 호환성이 깨지는 변경이 있을 수 있어요.
제약 때문에 구축 중인 것이 제한된다면 MCP 서버를 수동으로 통합하는 것이 항상 선택지예요.
지원 모델
이 섹션은 모델과 그 함수 호출 기능을 나열해요. 실험적 모델은 포함되지 않아요. 포괄적인 기능 개요는 모델 개요 페이지에서 찾을 수 있어요.
| 모델 | 함수 호출 | 병렬 함수 호출 | 복합 함수 호출 |
|---|---|---|---|
| Gemini 3.8 Flash | ✔️ | ✔️ | ✔️ |
| Gemini 3.7 Flash | ✔️ | ✔️ | ✔️ |
| Gemini 3.6 Flash | ✔️ | ✔️ | ✔️ |
| Gemini 3.5 Flash-Lite | ✔️ | ✔️ | ✔️ |
| Gemini 3.1 Pro Preview | ✔️ | ✔️ | ✔️ |
| Gemini 3.1 Flash-Lite | ✔️ | ✔️ | ✔️ |
| Gemini 3.5 Flash | ✔️ | ✔️ | ✔️ |
| Gemini 2.5 Pro | ✔️ | ✔️ | ✔️ |
| Gemini 2.5 Flash | ✔️ | ✔️ | ✔️ |
| Gemini 2.5 Flash-Lite | ✔️ | ✔️ | ✔️ |
모범 사례
- 함수와 매개변수 설명: 설명을 매우 명확하고 구체적으로 작성하세요. 모델이 이 설명에 의존해 올바른 함수를 선택하고 적절한 인자를 제공해요.
- 이름 규칙: 설명적인 함수 이름을 사용하세요(공백, 마침표, 하이픈 없이).
- 강한 타입: 매개변수에 특정 타입(integer, string, enum)을 사용해 오류를 줄이세요. 매개변수의 유효 값 집합이 제한적이면 enum을 사용하세요.
- 도구 선택: 모델은 임의의 수의 도구를 사용할 수 있지만, 너무 많이 제공하면 잘못되거나 차선의 도구를 선택할 위험이 커져요. 최상의 결과를 위해 컨텍스트나 작업에 관련된 도구만 제공하고, 활성 집합을 최대 10-20개로 유지하는 것이 좋아요. 총 도구 수가 많은 경우 대화 컨텍스트 기반의 동적 도구 선택을 고려하세요.
- 프롬프트 엔지니어링:
- 컨텍스트 제공: 모델에 역할을 알려주세요(예: "당신은 유용한 날씨 어시스턴트입니다.").
- 지시 제공: 함수의 사용 방법과 시기를 지정하세요(예: "날짜를 추측하지 말고, 예보에는 항상 미래 날짜를 사용하세요.").
- 명확화 장려: 필요하면 모델에게 명확한 질문을 하도록 지시하세요.
- 더 많은 전략은 Agentic 워크플로를 참조하세요. 다음은 테스트된 시스템 지시의 예시예요.
- Temperature: 더 결정적이고 안정적인 함수 호출을 위해 낮은 temperature(예: 0)를 사용하세요.
- 검증: 함수 호출에 중대한 결과가 있다면(예: 주문하기) 실행 전에 사용자와 호출을 검증하세요.
- 종료 이유 확인: 모델이 유효한 함수 호출을 생성하지 못한 경우를 처리하려면 모델 응답의
finishReason을 항상 확인하세요. - 오류 처리: 예상치 못한 입력이나 API 실패를 우아하게 처리하도록 함수에 견고한 오류 처리를 구현하세요. 모델이 사용자에게 유용한 응답을 생성하는 데 사용할 수 있는 정보성 있는 오류 메시지를 반환하세요.
- 보안: 외부 API 호출 시 보안에 주의하세요. 적절한 인증·인가 메커니즘을 사용하고, 함수 호출에서 민감한 데이터를 노출하지 마세요.
- 토큰 제한: 함수 설명과 매개변수는 입력 토큰 제한에 포함돼요. 토큰 제한에 부딪히면 함수 수나 설명 길이를 제한하고, 복잡한 작업을 더 작고 집중된 함수 집합으로 나누는 것을 고려하세요.
- bash와 사용자 정의 도구 혼합: bash와 사용자 정의 도구를 혼합해 구축한다면, Gemini 3.1 Pro Preview는
gemini-3.1-pro-preview-customtools라는 별도의 API 엔드포인트를 제공해요.
도구 전 텍스트 요구 사항에 대한 해결 방법
문제: 프롬프트가 도구 호출 바로 전에 구조화된 텍스트(XML, YAML, JSON 등)(예: <UPDATE>...</UPDATE>)를 출력하도록 요구하는 경우, 도구 호출이 때때로 Malformed_Function_Call로 실패할 수 있어요.
해결 방법: 다음 우회 방법이 이 문제를 해결해요.
- 권장: 모델이 도구 전 메모를 원시 텍스트 대신 전용
update()함수 호출 안에 넣도록 지시하세요(자세한 내용은 아래). - 구조화된 텍스트 대신 마크다운 헤더(
# UPDATE,## PLAN)로 메모를 작성하도록 모델에 지시하세요. - 도구 호출 전에 텍스트를 출력하도록 요구하지 마세요.
권장 우회 방법: 작업 내용을 전용 함수 호출로 감싸기
원래 지시 대신:
Before calling a tool, in every response you MUST first output a single `<UPDATE>` part as specified, don't skip this part or any of required sub-tags within `<UPDATE>`.
다음과 같이 업데이트된 지시를 사용하세요.
Before calling any other tool, in every response you MUST first call `update` with all required parameters (previous_step, plan, next_step, external).
그리고 고객 요청에서 이전 <UPDATE> XML 형식에 대한 모든 참조를 업데이트하세요. 그런 다음 update 함수에 대한 해당 함수 선언을 추가하세요.
{
"name": "update",
"description": "Update working notes (previous step analysis, plan, next step, external note).",
"parameters": {
"type": "OBJECT",
"properties": {
"previous_step": {
"type": "STRING",
"description": "Key findings and outcomes since the previous step."
},
"plan": {
"type": "STRING",
"description": "The current status of the plan."
},
"next_step": {
"type": "STRING",
"description": "Brief explanation of the immediate next action according to the plan."
},
"external": {
"type": "STRING",
"description": "A short, plain-language note shown to the User about what you are ABOUT TO DO next."
}
},
"required": [
"previous_step",
"plan",
"next_step",
"external"
]
}
}
그러면 모델이 같은 단계에서 두 번의 호출을 하게 돼요: 구조화된 XML을 대체하는 update() 호출과 실제로 하고 싶은 함수 호출이요.
참고 사항과 한계
- 함수 호출 부분의 위치: 사용자 정의 함수 선언을 내장 도구(Google Search 같은)와 함께 사용하면 모델이 한 턴에서
functionCall,toolCall,toolResponse부분을 섞어 반환할 수 있어요. 때문에functionCall이 parts 배열에서 항상 마지막 항목이라고 가정하지 마세요. JSON 응답을 수동으로 파싱한다면 위치에 의존하지 말고 항상 parts 배열을 순회하세요. - OpenAPI 스키마의 하위 집합만 지원돼요.
ANY모드에서 API가 매우 크거나 깊게 중첩된 스키마를 거부할 수 있어요. 오류가 발생하면 속성 이름을 줄이거나, 중첩을 줄이거나, 함수 선언 수를 제한해 함수 매개변수·응답 스키마를 단순화해 보세요.- 지원되는 Python 매개변수 유형은 제한적이에요.
- 자동 함수 호출은 Python SDK 전용 기능이에요.
더 알아보기 (Learn more)
함수 호출은 모델이 자연어 응답 대신 구조화된 함수 호출을 예측해 외부 도구·API와 연결되게 하는 핵심 기능이에요. 직렬·병렬·복합 호출, 함수 호출 모드, thinking 모델과의 상호작용, MCP 지원까지 폭넓게 활용할 수 있답니다. 생각(Thinking), 생각 서명(Thought signatures), 구조화된 출력, 도구 조합 문서를 이어서 살펴보세요.