Mechanical rename produced by scripts/msd-rename.cjs: gsd/Gsd/GSD -> msd/Msd/MSD across contents and paths, upstream package/repo coordinates -> @golem15/msd-core and golem15com/msd-core. Deep links into upstream history, sibling upstream packages, the GSD-2 import feature, CHANGELOG.md and .changeset/ are kept as-is. Hand edits on top: MSD block-letter banner and logos, LICENSE copyright line, package/plugin identity, regenerated lockfile, install-tree fixtures, derived registries and benchmark baseline; migration checksum baseline re-locked (MSD keeps its own install state, so no install had applied the old sums); sort-order and regex-escaped expectations in tests adjusted.
13 KiB
MSD Core의 다중 에이전트 오케스트레이션
설명 — 이 문서는 MSD Core가 다중 에이전트 오케스트레이션을 중심으로 설계된 이유와 구성 요소들이 어떻게 맞물리는지를 설명한다. 단계별 가이드가 아니다. 설정에 대해서는 모델 프로필 설정과 설정 레퍼런스를 참조하라. 전체 에이전트 목록은 인벤토리를 참조하라.
이 설계가 해결하는 문제
AI 코딩 에이전트는 저하된다. 모델이 나빠지기 때문이 아니라 컨텍스트 윈도우가 채워지기 때문이다. 대화가 길어질수록 초반의 결정들과 코드가 중간 단계들의 노이즈에 밀려나거나 희석된다. 복잡한 작업에서 다섯 번째 파일을 작성할 때쯤 에이전트는 첫 번째 메시지에서 명시된 제약 조건을 이미 잊었을 수도 있다. 이를 컨텍스트 부패라고 부르기도 한다.
MSD Core의 다중 에이전트 설계는 그 문제에 대한 직접적인 대응이다. 하나의 장시간 실행 에이전트가 전체 세션을 담당하는 대신, 얇은 오케스트레이터가 신선한 200K 토큰 컨텍스트 윈도우와 자신의 특정 작업을 수행하는 데 필요한 결과물만 갖고 시작하는 단수명 전문화 에이전트들을 생성한다. 오케스트레이터 자신은 절대 무거운 작업을 하지 않는다; 컨텍스트를 로드하고, 적합한 에이전트를 생성하고, 결과를 수집하고, .planning/의 공유 상태를 업데이트한다.
오케스트레이터 → 에이전트 패턴
msd-core/workflows/의 모든 워크플로우는 동일한 형태를 따른다:
오케스트레이터 (워크플로우 .md 파일)
│
├── 컨텍스트 로드
│ msd-tools.cjs init <workflow> <phase>
│ → JSON: 프로젝트 정보, 설정, 상태, 단계 상세
│
├── 모델 해결
│ msd-tools.cjs resolve-model <agent-name>
│ → opus | sonnet | haiku | inherit
│
├── 전문화 에이전트 생성 (Task/SubAgent 호출)
│ ├── 에이전트 정의 (agents/*.md)
│ ├── 컨텍스트 페이로드 (init JSON)
│ ├── 모델 할당
│ └── 도구 권한
│
├── 결과 수집
│
└── 상태 업데이트
msd-tools.cjs state update / state patch / state advance-plan
오케스트레이터는 의도적으로 얇다. 도메인에 대해 추론하지 않고, 코드를 작성하지 않으며, 다음 단계로 라우팅하는 것 이상으로 결과를 해석하지 않는다. 그 경계는 각 계층의 책임을 명확하게 유지하고 오케스트레이터의 컨텍스트가 도메인 노이즈를 축적하는 것을 방지한다.
에이전트 목록
MSD Core의 에이전트들은 리서치 → 계획 → 실행 → 검증 파이프라인에 매핑되는 기능 범주로 나뉜다:
| 범주 | 에이전트 | 일반적인 병렬성 |
|---|---|---|
| 리서처 | msd-project-researcher, msd-phase-researcher, msd-ui-researcher, msd-advisor-researcher |
4개 병렬 (스택, 기능, 아키텍처, 함정) |
| 합성기 | msd-research-synthesizer |
리서처 완료 후 순차적 |
| 플래너 | msd-planner, msd-roadmapper |
순차적 |
| 검사기 | msd-plan-checker, msd-integration-checker, msd-ui-checker, msd-nyquist-auditor |
순차적, 최대 3번 수정 반복 |
| 실행기 | msd-executor |
웨이브 내 병렬, 웨이브 간 순차적 |
| 검증기 | msd-verifier |
모든 실행기 완료 후 순차적 |
| 매퍼 | msd-codebase-mapper |
4개 병렬 하위 프로브 |
| 감사기 | msd-ui-auditor, msd-security-auditor |
순차적 |
각 에이전트 정의(agents/*.md)는 허용된 도구 접근, 목적, 터미널 출력 색상을 선언한다. 파일을 읽고 단일 출력 문서를 작성하기만 하면 되는 에이전트는 정확히 그런 권한만 받는다 — Bash 실행 없음, 광범위한 상태 접근 없음. 그 제약은 의도적이다: 에이전트가 예상치 못하게 행동할 경우 영향 범위를 작게 유지한다.
전체 31개 에이전트 목록은 인벤토리를 참조하라.
웨이브 기반 병렬 실행
다중 에이전트 설계의 가장 눈에 띄는 표현은 /msd-execute-phase가 서로 의존관계가 있는 계획들의 집합을 처리하는 방식이다.
실행기를 생성하기 전에 오케스트레이터는 웨이브 분석을 수행한다: 각 PLAN.md 파일의 의존성 선언을 읽고 계획들을 웨이브로 그룹화한다. 선언된 의존성이 없는 계획들은 웨이브 1을 형성하고 병렬로 실행된다. 웨이브 1에 의존하는 계획들은 웨이브 2를 형성하고, 계속해서 이어진다.
계획 01 (의존성 없음) ─┐
계획 02 (의존성 없음) ─┤─── 웨이브 1 (병렬)
계획 03 (의존: 01) ─┤─── 웨이브 2 (웨이브 1 대기)
계획 04 (의존: 02) ─┘
계획 05 (의존: 03, 04) ─── 웨이브 3 (웨이브 2 대기)
웨이브 내 각 실행기는:
- 신선한 컨텍스트 윈도우(200K 토큰, 또는 지원 모델에서 최대 1M)를 받는다
- 담당하는 특정
PLAN.md를 받는다 - 프로젝트 컨텍스트(
PROJECT.md,STATE.md)를 받는다 - 단계 컨텍스트(가용한 경우
CONTEXT.md,RESEARCH.md)를 받는다 - 완료 시 원자적 git 커밋을 생성한다
- 만들어진 것을 설명하는
SUMMARY.md를 작성한다
웨이브의 모든 실행기가 완료된 후, 오케스트레이터는 전체 웨이브에 대해 한 번 사전 커밋 훅을 실행한다. 실행기는 여러 에이전트가 병렬로 커밋할 때의 빌드 잠금 경합(예: Rust 프로젝트의 Cargo 잠금 충돌)을 방지하기 위해 --no-verify로 커밋한다. 따라서 훅은 커밋당 한 번이 아닌 웨이브당 한 번 실행된다.
병렬 커밋 안전성
여러 실행기가 동시에 실행될 때 쓰기 충돌을 방지하는 두 가지 메커니즘이 있다:
-
STATE.md에 대한 원자적 잠금 —STATE.md에 대한 모든 쓰기는O_EXCL원자적 생성을 사용하는 잠금파일(STATE.md.lock)을 사용한다. 이는 두 에이전트가 각각 파일을 읽고, 서로 다른 필드를 수정하고, 나중에 쓰는 쪽이 먼저 쓴 쪽의 변경 사항을 덮어쓰는 읽기-수정-쓰기 경합 조건을 방지한다. 오래된 잠금(10초 이상)은 자동으로 지워진다. -
웨이브당 훅 실행 — 각 실행기가 사전 커밋 훅을 독립적으로 실행하는 대신(공유 빌드 결과물에 파일 수준 경합을 유발할 수 있음), 오케스트레이터는 모든 웨이브가 완료된 후 한 번
git hook run pre-commit을 실행한다.
대형 윈도우 모델을 위한 적응형 컨텍스트 보강
표준 200K 컨텍스트 윈도우는 실행기가 단일 집중된 계획을 구현하기에 충분하다. 구성된 context_window가 500K 토큰 이상인 경우(예: Opus 4.6 또는 Sonnet 4.6을 1M 클래스 모드로 사용할 때), 오케스트레이터는 자동으로 표준 윈도우에 들어가지 않는 추가 컨텍스트로 서브에이전트 프롬프트를 보강한다:
- 실행기 에이전트는 이전 웨이브의
SUMMARY.md파일들과 단계CONTEXT.md/RESEARCH.md를 받아 단계 내 교차 계획 인식을 갖는다 - 검증기 에이전트는 모든
PLAN.md,SUMMARY.md,CONTEXT.md파일들과REQUIREMENTS.md를 받아 이력 인식 검증을 할 수 있다
이 보강은 config.json의 context_window 값에 조건부이다. 표준 윈도우 설정에서는 캐시 친화적 순서로 토큰 효율성을 최대화하는 잘린 버전의 프롬프트를 사용한다.
이 설계의 이유 — 컨텍스트 엔지니어링과의 연결
오케스트레이터 → 에이전트 패턴은 더 광범위한 컨텍스트 엔지니어링 접근 방식의 일부로서만 의미가 있다: AI 에이전트의 컨텍스트 윈도우에 들어가는 것이 모델 등급이나 프롬프트 품질만큼 중요하다는 아이디어. 전체 내용은 컨텍스트 엔지니어링을 참조하라.
다중 에이전트 오케스트레이션은 두 가지 방식으로 컨텍스트 엔지니어링을 구현한다:
컨텍스트 격리. 각 에이전트는 필요한 것만 받는다. 리서처는 프로젝트 설명과 도메인 질문들을 받는다; 전체 계획 이력은 받지 않는다. 검증기는 모든 계획과 요약을 받는다; 원시 리서치는 받지 않는다. 격리는 각 에이전트의 컨텍스트를 다른 파이프라인 단계들의 노이즈로 희석되지 않고 신호로 밀도 있게 유지한다.
세션 간 컨텍스트 위생. 모든 상태가 사람이 읽을 수 있는 마크다운과 JSON으로 .planning/에 저장되기 때문에(에이전트의 컨텍스트 윈도우가 아닌), MSD 워크플로우는 컨텍스트 리셋(/clear), 탭 전환, 며칠간의 휴식을 견뎌낸다. 다음 에이전트는 항상 긴 대화의 재구성된 기억이 아닌 영속적이고 검증된 결과물에서 시작한다.
트레이드오프
다중 에이전트 오케스트레이션은 비용이 없지 않다.
조율 오버헤드. 각 에이전트 생성은 왕복이다: 오케스트레이터가 프롬프트를 형식화하고, 컨텍스트를 넘기고, 서브에이전트가 완료될 때까지 기다리고(일반적으로 1-5분), 결과를 파싱해야 한다. 하나의 컨텍스트에서 작동하는 단일 능력 있는 에이전트는 단순한 작업에서 더 빨리 완료될 것이다. MSD는 의존성이 허용되는 모든 곳에서 병렬성을 기본값으로 만들어 이를 완화한다 — plan-phase의 네 리서처들은 순차적이 아닌 동시에 실행된다.
실행 중 불투명성. 서브에이전트가 실행되는 동안 그 작업은 부모 세션에서 보이지 않는다. 실시간 진행 스트림이 없다. 이것은 신선한 컨텍스트 설계의 의도적인 결과이다: 서브에이전트가 자체 컨텍스트 윈도우에서 작동하고 있다. 오케스트레이터는 생성 라인에 활성 표시를 보여줌으로써("서브에이전트에서 실행됨 — 반환될 때까지 출력 없음") 기대치를 설정한다.
컨텍스트 스티칭 비용. 각 에이전트에 적합한 결과물들을 패키징하려면 오케스트레이터가 컨텍스트 페이로드를 조립하고 전송하는 데 토큰을 소비해야 한다. 이것이 격리의 비용이다. msd-tools.cjs init 핸들러는 완전성과 토큰 예산의 균형을 맞추는 JSON 페이로드를 생성하며, 반복 호출에서 캐시에 도달하도록 캐시 친화적 순서를 적용한다.
모델 비용 증폭. Opus 등급으로 다섯 개의 에이전트를 병렬로 실행하는 것은 하나를 실행하는 것보다 더 비용이 많이 든다. 모델 프로필 시스템(model_profiles.md, model-profiles.cjs에 의해 에이전트별로 해결됨)을 사용하면 덜 중요한 에이전트에 더 저렴한 등급을 할당할 수 있다. dynamic_routing 기능은 모든 에이전트를 더 저렴한 등급에서 시작하고 소프트 실패 시에만 에스컬레이션함으로써 비용을 더 줄여준다. 전체 옵션은 설정을 참조하라.
이런 비용의 대가로 이 설계는 대형 단계에서의 일관된 품질을 제공한다. 400줄 계획의 열 번째 파일을 작성하는 실행기는 컨텍스트가 신선하기 때문에 저하되지 않는다. 스무 개의 요구 사항을 확인하는 검증기는 처음 열 개를 잊지 않는다. 왜냐하면 대화 이력이 아닌 구조화된 입력으로 모두 받았기 때문이다.