로컬에서 AI 멀티 에이전트 만들기 (1) — 설계와 환경 구성
시리즈 (3편 중 1편)
편 제목 핵심 → 1편 설계와 환경 구성 AgentEngine 추상화, CLI/API 팩토리 2편 에이전트 구현 EventBus, Orchestrator, 3개 에이전트 3편 실전과 확장 실행 결과, 피드백 루프, 비용 최적화
“AI한테 코드 짜달라고 하면 되는데, 에이전트를 왜 여러 개 돌려?”
나도 처음엔 그렇게 생각했다. Claude에게 “TODO 앱 만들어줘” 하면 한 번에 끝나니까. 그런데 codemon-make를 7에이전트로 운영하면서 생각이 바뀌었다.

단일 에이전트의 한계
하나의 에이전트에 모든 것을 맡기면:
- 컨텍스트 오염: 기획, 코딩, 리뷰를 한 세션에서 하면 뒷부분으로 갈수록 품질이 떨어진다
- 디버깅 불가: 어디서 잘못됐는지 알 수 없다. 계획이 나빴나, 코드가 나빴나?
- 모델 낭비: 간단한 계획에도 비싼 모델을 쓰고, 코드 작성에도 같은 모델을 쓴다
프로덕션에서 7에이전트를 돌려보니 답이 보였다. 역할을 나누면 각 단계를 독립적으로 개선할 수 있다.
아키텍처: 3에이전트 파이프라인
codemon-make의 7에이전트에서 핵심 패턴만 뽑으면 3개로 충분하다.
사용자: "React로 TODO 앱 만들어줘"
│
▼ task.created
│
├─ PlannerAgent → 구현 계획 JSON
│
▼ plan.completed
│
├─ CoderAgent → 실제 코드 작성
│
▼ code.completed
│
├─ ReviewerAgent → 리뷰 + 점수
│
▼ review.completed → 결과 출력이 파이프라인을 지탱하는 4가지 핵심 패턴:
| 패턴 | 역할 | 구현 |
|---|---|---|
| AgentEngine | LLM 호출 추상화 | CLI / API 교체 가능 |
| EventBus | 에이전트 간 통신 | Redis pub/sub |
| Orchestrator | 이벤트 → 큐 라우팅 | BullMQ 큐 연결 |
| Worker | 큐 소비 + 에이전트 실행 | BullMQ Worker |
환경 설정
레포 클론
git clone https://github.com/codemon-ai/agent-basic.git
cd agent-basic
npm installRedis 시작
docker compose up -dcompose.yml은 Redis 7 Alpine 이미지 하나:
services:
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
- redis-data:/data환경변수
cp .env.example .envENGINE_TYPE=claude-cli # 또는 anthropic-api
ANTHROPIC_API_KEY=sk-ant-... # API 엔진 사용 시
REDIS_URL=redis://localhost:6379AgentEngine: LLM 호출 추상화
멀티 에이전트의 첫 번째 설계 결정은 **“LLM을 어떻게 호출할 것인가”**다.
codemon-make에서는 Claude CLI와 Anthropic API를 모두 쓴다. CLI는 파일 시스템 접근이 가능하고, API는 가볍고 빠르다. 이 두 가지를 하나의 인터페이스로 묶었다.
// src/engines/types.ts
export interface AgentEngineResult {
result: string;
session_id: string;
num_turns: number;
duration_ms: number;
cost_usd: number;
}
export interface AgentEngineRunOptions {
cwd: string;
timeoutMs?: number;
disallowedTools?: string[];
onProgress?: (message: string) => void;
}
export interface AgentEngine {
name: string;
run(prompt: string, options: AgentEngineRunOptions): Promise<AgentEngineResult>;
}핵심은 run() 하나. 프롬프트를 넣으면 결과가 나온다. CLI든 API든 같은 인터페이스.
Claude CLI 엔진
// src/engines/claude-cli-engine.ts (핵심 부분)
const child = spawn("claude", [
"-p",
"--dangerously-skip-permissions",
"--output-format", "json",
], { cwd, env });
// 프롬프트는 stdin으로 전달 (ARG_MAX 회피)
child.stdin.write(prompt);
child.stdin.end();CLI 엔진의 장점: Claude Code의 도구(파일 생성, Bash 실행)를 그대로 쓸 수 있다. CoderAgent에 이상적.
Anthropic API 엔진
// src/engines/anthropic-api-engine.ts (핵심 부분)
const stream = this.client.messages.stream({
model: this.model,
max_tokens: 4096,
messages: [{ role: "user", content: prompt }],
});
const response = await stream.finalMessage();API 엔진의 장점: 빠르고, 비용 예측이 쉽다. PlannerAgent, ReviewerAgent에 적합.
팩토리 패턴
// src/engines/index.ts
export function createEngine(type: EngineType, options?): AgentEngine {
switch (type) {
case "claude-cli": return new ClaudeCliEngine();
case "anthropic-api": return new AnthropicApiEngine(options?.apiKey);
}
}.env에서 ENGINE_TYPE만 바꾸면 전체 시스템의 엔진이 교체된다.

다음 편에서
에이전트 엔진과 환경 구성을 마쳤다. 2편에서는 이 엔진 위에 EventBus, Orchestrator, 그리고 3개 에이전트를 구현한다.
→ 다음: 2편 — 에이전트 구현