Claude Code Custom Agent 설계 여정: Agent 중심에서 Task 중심으로
Source: Dev.to
들어가며
Design Doc 작성을 자동화하고 싶었다.
디자인 시안을 확인하고, 기획서를 읽고, 코드베이스를 파악해서 초안을 뽑아주는 것이 /design-doc Command의 목표였다.
Command는 금방 만들었지만, 그 다음 단계인 Custom Agent 설계가 문제였다. 두 번의 설계 전환과 여러 실패 끝에 현재 구조에 도달했다. 이 글은 그 여정이다.
초기 구조: 고정된 4개 Agent 병렬 호출
/design-doc 실행
↓
Main Agent가 4개 Agent 병렬 호출
├── code-researcher (코드베이스 분석)
├── doc-researcher (내부 문서 분석)
├── external-researcher (외부 도구 전부)
└── app-researcher (실제 앱 동작 확인)
↓
결과 조합 → Design Doc 초안
- 구조가 단순하고 역할이 명확해 보였다.
code-researcher가 Opus 모델로 실행되면서 전체가 지연됐다. 다른 Agent들은 이미 끝났는데 하나를 기다리고 있었다.- 입력에 포함되지 않은 소스도 조사하려 했다. 필요 없는 일을 하고 있었다.
external-researcher하나가 디자인 도구, 문서 도구, 웹을 전부 처리해야 했다. 각 플랫폼의 특성이 달라 하나의 프롬프트에 다 담으려니 비대해졌다.
전환: Task 중심 설계
입력: "A 기능 개선. 디자인: ..., 기획서: ..."
↓
Main Agent가 입력 분석 → 필요한 Task 도출
↓
Research Tasks (필요한 것만):
├── design-review
├── feature-spec
└── code-module-analysis
↓
Design Task → Write Task → 완료
핵심 변화
- Task가 작고 구체적
- 필요한 Task만 선택적으로 실행
- Agent는 Task 수행을 위한 도구
external-researcher도 분리했다.
external-researcher (1개)
↓ 분리
design-researcher (디자인 도구)
docs-researcher (문서 도구)
web-researcher (웹)
각 소스의 특성이 다르다
| 소스 | 특징 |
|---|---|
| 디자인 도구 | 빠른 분석 vs 상세 분석 전략 필요 |
| 문서 도구 | 인증 방식, 페이지 구조 파악 방식이 다름 |
| 웹 | MCP가 아닌 기본 도구 사용 |
실패 처리 차이
- 디자인 도구 권한 없음 → 공유 설정 확인 요청
- 문서 도구 접근 불가 → 토큰 확인 요청
- 웹 타임아웃 → 다른 URL 시도
URL 패턴에 따른 자동 라우팅
| URL 패턴 | 담당 Agent |
|---|---|
| 디자인 도구 URL | design-researcher |
| 문서 도구 URL | docs-researcher |
| 그 외 | web-researcher |
새로운 문제: Agent 실패 알림
MCP 연결이 끊기거나 권한이 없을 때 Agent가 단순히 "접근할 수 없습니다." 라고 반환했다. Command는 재시도 가능한지, 포기해야 하는지 알 수 없었다. 모든 외부 연동에서 같은 문제가 발생했다.
상태 태그 도입
Agent가 결과물 최상단에 상태를 명시하도록 설계했다.
[BLOCKED:mcp-disconnected]
분석 대상
- URL: https://…
실패 사유
MCP 연결이 끊어졌습니다. 연결 확인 후 재시도해주세요.
상태 태그 정의
| 상태 | 설명 | Command 후처리 |
|---|---|---|
[SUCCESS] | 정상 완료 | 다음 단계 진행 |
[BLOCKED:reason] | 사용자 조건 필요 | 사용자에게 전달, 대기 |
[PARTIAL] | 부분 완료 | 결과 활용, 미완료 명시 |
[FAILED:reason] | 복구 불가 | 사용자에게 알림 |
Blocked 사유 코드: auth-error, permission-denied, invalid-input, mcp-disconnected
핵심 규칙: [BLOCKED:*]는 Agent가 임의로 스킵하지 않는다. 반드시 호출자에게 전달한다.
구성 요소
Agent
- Output 형식 정의
- 실행 로직
- Quality Gate
- 상태 반환
Command
- 워크플로우 정의
- Agent 호출 순서 및 경로 지정
- 결과 조합
- 상태별 후처리
Agent가 하지 않는 것
- 저장 경로 결정 (호출자가 지정)
Command라는 개념 언급 (호출자 독립적)- 다음 단계 결정 (상태만 반환)
이유: Agent는 Command가 호출할 수도, 사용자가 직접 호출할 수도, 다른 Agent가 호출할 수도 있다. 호출자가 누구든 동일하게 동작해야 한다.
섹션 정의 (6‑Section)
| 섹션 | 목적 | 비고 |
|---|---|---|
| YAML Frontmatter | name, description, tools, model | description이 자동 위임 판단에 사용됨 |
| 역할 정의 | 한 줄로 핵심만 | |
| 입력 | 필수/선택 파라미터 | 6‑Section에 없음 |
| 실행 | 단계별 절차 (도구가 많으면 전략 포함) | |
| Output | 상태 태그 + 결과 템플릿 (상태 태그 최상단) | |
| Quality Gate | 자가 검증 체크리스트 | |
| 실패 시 | 상황별 상태 코드와 대응 | 6‑Section에 없음 |
| 주의 사항 | 자주 하는 실수 방지 | 6‑Section에 없음 |
기존 6‑Section vs 8‑Section 비교
| 항목 | 6‑Section | 8‑Section |
|---|---|---|
| Role Definition | 역할 정의 | 역할 정의 |
| Expertise Areas | ❌ (전문 Agent엔 불필요) | ❌ |
| Workflow | 실행 | 실행 |
| Communication Protocol | ❌ (개선 예정) | ❌ |
| Output Format | Output (상태 태그 추가) | Output |
| Quality Checklist | Quality Gate | Quality Gate |
| 입력 | ❌ | ❌ |
| 실패 시 | ❌ | ❌ |
| 주의 사항 | ❌ | ❌ |
아직 구현되지 않은 부분: Communication Protocol
현재는 상태 태그로 단방향 반환만 한다:
Command → Agent → [SUCCESS] 결과
향후 구조화된 프로토콜을 추가하면 더 유연한 통신이 가능해질 것이다:
- 상태 보고에 메타 정보 추가
- Agent 간 위임 요청
배운 점
- Agent 중심보다 Task 중심: Agent 단위로 생각하면 역할이 비대해진다. Task 단위로 쪼개라.
- 범용보다 전문화: 플랫폼 특성이 다르면 분리하라.
- 상태 태그로 소통: Agent가 막히면 상태로 알려야 한다.
- 책임 분리: Agent는 상태만 반환하고, 후처리는 호출자가 담당한다.
- 입력과 실패 설계: 6‑Section엔 없지만, 외부 연동 Agent엔 필수다.
- 커뮤니티 참고, 맹신 금지: 내 상황에 맞게 조정하라.