JSON Schema: Tool의 청사진
Day 2: Tool 정의 & Function Calling
JSON Schema: Tool의 청사진
AI Agent 기초 > Day 2: Tool 정의 & Function Calling
- JSON Schema의 핵심 속성을 이해한다
- 제조 도메인에 맞는 Schema를 설계할 수 있다
- OpenAI Function Calling 형식의 Schema를 작성할 수 있다
JSON Schema가 뭘까?
집을 짓기 전에 설계도를 그린다. Tool을 만들기 전에 Schema를 그린다.
Schema = "이 Tool을 부르려면 어떤 값을 넣어야 하는지"
Function Calling의 parameters 스키마는 입력만 규정한다.
반환 형식은 스키마가 정하지 않으므로, 무엇을 돌려주는지는 description에 글로 적어야 한다.
기본 타입 6가지
타입 | 예시 | 제조 현장 예시
─────────────┼──────────────────────┼─────────────────────
string | "CNC-001" | 설비 ID, 알람 코드
number | 45.7 | 온도, 진동, 압력
integer | 150 | 수량, 일수, 횟수
boolean | true | 포함 여부, 긴급 여부
array | ["CNC-001","CNC-002"] | 설비 목록, 부품 목록
object | {"id": "CNC-001"} | 설비 정보, 필터 조건Schema 구조 해부
{
"type": "object",
"properties": {
"equipment_id": {
"type": "string",
"description": "설비 고유 ID. 형식: TYPE-NNN (예: CNC-001, PRESS-005)"
},
"include_alarms": {
"type": "boolean",
"description": "활성 알람 포함 여부",
"default": true
},
"days": {
"type": "integer",
"description": "조회할 기간 (일 단위). 최소 1, 최대 365",
"minimum": 1,
"maximum": 365,
"default": 7
}
},
"required": ["equipment_id"]
}
각 필드 분석:
| 필드 | 필수 | 이유 |
|---|---|---|
| equipment_id | O | 어떤 설비를 조회할지 반드시 알아야 함 |
| include_alarms | X | 모델이 안 보내면 파이썬 기본 인자가 채운다 |
| days | X | 모델이 안 보내면 파이썬 기본 인자가 채운다 |
핵심: required에는 "없으면 Tool이 아예 동작하지 못하는 것"만 넣는다.
함정: 스키마의
default는 API가 값을 채워 주지 않습니다. 모델에게 "안 보내면 대개 이 값으로 본다"고 알려 주는 참고 문구일 뿐입니다. 실제로 값을 채우는 것은 파이썬 함수의 기본 인자(def get_alarm_history(equipment_id: str = "", days: int = 30))입니다. 스키마에만default를 적고 함수 시그니처를 비워 두면, 모델이 생략한 순간 TypeError가 납니다.
description이 결정적이다
LLM은 description을 읽고 Tool을 선택한다. description이 불분명하면 LLM이 엉뚱한 Tool을 고른다.
나쁜 description
{
"name": "get_status",
"description": "상태 조회",
"parameters": {
"properties": {
"id": { "type": "string", "description": "ID" }
}
}
}
LLM: "상태? 뭐의 상태? 설비? 주문? 재고? id가 뭐 id?"
좋은 description
{
"name": "get_equipment_status",
"description": "제조 설비의 현재 가동 상태를 조회합니다. 설비 ID를 입력하면 가동/비가동/경고 상태, 실시간 가동률(%), 온도(°C), 진동(mm/s), 활성 알람 목록을 반환합니다. 설비 ID 형식은 'CNC-001', 'PRESS-005'입니다.",
"parameters": {
"properties": {
"equipment_id": {
"type": "string",
"description": "조회할 설비의 고유 ID. 형식: 설비유형-일련번호 (예: CNC-001, CNC-002, PRESS-005, CONV-010)"
}
}
}
}
LLM: "아, 설비 상태를 조회하는 거구나. CNC-001 형식으로 ID를 넣으면 되겠다."
enum: 선택지를 제한하라
{
"line": {
"type": "string",
"description": "생산 라인 선택",
"enum": ["A-LINE", "B-LINE", "C-LINE", "ALL"]
}
}
enum이 없으면 LLM이 "A라인", "A line", "라인A" 등 다양한 형식으로 보낸다. enum으로 제한하면 정확도가 올라간다.
복합 파라미터: 필터 조건
{
"name": "search_alarm_history",
"description": "알람 이력을 검색합니다. 설비 ID, 기간, 알람 유형으로 필터링 가능합니다.",
"parameters": {
"type": "object",
"properties": {
"equipment_id": {
"type": "string",
"description": "설비 ID (생략 시 전체 설비 조회)"
},
"alarm_type": {
"type": "string",
"description": "알람 유형 필터",
"enum": ["error", "warning", "info", "all"],
"default": "all"
},
"date_range": {
"type": "object",
"description": "조회 기간",
"properties": {
"start_date": {
"type": "string",
"description": "시작일 (YYYY-MM-DD 형식)"
},
"end_date": {
"type": "string",
"description": "종료일 (YYYY-MM-DD 형식)"
}
}
},
"limit": {
"type": "integer",
"description": "최대 결과 수",
"default": 50,
"minimum": 1,
"maximum": 500
}
},
"required": []
}
}
strict 모드: 스키마를 지키게 만들기
지금까지의 스키마는 "이렇게 보내 달라"는 요청이다. 모델이 형식을 어겨도 API가 막아 주지 않는다.
strict: true와 additionalProperties: false를 함께 쓰면 모델 출력이 스키마를 따르도록 강제된다.
{
"type": "function",
"function": {
"name": "get_equipment_status",
"description": "설비의 현재 가동 상태를 조회합니다...",
"strict": true,
"parameters": {
"type": "object",
"properties": {
"equipment_id": { "type": "string", "description": "설비 ID (예: CNC-001)" }
},
"required": ["equipment_id"],
"additionalProperties": false
}
}
}
additionalProperties: false: 스키마에 없는 키를 모델이 지어내지 못하게 한다strict: true를 켜면 모든 속성이required에 들어가야 한다. 선택 파라미터는"type": ["string", "null"]처럼 null을 허용해 두고, 함수 쪽에서 None을 기본값으로 처리한다
제조 도구는 설비 ID·부품 코드처럼 형식이 정해진 값을 받으므로 strict 모드의 이득이 크다. 스키마를 잡고 나면 켜 두는 편이 낫다.
팁: 제조 현장에서는 날짜 형식 통일이 중요하다. "1월 15일", "01/15", "2026-01-15" 등 다양한 형식이 올 수 있다. description에 형식을 명시하면 LLM이 맞춰서 보내준다.
본문에서 다룬 strict 모드와 default의 동작을 공식 사양과 대조해 확인하세요.
JSON Schema의 type·properties·required·enum·description 동작이 공식 사양(draft-2020-12)과 일치하는지 확인해줘. 그리고 OpenAI Function Calling에서 (1) 스키마의 default 가 값을 채워 주지 않는다는 설명이 맞는지, (2) strict: true 를 켤 때 additionalProperties: false 와 모든 속성의 required 명시가 왜 함께 요구되는지, (3) 선택 파라미터를 null 허용으로 처리하는 방식이 맞는지 짚어줘.