docs(readme): review fixes (38a64423 / c5a8813c / 7d29a620) and README.ko.md in step
- install.sh: what it actually checks; it writes a starter .mam.env with MQTT_BROKER=localhost (broker.hivemq.com is only the unset fallback); install_mam.sh is a separate installer. - Security: tokens exist only when given or when the broker has TLS or a username (PoC: no signature check); the remote dispatch carries the token. - Server isolation: create defaults to a workspace-named server; the shim bootstraps only a named server and never when MAM_NO_AUTOSTART=1 (status/monitor); restore-off is the normal path, with a warning fallback. - Loop: the selected reviewers must all pass; no reviewer option means a creator self-review. - Interpreter order with the PATH python3 fallback; exit 5 also covers target_not_found; two layers with their own registries; test isolation stated as sandboxes plus after-run guards; quick start uses named sessions. - README.ko.md now mirrors README.md. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VCgu9Fa9iT7TbJUSzdq4Ff
This commit is contained in:
1 parent
20b1014717
commit
423abc7844
2 files changed
+215
-190
No files matched your search
+191
-168
@@ -1,6 +1,6 @@
|
||||
# herdr-agent-orchestration (다중 에이전트 Herdr 오케스트레이션 및 메시징 백플레인)
|
||||
|
||||
Herdr와 MQTT 브로커를 기반으로 구축된 고신뢰성 **다중 에이전트 오케스트레이션 및 메시징 백플레인** 프레임워크입니다. `claude`, `agy`, `hermes`, `grok`, `opencode`, `codex` 등 다중 LLM 백엔드 에이전트 전반에 걸쳐 장시간 수행되는 작업(코드 생성, 리팩토링, 보안 검토 등)을 조정, 격리 및 감사할 수 있도록 설계되었습니다.
|
||||
[herdr](https://herdr.dev)와 MQTT 위에 만든 **다중 에이전트 오케스트레이션·메시징 백플레인**입니다. 장시간 실행되는 코딩 에이전트(`claude`, `agy`, `hermes`, `grok`, `opencode`, `codex`)를 격리된 herdr pane 에서 돌리고, 작업을 추적되는 잡으로 위임하며, 모든 리뷰어가 통과시킬 때까지 planner / creator / reviewer 루프를 돌립니다.
|
||||
|
||||
[](VERSIONS.md)
|
||||
|
||||
@@ -8,212 +8,235 @@ Herdr와 MQTT 브로커를 기반으로 구축된 고신뢰성 **다중 에이
|
||||
|
||||
## 🚀 개요
|
||||
|
||||
최근의 에이전트 워크플로우는 세션 타임아웃, 프로세스 격리 부재, 터미널 뷰포트 잘림(스크롤백 한계로 인한 디버그 로그 유실), 복잡한 동시성 경쟁 등의 문제를 자주 겪습니다.
|
||||
긴 에이전트 작업은 정해진 방식으로 깨집니다. 터미널과 함께 세션이 죽고, 한 pane 에 잡 두 개가 들어가고, 오케스트레이터는 바쁜 에이전트와 죽은 에이전트를 구분하지 못하고, 리뷰는 읽은 뒤에 바뀐 코드를 승인합니다. Multi-Agent Mux(MAM)는 이를 다음으로 막습니다.
|
||||
|
||||
**herdr-agent-orchestration**은 다음과 같은 솔루션을 통해 이를 해결합니다:
|
||||
1. **Herdr 기반 프로세스 격리:** 개별적으로 격리된 herdr 환경 내부에 에이전트 CLI 세션을 띄워, 백그라운드에서 끊김 없이 장시간 작업이 영속되도록 보장합니다. 백그라운드 데몬 서버는 독립된 OS 세션/프로세스 그룹(`start_new_session=True`)으로 분리되어 부모 셸의 시그널 브로드캐스트로부터 안전하게 격리됩니다.
|
||||
2. **비동기 이벤트 기반 아키텍처:** MQTT 브로커를 메시징 백플레인으로 활용하여, 에이전트 간 상태 전이 단계(`started`, `progress`, `completed`, `error`)를 긴밀하게 제어 및 조정합니다.
|
||||
3. **Multi-Agent Mux (MAM):** 파일 기반의 어드바이저리 락(`fcntl`) 및 SQLite WAL 데이터베이스(`.mam/agent-sessions.db`)를 결합하여, 동시성 작업 선점 경쟁을 방지하고 에이전트 세션의 라이프사이클을 드리프트 없이 관리합니다.
|
||||
4. **리뷰어 기반 고신뢰 검증 루프:** Worker 에이전트가 구현한 코드 변경 사항에 대해 상이한 강점을 지닌 전문 검증 에이전트(Claude, Hermes, Grok, OpenCode, Codex 등)들로부터 최종 `PASS` 판정을 획득한 뒤 머지하도록 교차 검증 루프를 자동화합니다.
|
||||
1. **격리되고 재개 가능한 에이전트 세션.** 에이전트마다 자기 herdr pane 에서 돌고, 보통 워크스페이스 전용 herdr 서버를 씁니다. 세션은 대화 ID 와 함께 `.mam/agent-sessions.yaml`(SQLite 백업)에 기록되므로, 멈춘 에이전트를 나중에 같은 대화로 재개할 수 있습니다.
|
||||
2. **화면이 아니라 이벤트로 판정하는 잡.** 위임 잡은 레지스트리 레코드와 MQTT 이벤트 흐름(`started`, `progress`, `completed`, `error`)입니다. 에이전트는 정해진 시간 안에 프롬프트 수신을 알리고, 일하는 동안 heartbeat 를 보내야 합니다. 잡을 닫는 것은 프로토콜 이벤트나 시간 초과뿐이며, 터미널을 읽어 판정하지 않습니다.
|
||||
3. **세션당 한 번에 잡 하나.** 프롬프트를 넣기 전에 디스패처가 레지스트리로 그 세션의 앞선 잡(온보딩 포함)이 끝나기를 기다립니다. pane 배치는 herdr 서버마다 직렬화되어, 동시에 실행한 `create` 가 같은 pane 을 차지하지 않습니다.
|
||||
4. **근거를 고정한 리뷰 루프.** `multi-agent-mux-loop` 는 변경을 선택한 리뷰어에게 보내고, 그 전원의 `PASS` 를 요구합니다. 리뷰어는 `--reviewer` 로 지정하거나 `--all-reviewer` 로 실행 중인 리뷰어 전원을 고르며, 둘 다 없으면 creator 가 스스로 리뷰합니다. `--worktree`/`--base` 를 쓰면 리뷰 라운드마다 소스 스냅샷에 묶이며, 라운드 중 소스가 바뀌면 그 승인은 버리고 다시 리뷰합니다.
|
||||
|
||||
---
|
||||
|
||||
## 🛠️ 핵심 스킬 및 구조
|
||||
## 📦 설치 및 설정
|
||||
|
||||
모든 오케스트레이션 스킬들은 `.agents/skills/` 디렉터리 하위에 정의되어 있습니다:
|
||||
아무 워크스페이스 디렉터리에서 MAM 을 설치합니다:
|
||||
|
||||
* **`multi-agent-mux-create`**: 격리된 herdr 세션을 생성하고 특정 에이전트 CLI를 백그라운드에서 구동합니다. 프로세스 PID 캡처, 메타데이터 레지스트리 업데이트 및 에이전트 인증 검증을 처리합니다.
|
||||
* **`multi-agent-mux-stop`**: 에이전트 CLI 세션을 정상 종료 키 입력(`/exit` 또는 `Exit`)을 통해 안전하게 닫고, 격리된 대화 히스토리 및 데이터베이스 로그를 삭제(purge)하는 클린업 작업을 수행합니다.
|
||||
* **`multi-agent-mux-resume`**: 디스크 또는 캐시에서 특정 워크스페이스의 세션 UUID를 조회하여 기존 대화 상태(`claude -r <uuid>`, `agy --conversation <uuid>`, `hermes --resume <uuid>`, `grok --resume <uuid>`, `opencode --session <uuid>`, `codex resume <uuid>`) 그대로 세션을 복구하고 재개합니다.
|
||||
* **`multi-agent-mux-status`**: 활성화된 모든 세션의 실시간 작동 상태를 쿼리하여 PID 정합성, 실행 명령 포맷, herdr 실제 상태와 데이터베이스 간의 동기화 드리프트를 감지합니다.
|
||||
* **`multi-agent-mux-monitor`**: 백그라운드 Reconcile 프로세스로 실행되어, 실시간 herdr 세션 변화를 모니터링하고 `.mam/agent-sessions.yaml` 메타데이터 파일에 상태를 동기화합니다.
|
||||
* **`multi-agent-mux-delegate-job`**: 태스크를 비동기식 독립 잡으로 위임 및 관리하는 핵심 모듈입니다 (본체 구현은 `.agents/skills/lib_py/delegation/`에 위치하며, `scripts/*.py`는 하위 호환 shim):
|
||||
* `registry.py`: 파일 락(`fcntl`)을 활용해 경쟁 조건 없이 잡을 원자적으로 등록 및 점유(claim)합니다.
|
||||
* `job_subscriber.py`: MQTT 백플레인 채널을 구독하여 실시간 상태 이벤트를 수집하고 이를 감사 로그(audit trail)에 기록합니다.
|
||||
* `publish_event.py`: 실행 상태 전환 및 세부 에러 내용을 워크스페이스 스크립트에서 백플레인으로 발행합니다.
|
||||
* `mqtt_common.py`: 브로커 접속 규칙, 크레덴셜 인증 및 HMAC 서명 기능을 공통 관리합니다.
|
||||
* **`multi-agent-mux-loop`**: Planner, Creator, Reviewer 3자 간의 자율적인 계획-실행-교차검증 반복 순환 루프를 구동합니다 (Python 루프 런타임 `lib_py.loop`, eager-import 불변 런타임, strict verdict parser 기반).
|
||||
* **`multi-agent-mux-orc-onboard`**: 오케스트레이터 UUID를 레지스트리에 격리 등록하여 서브 에이전트 자동 탐색 오염을 방지합니다.
|
||||
|
||||
---
|
||||
|
||||
## 📐 전체 아키텍처 구성 (Big-Picture Architecture)
|
||||
|
||||
이 시스템은 크게 두 가지 계층(Layer)을 통해 다중 워크스페이스에서 작동하는 LLM 에이전트들을 조율합니다:
|
||||
|
||||
1. **Layer A — Herdr 오케스트레이션 (lib.sh + status/resume/stop/create)**: 워크스페이스별 에이전트 세션을 독립된 herdr 인스턴스로 분리 실행하고, `.mam/agent-sessions.yaml` 및 SQLite 데이터베이스(`.mam/agent-sessions.db`)를 통해 에이전트 세션 메타데이터의 단일 참조 지점(Single Source of Truth)을 유지합니다.
|
||||
2. **Layer B — 비동기 잡 위임 (delegate-job)**: 에이전트에 특정 태스크를 전송하고 비동기 이벤트 채널(MQTT)을 통해 진행 상황과 완료 여부를 모니터링합니다.
|
||||
|
||||
두 레이어는 파일 I/O 처리를 위한 하나의 핵심 관문인 `lib.sh::atomic_dump_yaml`을 공유합니다. 모든 YAML/DB 쓰기 작업은 SQLite 데이터베이스 트랜잭션 락과 데이터 스키마 유효성 검증을 거칩니다.
|
||||
|
||||
### 데이터 흐름 개요 (Data Flow)
|
||||
|
||||
```text
|
||||
+-----------+ register_job +-------------------+
|
||||
| delegator | ---------------> | .mam/jobs/<id>.json| <-- 실시간 잡 정보
|
||||
+-----------+ +---------+---------+
|
||||
|
|
||||
| atomic rename + fsync
|
||||
v
|
||||
+-----------------+
|
||||
| audit log | <-- 추가 전용
|
||||
| .mam/delegate_ | events.ndjson
|
||||
| job_logs/<id>/ |
|
||||
+--------+--------+
|
||||
^
|
||||
| (최선 노력 미러링)
|
||||
|
|
||||
+-----------+ publish_event +-----+-----+ +---------+
|
||||
| agent | ---------------> | MQTT broker | <--- | monitor |
|
||||
| (claude) | +-------------+ +----+----+
|
||||
+-----------+ |
|
||||
^ v
|
||||
| 구독자(subscriber) atomic_dump_yaml
|
||||
| (job_subscriber.py) (.mam/agent-sessions.yaml)
|
||||
| ^
|
||||
+-------- 위임 대기 영역 -----------------+ |
|
||||
+---+---+
|
||||
| reconcil|
|
||||
| e.sh |
|
||||
+--------+
|
||||
```bash
|
||||
curl -fsSL https://git.godopu.com/tmpl/multi-agent-mux/raw/branch/main/deploy/install.sh | bash
|
||||
```
|
||||
|
||||
### 🔒 Herdr 서버 격리 (Herdr Server Isolation)
|
||||
로컬 클론에서는:
|
||||
|
||||
에이전트 세션 간의 충돌 및 시스템 전역 herdr 프로세스와의 혼선을 막기 위해 독립된 서버 소켓 환경을 보장합니다:
|
||||
* **워크스페이스별 심(Shim):** `_init_herdr_isolation` 및 `_resolve_real_herdr_path` 함수가 `/tmp/multi-agent-herdr-shim/<HERDR_SERVER_NAME>/herdr` 경로에 독립된 심 디렉터리를 구성하고, 일반 herdr 명령 실행 시 자동으로 `herdr -L <server>` 형태의 독립 소켓 서버를 사용하게 만듭니다.
|
||||
* **PATH 환경변수 변조:** 자식 프로세스를 생성할 때 `PATH` 변수 맨 앞에 심 디렉터리 경로를 삽입합니다. 이로 인해 에이전트의 내부 셸에서 수행되는 모든 `herdr` 명령어는 해당 격리 서버 소켓으로 강제 제약됩니다.
|
||||
* **환경 복구:** `HERDR_SERVER_NAME`을 `default`로 설정하는 경우 PATH 오버라이드가 정리되고 기본 전역 herdr 서버를 사용하게 됩니다.
|
||||
```bash
|
||||
bash deploy/install.sh
|
||||
```
|
||||
|
||||
### 🛡️ 동시성 설계 및 쓰기 직렬화
|
||||
`install.sh` 는 여러 번 실행해도 안전합니다. 하는 일은 다음과 같습니다.
|
||||
- herdr 와 Python 3.9+ 가 설치돼 있는지, 시스템 `python3` 에 PyYAML 이 있는지 확인합니다.
|
||||
- `.agents/` 와 `.mam.env.example` 을 워크스페이스에 복사합니다.
|
||||
- `.venv` 를 만들고 `paho-mqtt`·PyYAML 을 설치합니다.
|
||||
- `MQTT_BROKER=localhost` 로 된 초기 `.mam.env` 를 씁니다. 이미 있는 `.mam.env` 는 그대로 두고, 예전 `.env` 는 `.mam.env` 로 이름을 바꿉니다.
|
||||
- `.venv`, `.mam/`, `.mam.env` 를 `.gitignore` 에 추가합니다.
|
||||
|
||||
여러 에이전트가 동시에 실행될 때의 레이스 컨디션을 방지하기 위해 락 기반의 실행 패턴을 고수합니다:
|
||||
* **SQLite 데이터베이스 락 (`BEGIN IMMEDIATE`):** `agent-sessions.yaml` 또는 SQLite 레지스트리에 쓰기 연산을 진행할 때, 반드시 `lib.sh` 내부의 `atomic_dump_yaml` 함수를 거쳐 SQLite 데이터베이스 `.mam/agent-sessions.db`에 `BEGIN IMMEDIATE` 트랜잭션 락을 획득하도록 직렬화합니다.
|
||||
* **이중 인터프리터 분리 구조:** 라이브러리 간 의존성 충돌과 실행 도구의 안정성을 보장하기 위해 환경을 이원화했습니다. MQTT 및 비동기 작업 통신에는 가상환경 `.venv` (paho-mqtt 필요)의 Python을 사용하고, YAML 직렬화 쓰기 및 유효성 검증을 담당하는 `atomic_dump_yaml`은 시스템 전역 `python3` (시스템 PyYAML 필요)을 호출합니다.
|
||||
* **NFS 및 네트워크 파일시스템 대응:** 네트워크 디바이스(NFS, CIFS, SSHFS)에서는 파일 락(`flock`) 및 SQLite WAL 기능이 오작동할 수 있습니다. `lib.sh`는 쓰기 대상 파일시스템 경로의 마운트 타입을 체크하여, 네트워크 파일시스템 감지 시 경고 로그를 출력하고 SQLite의 저널 모드를 `WAL`에서 `DELETE`로 자동 전환해 동시성 안전을 강화합니다.
|
||||
`.mam.env` 의 `MQTT_BROKER` 를 직접 운영하는 브로커로 바꾸십시오(사설 브로커는 [MESSAGING.md](MESSAGING.md) 참고). `MQTT_BROKER` 가 아예 설정되지 않으면 코드는 공개 브로커 `broker.hivemq.com` 을 씁니다. 시험용으로는 괜찮지만 실제 작업용은 아닙니다. `deploy/generate-env.sh` 는 `.mam.env.example` 로 `.mam.env` 를 다시 만듭니다. 업데이트와 제거는 `deploy/update.sh`, `deploy/remove.sh` 입니다. `deploy/install_mam.sh` 는 로컬 클론에서 다른 디렉터리로 복사해 설치하는 별도 설치기입니다.
|
||||
|
||||
---
|
||||
|
||||
## 📐 아키텍처 및 조정 루프 (Review Loop)
|
||||
## 🛠️ 핵심 스킬
|
||||
|
||||
Project Manager(PM), Worker, Reviewer 역할 간의 협업 구조는 엄격한 교차 검증 루프를 따릅니다:
|
||||
모든 스킬은 `.agents/skills/` 아래에 있고, 각 `SKILL.md` 가 옵션과 종료 코드를 설명합니다.
|
||||
|
||||
| 스킬 | 하는 일 |
|
||||
|---|---|
|
||||
| **`multi-agent-mux-create`** | 에이전트를 herdr pane 에서 시작하고 세션을 등록합니다. `--onboard` 는 온보딩 잡이 끝날 때까지 기다립니다(실패하면 종료 코드 44, 시간 안에 끝나지 않으면 45; 세션은 남김). `scripts/worktree_prepare.sh` 는 creator 용 이슈 워크트리를 준비합니다. |
|
||||
| **`multi-agent-mux-stop`** | 세션을 정상 종료합니다. 대화 ID 를 행에 저장합니다(`status: stopped`, `resumable: true`). `--purge-conversation --yes` 는 대신 대화를 지웁니다. `scripts/worktree_remove.sh` 는 서브모듈까지 깨끗한지 확인한 뒤에만 이슈 워크트리를 지웁니다. |
|
||||
| **`multi-agent-mux-resume`** | 멈춘 세션을 저장된 대화로 되살립니다(`claude -r`, `agy --conversation`, `hermes --resume`, `grok --resume`, `opencode --session`, `codex resume`). 세션이 원래 돌던 디렉터리에서만 재개합니다. |
|
||||
| **`multi-agent-mux-status`** | 모든 세션의 읽기 전용 스냅샷: 레지스트리 상태, herdr 생존, pane 명령과 cwd, 재개 ID, 불일치(drift). |
|
||||
| **`multi-agent-mux-monitor`** | 장기 실행 조정자(`reconcile.sh --subscribe`). 잡 이벤트에 반응하고, 브로커가 죽으면 폴링으로 돌아가며, 레지스트리 불일치를 고칩니다. 예를 들어 죽은 세션을 `terminated` 로 표시하고, 레지스트리가 모르는 살아 있는 세션을 등록합니다. |
|
||||
| **`multi-agent-mux-delegate-job`** | 세션(`herdr:<name>`)이나 다른 호스트의 러너(`remote:<name>`)에 잡을 위임하고 결과를 기다립니다. [위임 계약](#-위임-계약)을 보십시오. |
|
||||
| **`multi-agent-mux-loop`** | 계획·구현·리뷰: 선택적인 planner 와 creator, 그다음 선택한 리뷰어(`--reviewer A,B`, 또는 `--all-reviewer` 로 creator 를 뺀 실행 중인 리뷰어 전원)가 모두 `PASS` 를 낼 때까지(또는 `--max-loop` 까지). 둘 다 없으면 creator 가 스스로 리뷰합니다. 루프 밖에서 끝난 작업은 `--review-only` 로 리뷰합니다. 통과한 리포트는 `.agents/reports/<session>/` 으로 옮겨 보관합니다. |
|
||||
| **`multi-agent-mux-orc-onboard`** | 오케스트레이터 자신의 세션 ID 를 등록해, 세션 탐색이 그것을 하위 에이전트로 착각하지 않게 합니다. |
|
||||
|
||||
---
|
||||
|
||||
## 📐 아키텍처
|
||||
|
||||
MAM 은 각자 레지스트리를 가진 두 계층으로 이루어집니다.
|
||||
|
||||
1. **세션 (herdr)**: `lib.sh` 와 create/stop/resume/status/monitor 스크립트가 에이전트를 돌리고, `.mam/agent-sessions.yaml`(+ `.mam/agent-sessions.db`)을 기준 기록으로 유지합니다.
|
||||
2. **잡 (위임)**: `lib_py/delegation/` 이 `.mam/jobs/<id>.json` 에 잡을 등록하고, 브리프를 주입하고, MQTT 로 잡의 이벤트를 따라갑니다. 모든 이벤트는 잡의 감사 로그 `.mam/delegate_job_logs/<id>/` 에도 덧붙여집니다.
|
||||
|
||||
```text
|
||||
+--------------+ register / pick +----------------------+
|
||||
| orchestrator | -----------------> | .mam/jobs/<id>.json | live record
|
||||
| (wrapper) | +----------+-----------+
|
||||
+------+-------+ | every transition
|
||||
| inject brief v
|
||||
v +----------------------+
|
||||
+--------------+ publish_event | .mam/delegate_job_ | append-only
|
||||
| agent pane | --------+ | logs/<id>/ | audit log
|
||||
+--------------+ | +----------------------+
|
||||
v
|
||||
+-------------+ events + retained state
|
||||
| MQTT broker | -------------------------> job_subscriber (orchestrator)
|
||||
+-------------+ -------------------------> monitor (reconcile.sh)
|
||||
|
|
||||
v
|
||||
.mam/agent-sessions.yaml / .db
|
||||
```
|
||||
|
||||
### 🔒 Herdr 서버 격리
|
||||
|
||||
- **워크스페이스 전용 서버.** `create` 는 기본으로 워크스페이스 이름(slug)을 딴 herdr 서버에서 에이전트를 돌립니다. 이 서버는 기본 herdr 와 분리된 자기 소켓을 씁니다. `--herdr-session <name>` 또는 `HERDR_SESSION_NAME` 으로 다른 이름을 고를 수 있습니다. 서버 이름은 세션 행에 기록되고, 이후 모든 명령이 그 서버로 갑니다.
|
||||
- **shim.** `lib.sh` 를 source 하면 `<workspace>/.mam/shim/herdr` 를 쓰고 `PATH` 맨 앞에 둡니다. shim 은 스크립트가 쓰는 tmux 식 명령(`new-session`, `has-session` …)을 herdr 의 에이전트 API 위에 제공합니다. 이름 있는 서버면 호출마다 `--session <server>` 를 붙이고, 그 서버가 돌고 있지 않으면 헤드리스로 시작합니다. 단 `MAM_NO_AUTOSTART=1` 이면 시작하지 않습니다. `status` 와 `monitor` 가 이 값을 설정하므로, 조회만으로 서버가 뜨는 일은 없습니다. `default` 서버 호출은 바꾸지 않고 사용자의 herdr 로 그대로 갑니다.
|
||||
- **예상치 못한 재실행 없음.** MAM 이 시작한 서버는 보통 사용자의 herdr 설정에 `resume_agents_on_restore = false` 를 더해 씁니다. 그래서 herdr 가 재시작돼도 저장된 에이전트를 권한 플래그 없이 다시 띄우지 않습니다. 이 설정을 만들 수 없으면 부트스트랩이 경고를 남기고, 서버는 restore 가 켜진 채 시작합니다.
|
||||
- **pane 배치는 한 번에 하나.** pane 배치는 서버별 잠금(`lib_py/pane_lock.py`, macOS·Linux 에서 `flock`)을 잡고 합니다. 한 폴더에서 동시에 실행한 `create` 도 각자 자기 pane 을 받습니다.
|
||||
|
||||
### 🛡️ 레지스트리 쓰기와 동시성
|
||||
|
||||
- **직렬화된 쓰기.** `agent-sessions.yaml` 의 모든 변경은 `lib.sh::atomic_dump_yaml` 을 거칩니다. `.mam/agent-sessions.db` 의 배타적 SQLite 트랜잭션(`BEGIN IMMEDIATE`) 안에서 실행되고, 검증한 뒤에 YAML 을 원자적으로 다시 씁니다. 잡 레코드는 별도의 레지스트리 잠금을 씁니다.
|
||||
- **Python 인터프리터.** 레지스트리 쓰기와 위임 헬퍼는 이 순서로 Python 을 고릅니다: `AGENT_PYTHON_BIN`, 활성화된 가상환경, 스킬 위쪽에서 가장 가까운 `.venv`, 마지막으로 `PATH` 의 `python3`. shim 과 `create` 의 일부 같은 셸 경로는 `PATH` 의 `python3` 를 직접 부릅니다.
|
||||
- **네트워크 파일시스템.** `.mam/` 이 NFS/CIFS/SSHFS 에 있으면 `lib.sh` 가 경고하고, SQLite 저널 모드를 `WAL` 에서 `DELETE` 로 바꿉니다.
|
||||
- **체크아웃당 루프 하나.** 루프 잠금이 같은 제어 평면에서 두 번째 `run_loop.sh` 를 거부합니다.
|
||||
|
||||
---
|
||||
|
||||
## 📨 위임 계약
|
||||
|
||||
전체 명세는 [MESSAGING.md §2.5](MESSAGING.md)에 있습니다.
|
||||
|
||||
- **전달**: 프롬프트를 넘긴 뒤 **T** 초(기본 180) 안에 에이전트가 `started` 를 발행해야 합니다. 그러지 않으면 잡은 실패로 닫히고(`agent_blocked`, 종료 코드 1), 프롬프트를 두 번 넣지 않습니다.
|
||||
- **생존**: `started --heartbeat N` 이 자동 heartbeat 를 시작합니다(기본 30 초마다). **K×N** 초(기본 120 초) 동안 아무 이벤트가 없으면 무응답으로 봅니다. herdr 상태와 pane 텍스트는 진단용으로만 로그에 남깁니다.
|
||||
- **예산**: 잡마다 벽시계 예산이 있습니다(`--timeout` / `MAM_JOB_TIMEOUT_S`, 기본 3600 초). 예산을 다 쓴 잡은 `wall_clock_timeout` 으로 닫힙니다.
|
||||
- **바쁜 세션**: 래퍼는 그 세션의 앞선 열린 잡이 끝나기를 `MAM_DISPATCH_WAIT_S` 만큼 기다립니다. 끝나지 않으면 `cancelled`(`session_busy`, 종료 코드 5)로 끝나고, 프롬프트는 전달되지 않습니다.
|
||||
- **원격 에이전트**: `remote:<name>` 은 브리프를 서명된 retained 브로커 메시지로 다른 호스트의 `remote.py run` 러너에 보냅니다. 사설 브로커에서만 쓰십시오.
|
||||
|
||||
| 종료 코드 | 의미 |
|
||||
|:---:|---|
|
||||
| `0` | `completed` |
|
||||
| `1` | 실패, 또는 T 안에 `started` 없음 |
|
||||
| `2` | K×N 동안 이벤트 없음(`deadline_timeout`) 또는 예산 소진(`wall_clock_timeout`) |
|
||||
| `3` | 브로커를 쓸 수 없고, 디스크에도 종결 상태가 없음 |
|
||||
| `5` | 전달 안 됨(`cancelled`): 세션이 바쁨, 대상을 찾지 못함, 또는 기다리는 동안 레코드를 다른 쪽이 가져감 |
|
||||
|
||||
---
|
||||
|
||||
## 🔁 리뷰 루프
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
autonumber
|
||||
actor User as User
|
||||
participant PM as Project Manager
|
||||
participant W as Worker
|
||||
actor User
|
||||
participant L as run_loop.sh
|
||||
participant P as Planner (optional)
|
||||
participant C as Creator
|
||||
participant R as Reviewers
|
||||
participant M as MQTT Backplane
|
||||
|
||||
User->>PM: 요구사항 전달
|
||||
Note over PM: 태스크 수립 및 Job 등록
|
||||
PM->>M: Job 등록 및 Subscriber 시작
|
||||
PM->>W: 작업 위임 (Job ID 및 가이드 제공)
|
||||
W->>M: 'started' 이벤트 발행
|
||||
Note over W: 코드 변경 및 자체 검증 수행
|
||||
W->>M: 'completed' (또는 'error') 발행
|
||||
PM->>R: 병렬 리뷰 요청 (Diff 제공)
|
||||
Note over R: 에이전트 교차 검증 (Claude, Hermes, Grok, OpenCode, Codex)
|
||||
alt 리뷰 피드백 (NOT PASS)
|
||||
R->>PM: NOT PASS (대안 코드 블록과 함께 피드백 전달)
|
||||
Note over PM: PM 직접 수정 또는 다시 위임 결정
|
||||
PM->>W: 리뷰 피드백 반영 재요청
|
||||
else 검증 통과 (PASS)
|
||||
R->>PM: PASS
|
||||
User->>L: --task, --creator, --reviewer / --all-reviewer
|
||||
opt --plan
|
||||
L->>P: write the plan (Creator challenges it for --plan-talk turns)
|
||||
end
|
||||
PM->>User: 최종 머지 완료 보고 및 변경사항 커밋
|
||||
L->>C: implement and commit (skipped with --review-only)
|
||||
loop up to --max-loop
|
||||
L->>R: review the snapshot diff (base..head)
|
||||
alt every reviewer PASS and the source unchanged
|
||||
R-->>L: [VERDICT: PASS]
|
||||
else NOT PASS
|
||||
R-->>L: [VERDICT: NOT PASS] + findings
|
||||
L->>C: fix (or [REBUT:] up to --max-rebut)
|
||||
end
|
||||
end
|
||||
L->>User: reports promoted to .agents/reports/<session>/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔒 보안 프로토콜 및 Replay 공격 방어
|
||||
|
||||
공용 MQTT 브로커 환경에서도 통신의 무결성을 보장하기 위해 **HMAC-SHA256 암호화 서명** 체계를 갖추고 있습니다:
|
||||
* **PoC 모드 (무인증):** 기본 설정 모드로 `auth_token`이 `null`로 세팅되어 간단한 로컬 환경 검증 시 암호화 시그니처 체크를 건너뜁니다.
|
||||
* **프로덕션 모드 (인증 필수):** 각 잡마다 무작위 암호화 토큰이 발급되며, 백플레인을 오가는 모든 페이로드에 토큰 기반으로 생성된 `hmac_sig` 서명을 탑재해야 수신측에서 수용합니다.
|
||||
* **Replay 공격 방어:** 각 이벤트는 단조 증가하는 정수형 시퀀스 번호(`seq`)를 포함합니다. 구독자(`job_subscriber.py`)는 특정 잡에 대해 이미 수용한 최대 시퀀스 번호보다 크지 않은 시퀀스 번호를 가진 페이로드를 즉시 폐기합니다. 페이로드 바디에 대한 HMAC 서명과 결합하여, 이 메커니즘은 클록 동기화에 의존하지 않고 재전송(re-injected) 및 순서가 바뀐 패킷을 차단합니다. 메시지 내 타임스탬프 필드는 참고용 메타데이터이며, 백플레인은 시간 오차(clock-skew) 윈도우를 별도로 검증하지 않습니다.
|
||||
- **엄격한 판정**: 판정 토큰은 리포트 마지막 줄에 단독으로 있어야 합니다. 판정이 없으면 `NOT PASS` 로 봅니다.
|
||||
- **리뷰 identity** (`--worktree` / `--base`): 라운드마다 커밋하지 않은 파일까지 담은 스냅샷을 리뷰합니다. 라운드 중 소스가 바뀌면 그 승인은 버립니다. 보관되는 리포트 옆에는 base·head·tree·리뷰어를 적은 `report-<job>.identity.json` 이 붙습니다.
|
||||
- **하위 잡**: creator 가 작업 일부를 위임하면(`--parent-job`), 루프는 리뷰 전에 그 잡들을 기다리고 상태를 리뷰어에게 보여 줍니다.
|
||||
|
||||
---
|
||||
|
||||
## 📁 리포지토리 구성
|
||||
## 🔐 보안
|
||||
|
||||
- **서명된 이벤트**: 토큰을 직접 넘기거나 브로커가 TLS 또는 사용자 이름을 쓰면, 잡은 고유 토큰(`auth_token`)을 받습니다. 그때 모든 이벤트와 retained 상태 메시지에 그 토큰으로 만든 HMAC-SHA256 서명이 붙고, 구독자는 검증에 실패한 메시지를 버립니다. 이벤트와 상태 메시지에는 토큰이 아니라 서명만 실립니다. TLS 도 사용자 이름도 없는 브로커(PoC 구성)에서는 잡에 토큰이 없어 서명을 검사하지 않습니다.
|
||||
- **원격 디스패치에는 토큰이 실린다**: `remote:<name>` 디스패치 메시지에는 잡의 토큰이 들어갑니다(`MAM_DISPATCH_SECRET` 으로 서명될 뿐 암호화되지는 않음). 접근이 통제된 사설 브로커에서만 쓰십시오.
|
||||
- **재전송과 순서**: 이벤트마다 증가하는 `seq` 가 붙습니다. 구독자는 지금까지 본 것보다 큰 번호만 받고, 빈 번호는 `seq_gap` 으로 기록합니다. 타임스탬프는 참고용입니다.
|
||||
- **자격 증명**: 브로커 자격 증명은 `.mam.env` 에만 있고, 잡 레코드에는 없습니다.
|
||||
|
||||
---
|
||||
|
||||
## 🧪 테스트
|
||||
|
||||
```bash
|
||||
.venv/bin/python -m pytest -q -p no:cacheprovider tests
|
||||
```
|
||||
|
||||
- 테스트는 약 1,900 개이고, 전체 실행에 한 시간 넘게 걸립니다.
|
||||
- 프로세스 안에서 자체 MQTT 브로커를 띄우므로 `.mam.env` 가 필요 없습니다. 테스트용으로 `.mam.env` 를 export 하지 마십시오.
|
||||
- 테스트는 임시 HOME·레지스트리·감사 로그 디렉터리와 mock herdr 를 쓰는 샌드박스에서 돕니다.
|
||||
- 실제 herdr 를 다루는 테스트는 일회용 herdr 서버를 직접 띄웁니다.
|
||||
- 실행이 끝나면 세션 단위 가드가 실제 제어 평면과 사용자의 에이전트 홈(`~/.claude/projects`, `~/.codex`, `~/.gemini` …)을 확인하고, 테스트가 남긴 항목이 있으면 실행을 실패시킵니다.
|
||||
- 일부 테스트는 플랫폼에 따라 다릅니다. Python 3.11+(`tomllib`), Linux(`/proc`), `nats-docker` 서브모듈이 필요한 테스트는 그 밖의 환경에서 건너뜁니다.
|
||||
|
||||
---
|
||||
|
||||
## 📁 저장소 구조
|
||||
|
||||
```text
|
||||
.
|
||||
├── .agents/
|
||||
│ ├── MULTI_AGENT_RULES.md # 에이전트 역할 행동 강령 및 뷰포트 스냅샷 규칙
|
||||
│ ├── MULTI_AGENT_RULES.ko.md # 에이전트 역할 행동 강령 (한국어 백업)
|
||||
│ └── skills/ # 코어 오케스트레이션 셸 스크립트 및 라이브러리
|
||||
│ ├── lib.sh # 공통 오케스트레이션 셸 함수 라이브러리
|
||||
│ ├── lib_py/ # 파이썬 코어 오케스트레이션 엔진
|
||||
│ │ ├── agents/ # 멀티 에이전트 CLI 수명 주기 어댑터
|
||||
│ │ ├── delegation/ # 비동기 잡 위임 및 CAS 상태 전이 엔진
|
||||
│ │ └── loop/ # 자율 계획-실행-교차검증 루프 런타임
|
||||
│ ├── multi-agent-mux-create/
|
||||
│ ├── multi-agent-mux-stop/
|
||||
│ ├── multi-agent-mux-resume/
|
||||
│ ├── multi-agent-mux-status/
|
||||
│ ├── multi-agent-mux-monitor/
|
||||
│ ├── multi-agent-mux-delegate-job/
|
||||
│ │ ├── requirements.txt # 파이썬 의존성 패키지 선언
|
||||
│ │ └── scripts/ # 하위 호환 shim 스크립트 (Python)
|
||||
│ ├── multi-agent-mux-loop/
|
||||
│ └── multi-agent-mux-orc-onboard/
|
||||
├── .mam/ # Multi-Agent Mux 메타데이터 (git-ignored)
|
||||
│ ├── agent-sessions.db # SQLite WAL 세션 데이터베이스
|
||||
│ ├── agent-sessions.yaml # 텍스트 형식의 세션 레지스트리 스냅샷
|
||||
│ └── jobs/ # 비동기 잡 메타데이터 JSON 파일들
|
||||
├── deploy/ # 배포 및 설치 도구 패키지 폴더
|
||||
│ ├── INSTALL.md # 설치 가이드 및 퀵스타트 매뉴얼
|
||||
│ ├── install_mam.sh # 로컬/클론 인스톨러 스크립트
|
||||
│ ├── generate-env.sh # 환경 파일(.mam.env) 템플릿 복사 스크립트
|
||||
│ ├── install.sh # 원격/네트워크 인스톨러 스크립트
|
||||
│ ├── update.sh # 업데이트 헬퍼 스크립트
|
||||
│ └── remove.sh # 삭제/언인스톨 헬퍼 스크립트
|
||||
├── docs/ # 기술 규격서, 가이드 및 아키텍처 계약 문서
|
||||
│ ├── contracts/ # 이슈/백플레인 계약 및 마이그레이션 로드맵
|
||||
│ ├── MAM_WEB_PTY_BRIDGE_PLAN.md # Web PTY 터미널 브리지 설계 계획서
|
||||
│ ├── NEW_AGENT_INTEGRATION_GUIDE.md # 신규 AI 코딩 에이전트 연동 가이드
|
||||
│ └── OPENCODE_OLLAMA_GUIDE.md # OpenCode 인터프리터 + Ollama 연동 가이드
|
||||
├── nats-docker/ # 사설 NATS 브로커 배포 서브모듈
|
||||
├── tests/ # 종합 회귀 테스트 스위트 (32개 모듈)
|
||||
├── AGENTS.md # 에이전트 행동 지침 및 오케스트레이터 스코프 가드
|
||||
├── BOOTSTRAP.ko.md # 프로젝트 초기 설치 가이드 (한국어 백업)
|
||||
├── BOOTSTRAP.md # 프로젝트 초기 설치 및 검증 상세 가이드
|
||||
├── IMPROVEMENTS.md # 이슈 백로그 및 완료된 아키텍처 과제 추적 원장
|
||||
├── MESSAGING.md # MQTT 메시징 프로토콜 와이어 규격서
|
||||
├── README.ko.md # 프로젝트 대표 소개 파일 (한국어)
|
||||
├── README.md # 프로젝트 대표 소개 파일 (영문 원본)
|
||||
└── VERSIONS.md # 릴리스 노트 및 4-way 락스텝 버전 원장
|
||||
│ ├── MULTI_AGENT_RULES.md / .ko.md # 역할, 워크플로우, 협업 규칙
|
||||
│ ├── reports/ # 보관된 리뷰 리포트 (+ identity 사이드카)
|
||||
│ └── skills/
|
||||
│ ├── lib.sh # 공용 셸 라이브러리 (herdr shim, 레지스트리 쓰기)
|
||||
│ ├── lib_py/ # Python 코어
|
||||
│ │ ├── agents/ # 에이전트별 CLI 어댑터 (spawn/resume/discover)
|
||||
│ │ ├── delegation/ # 잡 레지스트리, 래퍼, MQTT 발행/구독, 원격 러너
|
||||
│ │ ├── loop/ # 리뷰 루프 런타임
|
||||
│ │ └── *.py # pane_lock, stall_watch, worktree, herdr_config, ...
|
||||
│ └── multi-agent-mux-*/ # 스킬마다 디렉터리 하나 (SKILL.md + scripts/)
|
||||
├── .mam/ # 런타임 상태 (git 제외): 세션, 잡, 감사 로그, shim
|
||||
├── deploy/ # install.sh, install_mam.sh, update.sh, remove.sh, generate-env.sh
|
||||
├── docs/ # contracts/, design/, 에이전트 통합·브리지 가이드
|
||||
├── nats-docker/ # 사설 NATS 브로커 배포 (서브모듈)
|
||||
├── tests/ # pytest 스위트
|
||||
├── AGENTS.md # 에이전트 행동 지침
|
||||
├── BOOTSTRAP.md / BOOTSTRAP.ko.md # 단계별 설치·검증 가이드
|
||||
├── IMPROVEMENTS.md # 백로그
|
||||
├── MESSAGING.md # MQTT 와이어 프로토콜과 위임 계약
|
||||
├── README.md # 영문 README
|
||||
└── VERSIONS.md # 릴리스 노트 (락스텝 버전 원장)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🚦 빠른 시작
|
||||
|
||||
자세한 빌드 절차는 **[BOOTSTRAP.md](./BOOTSTRAP.md)** 문서를 참조하십시오. 아래는 간략한 요약입니다:
|
||||
전체 과정은 [BOOTSTRAP.ko.md](BOOTSTRAP.ko.md)를 보십시오. 요약하면:
|
||||
|
||||
1. **환경 설정 파일(.mam.env) 생성:**
|
||||
```bash
|
||||
./deploy/generate-env.sh
|
||||
```
|
||||
2. **가상환경 생성 및 의존성 패키지 설치:**
|
||||
```bash
|
||||
python3 -m venv .venv
|
||||
source .venv/bin/activate
|
||||
pip install -r .agents/skills/multi-agent-mux-delegate-job/requirements.txt
|
||||
```
|
||||
3. **레지스트리 및 환경 작동 자가 검증:**
|
||||
```bash
|
||||
.venv/bin/python3 .agents/skills/multi-agent-mux-delegate-job/scripts/registry.py list
|
||||
```
|
||||
```bash
|
||||
# 1. 워크스페이스에 설치한 뒤 .mam.env 에 브로커를 설정
|
||||
bash deploy/install.sh
|
||||
|
||||
# 2. 전용 herdr 서버에서 creator 와 reviewer 시작
|
||||
bash .agents/skills/multi-agent-mux-create/scripts/create_session.sh \
|
||||
--workspace "$PWD" --agent claude --role developer --session creator-claude-01 \
|
||||
--herdr-session my-project --onboard
|
||||
bash .agents/skills/multi-agent-mux-create/scripts/create_session.sh \
|
||||
--workspace "$PWD" --agent codex --role reviewer --session reviewer-codex-01 \
|
||||
--herdr-session my-project --onboard
|
||||
|
||||
# 3. 세션 확인
|
||||
bash .agents/skills/multi-agent-mux-status/scripts/status.sh
|
||||
|
||||
# 4. 루프로 작업 실행
|
||||
bash .agents/skills/multi-agent-mux-loop/scripts/run_loop.sh \
|
||||
--creator creator-claude-01 --all-reviewer --task "Fix the typo in docs/guide.md"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📝 협업 에이전트 준수 사항
|
||||
## 📝 프로젝트에 합류하는 에이전트에게
|
||||
|
||||
이 프로젝트에 새로 합류한 에이전트는 다음 규칙을 준수해야 합니다:
|
||||
1. **[MULTI_AGENT_RULES.md](.agents/MULTI_AGENT_RULES.md)** 문서를 정독하여 프로젝트 매니저(PM), 작업자(Worker), 리뷰어(Reviewer) 간의 역할 및 개발 제약조건을 인지하십시오.
|
||||
2. 장시간 명령을 실행하는 경우 터미널 스크롤백 로그 유실을 방지하기 위해 `MULTI_AGENT_RULES.md` (제4장)에 기재된 **뷰포트 스냅샷 규칙(Pane Snapshotting Rules)**을 반드시 적용하십시오.
|
||||
3. 리뷰어 세션에 diff 검증을 요청하기 전에는 어떠한 코어 파일의 임의 수정도 프로덕션 브랜치에 승인 없이 머지할 수 없습니다.
|
||||
1. 역할과 규칙은 [AGENTS.md](AGENTS.md)와 [MULTI_AGENT_RULES.ko.md](.agents/MULTI_AGENT_RULES.ko.md)를 읽으십시오.
|
||||
2. 긴 출력이 pane 스크롤백 밖으로 사라지지 않도록 `MULTI_AGENT_RULES.ko.md` §4 의 스냅샷 규칙을 따르십시오.
|
||||
3. 브리프가 지시하는 대로 잡 이벤트를 발행하십시오(`started --heartbeat`, 그다음 `completed` 또는 `error`). 리뷰받은 diff 없이 핵심 로직을 바꾸지 마십시오.
|
||||
Reference in new issue
Block a user