튜토리얼
왜 AI 에이전트는 Tool Calling에서 Skills + Plugins로 가는가: 2026 아키텍처 변화와 JSON 데이터 흐름
Tool Calling은 폐기되지 않았다. 폐기된 것은 모든 도구 Schema와 안내서를 한 요청에 넣는 습관이다.
이미 에이전트 루프가 무엇인지, MCP 이 hop에서 arguments를 어떻게 검증하는지, Skills / MCP / Plugin을 어떻게 고르는지를 썼다. 오늘은 그 세 편을 반복하지 않는다. 리뷰에서 더 자주 나오는 말은 이것이다. “이미 Tool Calling이 있는데 왜 Skills와 Plugins인가?” 필드 채우기가 아니라 아키텍처가 왜 바뀌는지다. 이유는 구체적이다. 도구가 늘면 전체 Schema 표가 창을 먼저 먹는다. 흐름이 길면 시스템 프롬프트의 SOP가 잘린다. 클라이언트를 바꾸면 설명서와 손이 갈라진다. Agent Skills는 점진 공개로 발견면을 name + description으로 줄인다. Agent Plugins 1.0.0이 정하는 것은 상자이지 호출이 아니다. Google도 단일 스킬, 단일 MCP, 단일 클라이언트에는 상자가 필요 없다고 한다. 이 글은 옛 요청과 새 궤적을 JSON으로 펼친다.
버티지 못하는 것은 호출이 아니라 발견면
Tool Calling은 여전히 모델이 함수 이름과 arguments를 고르는 hop이다. 2026년에 누가 퇴역을 선언하지 않았다. 퇴역한 것은 포장 습관이다. 시작 때 쉰 개의 inputSchema를 tools[]에 붓고, “먼저 프로젝트를 확인하고, 그다음 billing, 주간 요약은 재무 형식으로”를 system에 붙인다. 열 개까지는 괜찮다. 세 번째 업무 영역이 붙으면 요청 자체가 아무도 diff하지 않는 거대한 JSON이 된다. 잘못된 도구는 환각처럼 보인다. 뿌리는 대개 발견면이 너무 넓고 설명서가 잘린 것이다. 호출 hop은 깨지지 않았다. 발견까지 같이 시킨 것이다.
창은 첫 번째 칼일 뿐이다. 두 번째는 변경이다. 재무가 주간 요약 절 순서를 바꾸면 시스템 프롬프트, 내부 wiki, 세 IDE에 붙여 둔 규칙을 같이 고친다. diff 가능한 SKILL.md가 없으면 그 변경은 PR에 안 들어간다. 세 번째는 크로스 클라이언트다. Cursor의 MCP 방언, Claude Code의 스킬 디렉터리, Antigravity의 플러그인 배치. 포장이 세 벌. 도구는 같은데 상자가 먼저 갈라진다. 통증은 tools/call 봉투가 아니다. 봉투 밖, “언제 쓰는지, 누구와 같이 가는지” 층이다.
그래서 “Skills + Plugins로 간다”는 구호 교체가 아니다. 발견과 포장을 호출 요청에서 빼내는 것이다. 호출 hop은 남는다. MCP와 JSON Schema를 보라. 에이전트 루프도 남는다. 정의 글을 보라. 오늘은 빼낸 뒤 JSON이 어떻게 흐르는지만 본다. 설치 후 클라이언트가 무엇을 쥐는지는 Plugin Manifest 실전의 다섯 hop이다. 이 글은 그 다섯 hop이 왜 나타났는지다.
| 이 층 | 옛 습관 | 2026 습관 |
|---|---|---|
| 어떤 흐름을 언제 쓸지 | 시스템 프롬프트의 긴 문단 | Skill description (약 백 토큰) |
| 어떤 손이 있는지 | 요청 안의 전체 tools[] | Plugin 설치 또는 MCP 연결 뒤 tools/list |
| 실제 호출 | 모델 arguments → 런타임 | 그대로다. 여전히 parse + Schema |
대체가 아니다. 호출층은 남고, 위에 한 층이 생긴다
Skills를 “차세대 Tool Calling”이라고 부르면 로그에서 층을 잘못 본다. Skill에는 tools/call이 없다. 설명서다. 시작 때는 메타데이터만 넣는다. 모델이 트리거에 맞은 뒤에 본문과 scripts/를 읽는다. 손은 MCP다. Plugin은 디렉터리다. 셋은 호출 위에 앉는다. arguments hop을 대체하지 않는다. 정직한 궤적에는 합법 tools/call이 한 번은 남는다. 없으면 발견층이 모델을 막은 것이지, 호출층이 지워진 것이 아니다.
점진 공개는 Agent Skills 명세의 핵이지 마케팅 형용사가 아니다. name 최대 64, description 최대 1024, 3인칭, 무엇을 하는지와 언제 쓰는지. 내부 코드명이나 1인칭 슬로건이면 발견면은 0이다. 도구는 있는데 모델이 고르지 않는다. 본문을 필요할 때 읽는 것은 런북과 쉰 개 Schema가 같은 창을 다투지 않게 하려는 것이다. 스크립트는 여전히 argv이지 tools/list의 일등 도구가 아니다. 안정적인 JSON 입력이 필요하면 역시 MCP다.
Plugin은 더 얇다. 도구 목록을 인라인할 수 없고 SOP를 plugin.json 최상위에 쓸 수 없다. 상자는 “이 설명서와 이 손이 있는가”에 답한다. 호출은 “이번 hop arguments가 합법인가”에 답한다. JSON 두 장, 일 두 가지. 네 질문은 결정 글에, 설치 후 다섯 hop은 Manifest 글에 있다. 오늘은 흐름이 납작에서 두꺼워진 경로만 그린다.
옛 데이터 흐름: 거대한 tools 배열 하나
옛 요청은 메뉴에 가게 규칙을 더한 모양이다. tools 각 항목에 완전한 inputSchema가 붙는다. system에 흐름을 넣는다. 사용자 한 문장에 모델이 전체 메뉴에서 고른다. 짧은 메뉴는 빠르다. 메뉴가 청구 + 경비 + 권한 + 배포 + 문서 검색이 되면 고르는 일 자체가 먼저 실패한다. 비슷한 도구가 서로 뺏고, SOP는 “비밀을 커밋하지 마라……” 중간에서 잘린다. 티켓에는 “모델이 미쳤다”고 쓴다. diff를 보면 먼저 미친 것은 요청 본문이다.
이 JSON에는 숨은 비용이 있다. 런타임이 조립하므로 저장소에 안 들어가는 경우가 많다. 누가 send_slack을 더해도 Schema가 얼마나 불었는지 보여주는 PR이 없다. 리뷰는 로그의 거대한 본문만 본다. 예산이 없으면 “발견층을 빼야 한다”는 신호도 없다. 평평한 구성은 도덕적 실패가 아니다. 계측 없는 팽창이다.
아래는 납작하게 줄인 옛 픽스처다. 운영은 더 길다. 먼저 parse되게 하고, tools.length와 요청 바이트에 CI 예산을 걸어라. 예산을 넘는 것은 “프롬프트를 한 줄 더”가 아니다. SOP와 전체 Schema를 시작 요청에서 빼라는 신호다.
{
"era": "flat-tool-calling",
"system": "Always check the billing project first. Never commit secrets. Write the weekly invoice summary the finance team actually reads.",
"tools": [
{
"name": "query_invoices",
"inputSchema": {
"type": "object",
"required": ["week"],
"properties": {
"week": { "type": "string", "pattern": "^[0-9]{4}-W[0-9]{2}$" },
"status": { "type": "string", "enum": ["open", "paid", "overdue"] }
}
}
},
{
"name": "export_csv",
"inputSchema": {
"type": "object",
"required": ["week"],
"properties": { "week": { "type": "string" } }
}
},
{
"name": "send_slack",
"inputSchema": {
"type": "object",
"required": ["channel", "text"],
"properties": {
"channel": { "type": "string" },
"text": { "type": "string" }
}
}
}
]
}
새 데이터 흐름: 메타데이터 → 본문 → 도구 계약
새 궤적은 필요할 때 두꺼워진다. 시작: 컨텍스트에는 스킬 메타데이터만 (상자를 깔았다면 Plugin 신원도). 매칭: 그때 SKILL.md 본문을 읽는다. 손이 필요하면: 이번 라운드 inputSchema를 tools/list에서 창에 넣는다. 호출: arguments는 예전과 같은 Schema 검사를 통과한다. 창에 동시에 올라가는 것은 “전체 메뉴 + 전체 규칙”에서 “색인 한 장 + 지금 연 한 권”으로 바뀐다. 토큰 청구는 시작 일시불에서 매칭 단위로 옮긴다.
tools[]는 사라지지 않았다. 뒤로 밀렸다. 뒤로 민 대가는 핸드셰이크 한 번, 매칭 실패 경로 하나다. description이 약하면 모델이 세 번째 hop에 못 가고, 사용자는 “Plugin을 깔아도 못 한다”고 한다. 발견면 버그이지 Tool Calling의 회귀가 아니다. 반대로 궤적에 이미 inputSchema가 있는데 런북을 system에 붓는 것은 새 구성의 후퇴다. 창 청구가 돌아온다.
아래는 같은 일의 새 픽스처다. 명세 파일이 아니다. 리뷰용 궤적이다. 옛 요청과 나란히 diff하면 SOP는 system에서 skills[].description으로, Schema는 시작에서 afterMatch.tools로 옮겨 있다. 호출층의 query_invoices 계약은 같은 canonical Schema로 남겨라. “새 아키텍처용” 두 번째 필드 세트를 만들지 마라.
{
"era": "skills-plus-plugins",
"startup": {
"plugin": "invoice-ops",
"skills": [
{
"name": "write-weekly-summary",
"description": "Turn invoice query results into the weekly summary finance reads. Use when the user asks for a week-end report.",
"loaded": "metadata"
}
]
},
"afterMatch": {
"skillBodyLoaded": true,
"tools": [
{
"name": "query_invoices",
"source": "mcp:invoice-tools",
"inputSchema": {
"type": "object",
"required": ["week"],
"properties": {
"week": { "type": "string", "pattern": "^[0-9]{4}-W[0-9]{2}$" },
"status": { "type": "string", "enum": ["open", "paid", "overdue"] }
}
}
}
]
}
}
왜 Plugin이 아직 필요한가. 설명서와 손은 같이 여행해야 한다
SOP를 Skill로, API를 MCP로 접기만 해도 요청은 얇아진다. 클라이언트가 두 대가 되면 디렉터리 배치와 MCP 방언이 다시 갈라진다. Plugin이 값을 갖는 때는 설명서와 손이 같이 가야 할 때다. Google Cloud Developer Plugin이 gcloud 가드레일 스킬과 Developer Knowledge MCP를 한 묶음으로 만드는 이유가 그것이다. Tool Calling이 약해서가 아니다. 상자는 어떤 도구도 실행하지 않는다. Antigravity, Claude Code, Cursor에서 발견 경로가 갈라지지 않게 할 뿐이다.
클라이언트 한 대, 서버 한 대면 그 클라이언트의 네이티브 MCP 설정을 써라. “선진적”이라고 Plugin을 먼저 만들면 Manifest만 한 장 는다. 결정 글의 셋째, 넷째 질문은 그대로다. 아키텍처 이동은 “모두 Plugin으로 승급”이 아니다. “호출층은 안정시키고, 아픈 곳에 발견과 포장을 더한다”이다. 두 번째 클라이언트가 없고 설명서와 손이 서로 의존하지 않으면 Skill이나 네이티브 MCP에서 멈추는 것이 올바른 2026 구성이다.
A2A 경계를 다시 긋는다. 다른 에이전트를 어떻게 찾느냐는 Agent Card이지, 상대를 tools[]에 넣는 것이 아니다. 평평한 Tool Calling이 부푸는 다른 길은 원격 에이전트를 함수 하나로 취급하는 것이다. arguments 모양이 터진다. 가로 위임은 오늘 흐름 밖이다. 오늘은 이 한 에이전트가 메뉴를 줄이고 색인을 늘리는 방법만 다룬다.
| 증상 | 먼저 움직일 층 | 하지 말 것 |
|---|---|---|
요청 200KB, tools 40개 | 발견: 스킬 메타데이터 + 필요할 때 Schema | 시스템 프롬프트를 더 늘리기 |
| IDE를 바꾸니 설명서와 손이 어긋남 | 포장: Plugin 디렉터리 | 다른 클라이언트 방언을 한 장 더 베끼기 |
| 도구는 맞는데 주간 요약 형식이 틀림 | 설명서: SKILL.md 본문 | 빈 format_report 도구를 더하기 |
두 픽스처를 나란히 diff
리뷰 픽스처는 적어도 세 장. 위의 옛 요청, 새 궤적, 실제 query_invoices arguments 한 번. 앞 두 장은 “팽창을 어느 층에서 빼냈는지”를 맡는다. 셋째는 호출층이 다시 쓰이지 않았음을 증명한다. inputSchema는 그 canonical이다. Plugin name을 도구 arguments에 넣거나 inputSchema를 plugin.json에 넣은 것은 diff에서 바로 보인다.
음수 예를 두 장 더한다. 새 궤적의 skills가 비었는데 era가 skills-plus-plugins라고 한다. 옛 요청 tools.length가 예산을 넘었는데 분할 기록이 없다. 전자는 구호만 바뀌고 발견면은 그대로인 것을 잡는다. 후자는 “프롬프트를 늘려 버틴다”를 잡는다. 저장소 픽스처에 비밀을 넣지 마라.
브라우저에서 끝난다.JSON 포맷으로 옛 요청과 새 궤적이 parse되는지 보고;JSON Schema 검증으로 inputSchema와 arguments를 보고;JSON Diff으로 옛 system / tools와 새 skills / afterMatch를 나란히 둔다. 데이터는 기기를 떠나지 않는다. 이어서 MCP와 JSON Schema, 결정 글, Manifest 다섯 hop.
관련: AI Agent란 무엇인가, MCP와 JSON Schema, Skills vs MCP vs Plugins, Plugin Manifest 실전.
자주 묻는 질문
Tool Calling을 지워야 하나?
지우지 마라. 모델은 함수 이름과 arguments를 고르고, 런타임은 tools/call을 보낸다. 지우는 것은 시작 때의 전체 메뉴이지 호출 hop이 아니다. 궤적에 합법 호출이 없으면 발견면을 먼저 보고, 그다음 런타임을 보라.
Plugin 없이 Skill만 써도 새 아키텍처인가?
발견층까지는 왔다. SOP가 시스템 프롬프트를 떠나 필요할 때 실린다. 요청은 얇아진다. 포장층은 아니다. 클라이언트 한 대로 충분하면 거기서 멈춰라. 두 번째가 나오고 설명서와 손이 같이 가야 하면 Plugin을 더하라.
모든 Schema를 시작 요청에 두는 편이 더 빠르지 않나?
메뉴가 짧고 도구가 안정적이며 클라이언트가 한 대면 더 빠르고 단순하다. 개수나 바이트로 예산을 넘으면 잘못된 도구 선택이 아낀 지연을 먹는다. 느낌보다 예산을 먼저 두어라.
Programmatic Tool Calling과 충돌하나?
충돌하지 않는다. Programmatic Tool Calling은 호출층의 프로그램 구조다. 모델이 단계대로 도구를 연속 호출한다. Skills + Plugins는 발견과 포장이다. 어떤 설명서를 읽고 어떤 손을 붙일지. 색인이 먼저, 연속 호출이 다음이다.
정리와 다음 단계
2026년에 “Tool Calling에서 Skills + Plugins로”는 한 줄로 줄어든다. 호출 hop은 남긴다. 발견과 포장은 거대한 요청에서 빼낸다. 모델은 주문한다. 자리에 앉을 때 메뉴 전체를 테이블에 올리지 않는다.
내는 순서는 이렇다. 옛 요청의 tools.length와 바이트에 예산을 건다. SOP를 description으로 접는다. 전체 Schema는 매칭 뒤로 옮긴다. 클라이언트가 두 대가 되면 plugin.json을 더한다. 옛 요청과 새 궤적은 JSONVue에 나란히 둔다. 루프 정의는 Agent 글, arguments는 MCP 글, 상자에 넣을지는 결정 글.