내장 도구와 함수 호출 결합하기

내장 도구와 함수 호출 결합하기

Preview: 내장 도구·커스텀 도구 조합은 Preview 단계이며 Gemini 3 모델에서만 지원돼요.

Gemini는 도구 호출의 컨텍스트 이력을 보존·노출함으로써 google_search 같은 내장 도구와 함수 호출(또는 커스텀 도구)을 단일 상호작용에서 결합할 수 있게 해 줘요. 내장·커스텀 도구 조합은 예를 들어 모델이 특정 비즈니스 로직을 호출하기 전에 실시간 웹 데이터에 근거를 둘 수 있는 복잡한 에이전트 워크플로를 가능하게 해요.

google_search와 커스텀 함수 getWeather로 내장·커스텀 도구 조합을 활성화하는 예제는 다음과 같아요.

# This will only work for SDK newer than 2.0.0
from google import genai

client = genai.Client()

getWeather = {
    "type": "function",
    "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"],
    },
}

# The Interactions API manages context automatically across tool calls.
# The model will first use Google Search, then call getWeather.
interaction = client.interactions.create(
    model="gemini-3.8-flash",
    input="What is the northernmost city in the United States? What's the weather like there today?",
    tools=[
        {"type": "google_search"},
        getWeather,
    ],
)

# Process steps: the interaction contains search results and a function call
for step in interaction.steps:
    if step.type == "function_call":
        print(f"Function call: {step.name} with args: {step.arguments}")
        # In a real application, you would execute the function here
        # and provide the result back to the model.
// This will only work for SDK newer than 2.0.0
import { GoogleGenAI } from '@google/genai';

const client = new GoogleGenAI({});

const getWeather = {
    type: "function",
    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"]
    }
};

// The Interactions API manages context automatically across tool calls.
// The model will first use Google Search, then call getWeather.
const interaction = await client.interactions.create({
    model: "gemini-3.8-flash",
    input: "What is the northernmost city in the United States? What's the weather like there today?",
    tools: [
        { type: "google_search" },
        getWeather,
    ],
});

// Process steps: the interaction contains search results and a function call
for (const step of interaction.steps) {
    if (step.type === "function_call") {
        console.log(`Function call: ${step.name} with args: ${JSON.stringify(step.arguments)}`);
        // In a real application, you would execute the function here
        // and provide the result back to the model.
    }
}
import com.google.genai.Client;
import com.google.genai.gaos.models.interactions.CreateModelInteraction;
import com.google.genai.gaos.models.interactions.Function;
import com.google.genai.gaos.models.interactions.GoogleSearch;
import com.google.genai.gaos.models.interactions.Interaction;
import com.google.genai.gaos.models.interactions.InteractionsInput;
import com.google.genai.gaos.models.interactions.Model;
import com.google.genai.gaos.models.operations.CreateInteractionRequestBody;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

Client client = new Client();

Map<String, Object> parameters = new HashMap<>();
parameters.put("type", "object");

Function customFunc =
    Function.builder()
        .name("get_user_location")
        .description("Retrieves user current location.")
        .parameters(parameters)
        .build();

CreateModelInteraction params =
    CreateModelInteraction.builder()
        .model(Model.of("gemini-3.8-flash"))
        .input(InteractionsInput.of("What is the weather like where I am right now?"))
        .tools(Arrays.asList(customFunc, new GoogleSearch()))
        .build();

Interaction interaction =
    client.interactions.create(CreateInteractionRequestBody.of(params)).interaction().get();

System.out.println(interaction.outputText().orElse(""));
package main

import (
    "context"
    "fmt"
    "log"

    "google.golang.org/genai"
    "google.golang.org/genai/interactions/models/interactions"
    "google.golang.org/genai/interactions/models/operations"
)

func main() {
    ctx := context.Background()
    client, err := genai.NewClient(ctx, nil)
    if err != nil {
        log.Fatal(err)
    }

    customFunc := interactions.NewTool(interactions.Function{
        Name:        genai.Ptr("get_user_location"),
        Description: genai.Ptr("Retrieves user current location."),
        Parameters: map[string]any{
            "type": "object",
        },
    })

    res, err := client.Interactions.Create(ctx, operations.CreateInteractionRequest{
        Body: operations.NewCreateInteractionRequestBody(interactions.CreateModelInteraction{
            Model: interactions.Model("gemini-3.8-flash"),
            Input: interactions.NewInteractionsInput("What is the weather like where I am right now?"),
            Tools: []interactions.Tool{
                customFunc,
                interactions.NewTool(interactions.GoogleSearch{}),
            },
        }),
    })
    if err != nil {
        log.Fatal(err)
    }
    if res.Interaction.OutputText != nil {
        fmt.Println(*res.Interaction.OutputText)
    }
}
# Specifies the API revision to avoid breaking changes when they become default
curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \
-H "Content-Type: application/json" \
-H "x-goog-api-key: YOUR_API_KEY" \
-d '{
  "model": "gemini-3.8-flash",
  "input": "What is the northernmost city in the United States? What'\''s the weather like there today?",
  "tools": [
    { "type": "google_search" },
    {
      "type": "function",
      "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"]
      }
    }
  ]
}'

출처: 원문

본문

작동 방식

Gemini 3 모델은 내장·커스텀 도구 조합을 가능하게 하는 도구 컨텍스트 순환(tool context circulation)을 사용해요. 도구 컨텍스트 순환을 통해 내장 도구의 컨텍스트를 보존·노출하고 같은 상호작용 안의 커스텀 도구와 공유할 수 있어요.

도구 조합 활성화

  • 사용하려는 내장 도구와 함께 function_declarations를 포함해 조합 동작을 트리거하세요.

API가 steps를 반환

상호작용 응답에서 API는 내장 도구 호출과 함수(커스텀 도구) 호출에 대해 별도의 steps를 반환해요.

  • 내장 도구 steps: API가 이를 자동으로 관리하며 턴 간 컨텍스트를 보존해요.
  • 함수 호출 steps: API는 커스텀 함수에 대해 function_call steps를 반환해요. 함수를 실행하고 결과를 다시 제공해요.

반환된 steps의 중요 필드

반환된 steps의 특정 필드는 도구 컨텍스트 유지와 도구 조합 활성화에 중요해요.

  • id: function_call와 function_response steps에 있음. 호출을 응답에 매핑하는 고유 식별자.
  • signature: thought steps와, Gemini 3+ 모델의 모든 도구 호출(예: function_call)·결과(예: function_response) steps에 있음. 이 암호화된 컨텍스트가 상호작용 간 도구 컨텍스트 순환을 가능하게 해요.

이 필드들 관리하기:

  • 상태 저장 모드(권장): previous_interaction_id를 사용하면 서버가 id와 signature 필드를 모두 자동 처리해요.
  • 무상태 모드: 대화 이력을 수동 관리할 때는 이후 요청에서 id와 signature 필드를 모두 모델에 다시 전달해 진위를 검증하고 컨텍스트를 유지해야 해요. 공식 SDK는 전체 응답 객체를 이력에 전달하면 이를 자동 처리해요.

도구별 데이터

일부 내장 도구는 도구 유형 특유의 사용자 가시 데이터 인자를 반환해요.

도구 사용자 가시 도구 호출 인자(있는 경우) 사용자 가시 도구 응답(있는 경우)
google_search queries search_suggestions
google_maps queries places google_maps_widget_context_token
url_context urls 탐색할 URL status: 탐색 상태 retrieved_url: 탐색된 URL
file_search 없음 없음

토큰과 가격

요청의 내장 도구 호출 파트는 prompt_token_count에 계산돼요. 이 중간 도구 steps가 이제 보이고 반환되므로 대화 이력의 일부가 돼요. 이는 응답이 아닌 요청에만 해당돼요.

Google Search 도구는 이 규칙의 예외예요. Google Search는 이미 쿼리 수준에서 자체 가격 모델을 적용하므로 토큰이 이중 청구되지 않아요(Pricing 페이지 참고).

자세한 내용은 Tokens 페이지를 읽어보세요.

한계

  • 도구 컨텍스트 순환이 활성화되면 기본적으로 validated 모드를 사용해요(auto 모드는 지원되지 않아요).
  • google_search 같은 내장 도구는 위치·현재 시간 정보에 의존하므로 system_instruction이나 function_declaration.description에 이와 충돌하는 위치·시간 정보가 있으면 도구 조합 기능이 잘 작동하지 않을 수 있어요.

지원 도구

표준 도구 컨텍스트 순환은 서버 측(내장) 도구에 적용돼요. Code Execution도 서버 측 도구지만 컨텍스트 순환에 대한 자체 내장 솔루션이 있어요. Computer Use와 함수 호출은 클라이언트 측 도구이며 역시 컨텍스트 순환에 대한 내장 솔루션이 있어요.

도구 실행 측 컨텍스트 순환 지원
Google Search 서버 측 지원
Google Maps 서버 측 지원
URL Context 서버 측 지원
File Search 서버 측 지원
Code Execution 서버 측 지원(내장, code_execution·code_execution_result steps 사용)
Computer Use 클라이언트 측 지원(내장, function_call·function_response steps 사용)
커스텀 함수 클라이언트 측 지원(내장, function_call·function_response steps 사용)

다음 단계

더 알아보기 (Learn more)