본문 바로가기
C.W.K.
Stream
Lesson 01 of 04 · published

도구 선언과 스키마

~14 min · tools, function-calling, schema, openapi

Level 0불씨
0 XP0/35 lessons0/10 achievements
0/140 XP to next level140 XP to go0% complete

모델은 코드를 읽지 못해

함수 호출이라는 이름 때문에 모델이 직접 함수를 실행한다고 생각하기 쉽지만 그렇지 않아. 모델은 이름, 설명, 매개변수 스키마로 이뤄진 선언을 읽고, 호출해 달라는 구조화된 요청을 내놓아. 실행하고 결과를 돌려주는 일은 애플리케이션 몫이고, 그다음 모델이 대화를 이어 가.

따라서 설명과 스키마는 모델이 도구에 관해 아는 전부야. 참고 문서가 아니라 API 계약이지.

전체 JSON Schema가 아니라 OpenAPI 하위 집합이야

Gemini의 도구 스키마는 OpenAPI 3.0의 일부만 지원해. JSON Schema와의 차이가 중요해:

기능Gemini(OpenAPI 하위 집합)JSON Schema
최상위 형식항상 "object"제한 없음
$ref / $defs지원하지 않음지원
anyOf / oneOf지원하지 않음지원
additionalProperties인식하지 않음지원
열거형enum 배열 사용같음
중첩 객체지원지원

핵심은 이거야. 스키마를 단순하게 유지하고 ref와 union type을 쓰지 마. 실제 도구가 여러 형태를 받아야 한다면 별도 도구로 나눠 공개해.

이름보다 설명이 중요해

모델은 설명을 읽고 도구를 골라. 좋은 설명이 붙은 do_thing이 모호한 설명의 queryEnterpriseAccountManagementSystem보다 더 잘 작동해. 30초 안에 훑어볼 동료에게 주는 docstring처럼 설명을 써.

Code

깔끔한 도구 선언·python
from google.genai import types

set_lights = {
    'name': 'set_light_values',
    'description': (
        'Adjusts the brightness and color temperature of a smart light. '
        'Brightness is a 0-100 integer percentage. Color temperature is one '
        'of "daylight" (5000K), "cool" (4000K), or "warm" (2700K).'
    ),
    'parameters': {
        'type': 'object',
        'properties': {
            'brightness': {
                'type': 'integer',
                'description': 'Brightness percent, 0-100.',
            },
            'color_temp': {
                'type': 'string',
                'enum': ['daylight', 'cool', 'warm'],
                'description': 'Color temperature preset.',
            },
        },
        'required': ['brightness', 'color_temp'],
    },
}

tools = types.Tool(function_declarations=[set_lights])
TypeScript 구조 — 같은 개념·typescript
import { Type } from '@google/genai';

const setLights = {
  name: 'set_light_values',
  description: 'Adjusts brightness (0-100) and color temperature (daylight/cool/warm).',
  parameters: {
    type: Type.OBJECT,
    properties: {
      brightness: {
        type: Type.INTEGER,
        description: 'Brightness percent, 0-100.',
      },
      color_temp: {
        type: Type.STRING,
        enum: ['daylight', 'cool', 'warm'],
        description: 'Color temperature preset.',
      },
    },
    required: ['brightness', 'color_temp'],
  },
};
경고 없이 실패하는 패턴·python
# ❌ Top-level array — Gemini wants object
bad1 = {'name': 'log_events', 'parameters': {'type': 'array', 'items': {...}}}

# ❌ Union types via anyOf
bad2 = {
    'parameters': {
        'type': 'object',
        'properties': {
            'value': {'anyOf': [{'type': 'string'}, {'type': 'integer'}]}
        }
    }
}

# ❌ Refs
bad3 = {
    'parameters': {
        'type': 'object',
        '$defs': {'User': {...}},
        'properties': {'user': {'$ref': '#/$defs/User'}}
    }
}

# ✅ Flat the union into two tools instead
set_string_value = {'name': 'set_string_value', 'parameters': {'type': 'object', 'properties': {'value': {'type': 'string'}}, 'required': ['value']}}
set_int_value    = {'name': 'set_int_value',    'parameters': {'type': 'object', 'properties': {'value': {'type': 'integer'}}, 'required': ['value']}}

External links

Exercise

캘린더, 날씨 서비스, GitHub처럼 실제로 쓰는 API 하나를 골라 도구 선언 2개를 작성해. 동료가 따로 묻지 않고 정확히 호출할 수 있을 만큼 빈틈없는 설명을 써. Flash에게 자연어 프롬프트로 도구 사용을 요청하고, 헤맨다면 스키마보다 설명부터 고쳐.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.