
2주 동안 8개 프로젝트를 진행하면서 하나의 패턴이 반복됐다. 복잡한 작업이 생기면 서브에이전트를 만들어 위임하는 것. 블로그 글 작성, 논문 용어 추출, 이미지 프롬프트 생성, SNS 콘텐츠 가공 등 각기 다른 맥락이었지만 서브에이전트 설계의 핵심 원칙은 놀랍도록 비슷했다.
이 글에서는 그간 쌓인 서브에이전트 사례를 모아 패턴별로 정리한다. Claude Code의 Task tool이 뭔지 모르는 분도 읽을 수 있게 기초부터 시작하되, 각 프로젝트의 구체적인 설계 판단도 함께 다룬다.
Claude Code에서 서브에이전트는 Task tool로 호출되는 별도의 AI 세션이다. 메인 에이전트가 대화 중에 "이 작업은 네가 해"라고 지시하면, 새로운 컨텍스트 창에서 독립적으로 실행된다.
핵심은 컨텍스트 격리다. 메인 에이전트의 대화 맥락 100K 토큰이 쌓여 있어도, 서브에이전트는 깨끗한 상태에서 필요한 지시만 받고 시작한다. 끝나면 결과만 돌려주고 사라진다. 이 단순한 메커니즘이 복잡한 작업을 다루는 데 꽤 강력하다.
실제로 서브에이전트를 쓰기 시작하면 마주치는 질문이 있다. 어떤 모델을 쓸지, 어디까지 맡길지, 파일은 누가 쓸지. 이런 판단이 프로젝트마다 달라지는데, 8개 사례를 관통하는 패턴을 뽑아보니 크게 다섯 가지로 정리됐다.
가장 기본적인 형태. 메인 에이전트가 하나의 서브에이전트를 호출하고 결과를 받는 구조다.
content-publisher가 대표적인 사례다. "K8s 주제로 글 써줘"라고 하면 서브에이전트가 프롬프트 가이드를 읽고, Lexical JSON으로 블로그 글을 생성한 뒤, PayloadCMS MCP를 통해 draft로 저장한다. 사용자 확인 후 published로 전환하는 Human-in-the-loop까지 한 에이전트 안에서 처리한다.
comfy-prompt 스킬도 같은 패턴이다. 이미지가 필요할 때 서브에이전트가 z_image_turbo 모델 특성에 맞는 프롬프트를 생성한다. CFG를 안 쓰는 모델이라 네거티브 프롬프트가 안 먹히는데, 이런 모델 특성을 스킬 문서에 담아두면 서브에이전트가 알아서 반영한다.
wrap 스킬은 세션 마무리 자동화다. /wrap 한 번이면 문서화, git commit, 스킬 사용 기록까지 순서대로 처리한다. 세션이 끝날 때마다 같은 작업을 반복하던 걸 서브에이전트 하나로 해결한 케이스.
이 패턴의 핵심 원칙은 "하나의 서브에이전트에 하나의 역할"이다. content-publisher는 CMS 발행만, comfy-prompt는 프롬프트 생성만, wrap은 세션 정리만. 역할이 명확하면 프롬프트도 단순해지고, 실패 시 원인 파악도 쉽다.
논문 번역 프로젝트에서 처음 만난 패턴이다. 용어 사전(glossary)을 구축하려면 PDF에서 전문 용어를 뽑아내야 하는데, 처음에는 하나의 에이전트가 용어 추출부터 품질 검수, 파일 저장, 번역 실행까지 전부 맡았다. 프롬프트가 복잡해지자 역할 혼동이 생기기 시작했다.
해법은 역할을 쪼개는 것이었다. 서브에이전트(Haiku)는 텍스트에서 용어를 추출해 JSON dict만 반환한다. 파일 저장도 안 하고 품질 판단도 안 한다. 메인 에이전트(Opus)가 결과를 받아서 불필요한 항목을 걸러내고, 마스터 사전에 병합하고, 번역 스크립트를 실행한다.
여기서 중요한 교훈이 하나 있다. 서브에이전트에게 파일 I/O를 시키면 안 된다. 두 서브에이전트가 동시에 같은 glossary.json을 수정하다가 데이터가 날아간 적이 있다. 파일을 쓸 수 있는 건 메인 에이전트뿐이라는 규칙을 세운 뒤로 이런 문제가 사라졌다.
모델 선택도 역할에 따라 달라진다. 용어 추출처럼 단순 반복 작업은 Haiku로 충분하다. 검수처럼 판단이 필요한 작업은 Opus가 맡는다. 모델 비용이 토큰당 수십 배 차이 나니, 이 구분이 비용에 직접 영향을 미친다.
100페이지짜리 논문의 용어를 추출한다고 하자. 한 서브에이전트가 전부 처리하면 시간이 오래 걸린다. 그래서 페이지 범위를 나눠 여러 서브에이전트에 병렬로 맡겼다.
서브에이전트 A: 1-30페이지 용어 추출 → JSON
서브에이전트 B: 31-60페이지 용어 추출 → JSON
서브에이전트 C: 61-100페이지 용어 추출 → JSON
메인 에이전트: 세 결과를 병합 → 마스터 사전 업데이트이때 각 서브에이전트는 JSON dict만 반환한다. CSV 파일을 직접 저장하지 않는다. 병합은 agent_total_glossary.py --merge로 메인 에이전트가 수행한다. 앞서 말한 "파일 I/O는 메인만" 원칙이 여기서도 적용된다.
Scatter-Gather의 전제 조건은 작업이 독립적으로 분할 가능해야 한다는 것이다. 페이지별 용어 추출은 순서에 의존하지 않으니 병렬이 가능하지만, "앞 절의 결과를 참조해서 다음 절을 처리"하는 작업은 이 패턴에 안 맞는다.
glossary 워크플로우를 리팩토링하면서 발견한 패턴이다. 논문 번역을 요청하면 에이전트가 가장 먼저 하는 일이 뭐였냐면, PDF에서 텍스트를 추출하고 서브에이전트에게 용어를 뽑게 하는 것이었다. 그런데 이미 glossary CSV가 있으면? 이 모든 과정이 낭비다.
그래서 번역 요청이 들어오면 가장 먼저 glossary_output/<basename>.glossary.csv 존재 여부를 확인한다. 파일이 있으면 용어 추출 전체를 건너뛰고 바로 번역으로 간다. 서브에이전트를 호출하기 전에 "그 작업이 정말 필요한가?"를 먼저 판단하는 것.
서브에이전트 호출은 공짜가 아니다. 토큰 비용, 실행 시간, 잠재적 오류 모두 비용이다. Short-Circuit은 이 비용을 최소화하는 가장 간단한 방법이다.
블로그 글 하나를 발행하려면 이런 과정을 거친다. 글감을 분석하고, 글을 쓰고, 이미지를 만들고, CMS에 저장하고, SNS용으로 가공하고, 배포한다. 5개 서비스를 넘나드는 작업이다.
Agent Teams는 이걸 하나의 대화에서 처리한다. 팀 리더 에이전트가 5개 전담 에이전트를 조율하는 구조다.
여기서 주목할 부분은 모델 선택이다. 콘텐츠 품질이 직접 결과물에 드러나는 에이전트(museck, comfy, postiz)에는 Opus를, 명령 실행 위주인 에이전트(n8n, homelab)에는 Sonnet을 배정했다. 전체 파이프라인 비용을 생각하면 이 구분이 꽤 중요하다.
오케스트레이터 패턴과 단독 서브에이전트의 결정적 차이는 팀 리더의 존재다. 단독 서브에이전트는 메인 에이전트가 곧 오케스트레이터이지만, Agent Teams에서는 팀 리더가 "이 작업은 museck-agent에게, 끝나면 결과를 comfy-agent에게 넘겨"처럼 에이전트 간 데이터 흐름을 관리한다.
지금까지 다룬 프로젝트를 표로 정리해보자.
프로젝트 서브에이전트 역할 모델 패턴
────────────────────────────────────────────────────────────
content-publisher CMS 글 발행 Sonnet 단독
blog-writer 글 작성+이미지+CMS Opus 단독
comfy-prompt 이미지 프롬프트 생성 - 단독(스킬)
wrap 세션 마무리 자동화 - 단독(스킬)
skill-version-mgr 스킬 버전 관리 - 단독(스킬)
glossary-extract PDF 용어 추출 Haiku 역할분리+병렬
glossary-workflow 추출→검수→병합→번역 Haiku/Opus Scatter-Gather
agent-team 5개 에이전트 파이프라인 혼합 오케스트레이터눈에 띄는 점이 있다. 단순한 작업은 스킬(프롬프트 파일) 형태로, 복잡한 작업은 에이전트 정의 파일로, 대규모 파이프라인은 Agent Teams로 진화한다. 작업의 복잡도에 따라 자연스럽게 적절한 추상화 수준이 결정된다.
8개 프로젝트를 관통하는 설계 원칙을 정리한다.
서브에이전트에게 "알아서 잘 해줘"는 최악의 지시다. 입력이 뭐고, 출력 형식이 뭔지 구체적으로 정해야 한다. glossary 추출 서브에이전트에게 "JSON dict로만 반환해. 파일은 건드리지 마"라고 명시한 게 대표적인 예시다.
여러 서브에이전트가 같은 파일을 동시에 수정하면 충돌한다. 파일을 쓸 수 있는 건 메인 에이전트(또는 팀 리더)뿐이고, 서브에이전트는 메모리(JSON, 문자열)로만 결과를 반환해야 한다. 소프트웨어 엔지니어링에서 말하는 "단일 쓰기 소유권"과 같은 원리다.
전부 Opus를 쓸 필요 없다. 용어 추출 같은 단순 반복은 Haiku, 글 생성 같은 창의적 작업은 Opus, 인프라 명령 실행은 Sonnet. 토큰 비용이 모델마다 수십 배 차이 나니까, 이 판단이 파이프라인 전체 비용을 좌우한다.
content-publisher는 프롬프트 가이드를 prompts/blog-post.md 파일로 분리했다. 에이전트가 실행 시 이 파일을 읽어 가이드라인을 따르는 구조. 프롬프트를 바꿀 때 에이전트 정의를 수정할 필요가 없어진다.
comfy-prompt 스킬은 여기서 한 발 더 나간다. 3계층 참조 문서(디퓨전 기초, 모델 패밀리, z_image_turbo 심층 가이드)를 두고 필요할 때만 로드한다. 프롬프트 자체를 버전 관리할 수 있게 된 셈이다.
완전 자동화는 위험하다. content-publisher는 draft 저장 후 사용자 확인을 거쳐야 published로 전환된다. Agent Teams 파이프라인에서는 두 곳에 사람이 개입한다. 블로그 draft 확인 후 발행, SNS 텍스트 확인 후 배포. 자동화와 품질 관리 사이의 균형점이다.
서브에이전트가 외부 서비스와 통신하는 방식도 중요하다. blog-writer와 content-publisher 모두 PayloadCMS와 상호작용하는데, REST API 대신 MCP(Model Context Protocol)를 사용한다.
MCP의 장점은 에이전트가 스키마를 자동으로 이해한다는 점이다. REST API는 엔드포인트, 필드, 타입을 에이전트에게 일일이 알려줘야 하지만, MCP는 서비스가 자기 스키마를 노출하니까 에이전트가 "posts 컬렉션에 title, slug, content 필드가 있네"를 스스로 파악한다.
물론 MCP만으로 모든 게 해결되지는 않는다. 이미지 업로드처럼 바이너리 파일을 다루는 작업은 여전히 REST API가 필요하다. blog-writer에서도 이미지는 REST API로 media에 올리고, 글 저장은 MCP로 하는 하이브리드 방식을 쓴다.
2주간 서브에이전트를 만들면서 계속 느낀 건, 이게 결국 소프트웨어 설계와 같다는 점이다. 관심사 분리, 단일 책임, 동시성 제어, 인터페이스 설계. 새로운 개념이 아니라 익숙한 원칙의 새로운 적용이다.
다른 점이 있다면, 인터페이스가 자연어라는 것. 함수 시그니처 대신 프롬프트로 입출력을 정의하고, 타입 체크 대신 에이전트의 판단에 의존한다. 그래서 더 유연하지만 더 불확실하기도 하다. Human-in-the-loop가 중요한 이유다.
서브에이전트를 처음 써보려는 분에게 한마디. 작게 시작하자. 단독 서브에이전트 하나로 반복 작업을 자동화해보고, 필요하면 역할을 나누고, 작업이 커지면 오케스트레이터를 도입하면 된다. 한 번에 Agent Teams부터 만들 필요는 없다.