30초 요약: 둘 다 마크다운 파일이지만 하는 일이 다릅니다
1. 서브에이전트는 .claude/agents/<이름>.md, 스킬은 .claude/skills/<이름>/SKILL.md에 만듭니다. 둘 다 YAML 프론트매터와 마크다운 본문으로 이뤄져 있고, 파일을 저장하면 몇 초 안에 감지돼 재시작 없이 다음 작업부터 반영됩니다.
2. 서브에이전트는 별도 컨텍스트 창에서 혼자 일하고 결과만 돌려주는 “위임 대상”이고, 스킬은 지금 진행 중인 대화에 절차와 지식을 얹어주는 “참고 자료”입니다.
3. 프론트매터에서 필수인 건 서브에이전트의 name·description 둘뿐입니다. 스킬은 name조차 선택(폴더명이 기본값)이고, description은 “권장”입니다. 서브에이전트는 17개, 스킬은 20개 필드가 공식 문서에 정의돼 있습니다.
공식 문서의 첫 문장이 두 기능의 차이를 가장 잘 설명합니다. 서브에이전트는 “검색 결과, 로그, 파일 내용처럼 다시 볼 일 없는 것들로 메인 대화가 넘칠 때” 쓰고, 스킬은 “같은 지시문, 체크리스트, 여러 단계 절차를 채팅에 계속 붙여넣고 있을 때” 만들라고 합니다. 즉 서브에이전트는 컨텍스트를 분리하는 도구이고, 스킬은 컨텍스트를 재사용하는 도구입니다.
테스트 프로젝트에 서브에이전트·스킬·hooks를 실제로 만들었습니다
빈 폴더에 코드 리뷰 서브에이전트(code-reviewer.md), 단어 수 세기 스킬(word-counter/SKILL.md), 그리고 위험한 명령을 막는 hooks 설정을 만들었습니다. 터미널에서 find .claude -type f로 파일 목록을 뽑고 cat으로 내용을 다시 확인한 화면입니다.

서브에이전트 쪽은 tools: Read, Grep, Glob으로 읽기와 검색만 허용해 리뷰어가 코드를 고쳐버리는 일을 막았습니다. 문서에 따르면 tools를 생략하면 서브에이전트가 쓸 수 있는 모든 도구를 그대로 물려받기 때문에, “읽기 전용”을 원한다면 이 줄이 꼭 필요합니다. hooks는 .claude/settings.json에 넣었고, PreToolUse에서 rm -rf 패턴의 Bash 명령을 차단하고 PostToolUse에서 파일 쓰기·수정 이벤트를 로그 파일에 남기도록 구성했습니다.

여기까지는 로그인 없이도 됩니다. 다만 claude -p로 “이 파일 리뷰해줘”를 보내면 “Not logged in · Please run /login”이 돌아와서, 서브에이전트가 실제로 어떤 리뷰를 써 주는지까지는 이번에 확인하지 못했습니다. 유료 결제나 신규 가입도 하지 않았습니다. 그래서 이 글은 “어떻게 만드는가”와 “공식 문서가 뭐라고 정의하는가”에 집중합니다.
스킬 프론트매터: 필수 필드가 하나도 없습니다
공식 문서(code.claude.com/docs/en/skills)의 프론트매터 표를 처음 열었을 때 가장 의외였던 건 필수 필드가 없다는 점입니다. name은 생략하면 폴더 이름을 쓰고, description은 “권장(Recommended)”이며 없으면 본문 첫 문단을 대신 씁니다. 표에는 총 20개 필드가 있는데, 자주 쓰게 될 것 위주로 추렸습니다.

| 필드 | 필수 | 무엇을 정하나 |
|---|---|---|
| name | 아니요 | 스킬 목록에 표시할 이름. 생략하면 폴더 이름을 씁니다 |
| description | 권장 | 무엇을 하고 언제 쓰는 스킬인지. Claude가 자동 호출 여부를 판단하는 기준이며, 없으면 본문 첫 문단으로 대신합니다 |
| when_to_use | 아니요 | 호출 시점을 알려주는 추가 문맥(예시 요청, 트리거 문구). description과 합쳐 1,536자에서 잘립니다 |
| argument-hint / arguments | 아니요 | /스킬이름으로 부를 때 자동완성에 보여줄 힌트와, 본문에서 $이름으로 치환할 위치 인자 목록 |
| disable-model-invocation | 아니요 | true면 Claude가 스스로 부르지 않고 사용자가 /스킬이름으로만 실행. 서브에이전트에 미리 로드되는 것도 막습니다 |
| user-invocable | 아니요 | false면 슬래시 메뉴에서 숨기고 Claude만 자동 호출. 기본값 true |
| allowed-tools / disallowed-tools | 아니요 | 이 스킬이 켜진 턴 동안 묻지 않고 쓸 수 있는 도구, 또는 쓸 수 없는 도구. 다음 메시지를 보내면 풀립니다 |
| model / effort | 아니요 | 스킬이 켜진 턴에만 적용할 모델과 effort 수준. 설정에 저장되지 않고 다음 프롬프트부터 원래대로 돌아옵니다 |
| context / agent / background | 아니요 | context: fork로 스킬을 별도 서브에이전트 컨텍스트에서 실행. agent로 어떤 서브에이전트 타입을 쓸지, background로 결과를 기다릴지 정합니다 |
| hooks / paths / shell | 아니요 | 스킬 호출 시 등록할 hooks, 특정 파일 패턴을 다룰 때만 자동 로드할 경로, 인라인 셸 명령을 bash와 powershell 중 무엇으로 돌릴지 |
| metadata / license / compatibility | 아니요 | Agent Skills 공개 표준(agentskills.io)과의 호환용 필드. Claude Code는 받기만 하고 동작에는 쓰지 않습니다 |
표를 보면 스킬이 “문서 조각” 이상이라는 게 드러납니다. disallowed-tools: AskUserQuestion을 걸어 두면 백그라운드에서 도는 스킬이 사용자에게 되묻다가 멈추는 일을 막을 수 있고, context: fork를 쓰면 스킬 하나가 사실상 일회용 서브에이전트처럼 돌아갑니다. 참고로 .claude/commands/에 두던 커스텀 명령어는 스킬에 통합됐습니다. .claude/commands/deploy.md와 .claude/skills/deploy/SKILL.md 둘 다 /deploy를 만들고 똑같이 동작하며, 기존 파일은 그대로 살아 있습니다.
서브에이전트 프론트매터: 필수는 name과 description, 나머지 15개는 선택

| 필드 | 필수 | 무엇을 정하나 |
|---|---|---|
| name | 예 | 소문자와 하이픈으로 된 고유 식별자. 파일명과 달라도 되고, 콜론(:)은 플러그인 식별자(my-plugin:reviewer) 전용이라 쓸 수 없습니다 |
| description | 예 | Claude가 언제 이 서브에이전트에 위임할지 판단하는 문장. 전체 서브에이전트의 description 합이 15,000토큰을 넘으면 시작 시 경고가 뜹니다 |
| tools / disallowedTools | 아니요 | 허용할 도구 목록, 또는 “이것만 빼고 전부” 방식의 제외 목록. 둘 다 없으면 모든 도구를 상속합니다 |
| model | 아니요 | sonnet·opus·haiku·fable, 전체 모델 ID, 또는 inherit. 생략하면 문서가 정한 “서브에이전트 모델 순서”(환경변수 → 설정 → 메인 대화 모델)를 따릅니다 |
| permissionMode | 아니요 | default·acceptEdits·auto·dontAsk·bypassPermissions·plan. manual은 default의 별칭입니다. 생략하면 메인 대화의 모드를 물려받고, 플러그인 서브에이전트에서는 무시됩니다 |
| maxTurns | 아니요 | 멈추기 전 최대 턴 수. 한도에 닿으면 결과가 “부분 완료”로 표시되고 Claude가 이어서 재개할 수 있습니다 |
| skills | 아니요 | 시작할 때 컨텍스트에 통째로 넣어 둘 스킬 목록. description만이 아니라 본문 전체가 주입됩니다 |
| mcpServers / hooks | 아니요 | 이 서브에이전트만 쓰는 MCP 서버와 생명주기 hooks. 둘 다 플러그인 서브에이전트에서는 무시됩니다 |
| memory | 아니요 | user·project·local 중 하나. 세션을 넘어 학습 내용을 agent-memory/<이름>/에 남깁니다 |
| background / isolation / effort | 아니요 | 항상 백그라운드로 돌릴지, worktree로 임시 git worktree에서 격리 실행할지, effort 수준을 얼마로 할지 |
| color / initialPrompt / experimental | 아니요 | 작업 목록에 표시할 색, --agent로 메인 세션을 맡길 때 자동 입력할 첫 프롬프트, 프롬프트 캐시 TTL 같은 실험 옵션 |
실제로 써 보면 가장 신경 쓸 필드는 description입니다. Claude는 이 문장과 지금 하려는 작업이 얼마나 맞아떨어지는지를 보고 위임 여부를 정하는데, description은 모든 서브에이전트 것이 항상 컨텍스트에 올라가 있습니다. 그래서 문서는 “description은 짧게, 자세한 지침은 본문(시스템 프롬프트)에”라고 권합니다. 본문은 그 서브에이전트가 실제로 돌 때만 로드되기 때문입니다.
skills와 서브에이전트, 언제 뭘 쓰나
같은 지침을 반복해서 붙여넣고 있다면스킬입니다. CLAUDE.md에 넣기엔 길고 매번 필요하진 않은 절차를 스킬로 빼면 쓸 때만 로드돼 컨텍스트를 아낍니다.
검색 결과·로그·파일 내용으로 메인 대화가 지저분해진다면서브에이전트입니다. 자기 컨텍스트에서 일하고 요약만 돌려주므로 메인 대화가 깨끗하게 유지됩니다.
같은 종류의 일꾼을 계속 새로 만들고 있다면서브에이전트로 정의해 두세요. 리뷰, 조사, 로그 분석처럼 역할이 정해진 반복 작업이 대표적입니다.
둘 다 애매하다면스킬로 시작하세요. 나중에 context: fork 한 줄만 추가하면 서브에이전트처럼 분리 실행됩니다.
공식 문서의 “Agents and parallel work” 개요 페이지는 서브에이전트를 “자기만의 컨텍스트 창에서 독립적으로 실행돼 결과만 돌려주는 특화 도구”로 설명합니다. 각 서브에이전트는 자기 시스템 프롬프트와 도구 권한을 갖고, 메인 대화는 오케스트레이터로서 무엇을 시키고 무엇을 돌려받을지만 정합니다.

한 가지 더 알아 둘 것은 내장 서브에이전트입니다. 직접 만들지 않아도 Explore(읽기 전용 코드 탐색), Plan, General-purpose 세 가지가 기본으로 들어 있고, Claude가 필요할 때 알아서 씁니다. v2.1.198부터 Explore는 항상 Haiku로 돌지 않고 메인 대화의 모델을 물려받되 Opus를 상한으로 둡니다. 탐색을 계속 저렴한 모델로 돌리고 싶다면 같은 이름 Explore로 프로젝트 서브에이전트를 만들어 model: haiku를 주면 내장 정의를 덮어씁니다.
파일을 어디에 두느냐가 적용 범위를 정합니다
| 위치 | 적용 범위 | 만드는 방법 |
|---|---|---|
| --agents CLI 플래그(JSON) | 그 세션에서만 | 실행할 때 JSON으로 전달 |
| .claude/agents/, .claude/skills/ | 현재 프로젝트. 저장소에 올려 팀과 공유하기 좋음 | Claude에게 만들어 달라고 하거나 직접 파일 생성 |
| ~/.claude/agents/, ~/.claude/skills/ | 내 계정의 모든 프로젝트 | 같음 |
| 플러그인의 agents/·skills/ | 플러그인이 켜진 곳. 이름 앞에 플러그인명: 접두어가 붙음 | 플러그인 설치 |
같은 이름이 여러 곳에 있으면 작업 디렉터리에 가까운 정의가 이깁니다. 이번에 만든 code-reviewer는 프로젝트 로컬에 뒀으니 이 테스트 프로젝트에서만 보이고, 모든 프로젝트에서 쓰고 싶으면 ~/.claude/agents/로 옮기면 됩니다. 플러그인에서 온 서브에이전트는 보안상 hooks·mcpServers·permissionMode를 무시하므로, 그 세 가지가 필요하면 파일을 프로젝트나 계정 폴더로 복사해 쓰라고 문서가 안내합니다.

hooks: 도구 실행 전후에 강제로 끼어드는 스크립트
hooks는 앞의 둘과 성격이 다릅니다. 스킬과 서브에이전트는 Claude가 판단해서 불러오지만, hooks는 .claude/settings.json(또는 settings.local.json)에 조건을 적어 두면 특정 이벤트에 무조건 실행됩니다. 도구 실행 직전(PreToolUse), 직후(PostToolUse), 사용자 입력 직후(UserPromptSubmit), 세션 종료 직전(Stop) 같은 이벤트가 있고, 서브에이전트 시작·종료(SubagentStart·SubagentStop)에도 걸 수 있습니다. 이번 데모의 PreToolUse hook은 jq로 도구 입력의 command 필드를 읽어 rm -rf가 있으면 종료 코드 2를 돌려주게 했습니다.

hook 입력은 stdin으로 JSON(이벤트 이름, 도구 이름, 도구 입력값 등)이 들어오고, 스크립트가 그걸 읽어 분기하는 식입니다. 스킬과 서브에이전트가 “필요할 때 꺼내 보는 자료”라면 hooks는 “매번 거쳐야 하는 검문소”에 가깝습니다. 세 가지를 조합하면 “리뷰는 읽기 전용 서브에이전트가, 커밋 메시지 형식은 스킬이, 위험한 명령 차단은 hook이” 맡는 식으로 역할을 나눌 수 있습니다.
자주 묻는 질문
서브에이전트를 만들면 바로 적용되나요?
네. Claude Code가 .claude/agents/와 ~/.claude/agents/를 감시하고 있어 파일을 추가하거나 고치면 몇 초 안에 반영됩니다. Claude에게 “서브에이전트 만들어 줘”라고 시켜도 같은 경로에 파일이 생기므로 방식은 동일합니다.
tools를 생략하면 어떻게 되나요?
서브에이전트가 쓸 수 있는 모든 도구를 물려받습니다. 읽기 전용 리뷰처럼 범위를 좁히고 싶다면 tools를 명시하거나 disallowedTools로 빼는 편이 안전합니다.
스킬은 어떻게 실행하나요?
Claude가 description과 현재 작업이 맞는다고 보면 자동으로 쓰고, /스킬이름으로 직접 부를 수도 있습니다. 자동 호출을 막으려면 disable-model-invocation: true, 수동 호출을 막으려면 user-invocable: false를 씁니다.
로그인 없이도 서브에이전트를 실행할 수 있나요?
아니요. 파일 구조와 인식 방식은 로그인 없이도 공식 문서와 대조해 확인할 수 있었지만, claude -p로 프롬프트를 보내면 “Not logged in · Please run /login”이 나옵니다. 실제 위임 응답을 받으려면 로그인이 필요합니다.
Claude Code 공식 문서(code.claude.com/docs/en/sub-agents, code.claude.com/docs/en/skills, code.claude.com/docs/en/hooks, Agents and parallel work 개요 페이지)의 프론트매터 표와 설명, 그리고 로컬 환경(Claude Code v2.1.260)에 실제로 만든 서브에이전트·스킬·hooks 파일을 2026년 9월 10일 확인했습니다. 계정 로그인이 되지 않은 환경이라 실제 위임 실행 결과(응답 내용)까지는 확인하지 못했습니다.