5개의 코딩 에이전트를 병렬로 실행하는 것은 쉽습니다. 하지만 하나가 충돌했을 때 상태를 잃지 않는 것이 어려운 부분입니다.
요약
멀티 에이전트 코딩 환경에서 발생하는 상태 충돌과 작업 트리 오염 문제를 해결하기 위한 Rust 기반 프레임워크 'brat'을 소개합니다. git refs를 활용한 append-only 이벤트 로그 방식을 통해 에이전트 충돌 시에도 상태를 안전하게 복구하고 관리할 수 있습니다.
핵심 포인트
- 멀티 에이전트 간의 조정(coordination) 및 상태 관리 문제 해결
- append-only 이벤트 로그를 통한 충돌 안전성 및 결정론적 상태 복구 보장
- git refs를 활용하여 작업 트리의 메타데이터 노이즈 제거
- Mayor, Convoy, Task 등 역할 기반의 체계적인 에이전트 오케스트레이션
당신의 레포지토리(repo)에 하나의 AI 코딩 에이전트를 지정하면 대부분 잘 작동합니다. 하지만 5개를 지정하면 문제는 에이전트 자체가 아니라 조정(coordination)의 문제가 됩니다. 누가 무엇을 작업하고 있는가. 에이전트 3의 세션이 작업 도중 종료되면 어떻게 되는가. 충돌 시 계획을 잃지 않도록 상태(state)가 어디에 저장되는가. 완료된 작업이 서로 충돌하지 않고 어떻게 다시 병합되는가.
대부분의 설정은 작업 트리(working tree)에 있는 JSON 파일과 요행에 의지해 이러한 질문에 답합니다. 프로세스가 종료되면 파일이 절반만 작성될 수 있습니다. 작업 트리가 지저분해지고 코드 리뷰(code review)를 오염시킵니다. 두 에이전트가 동일한 상태를 편집하면 하나가 조용히 승리해 버립니다.
brat은 이러한 질문들에 제대로 답하기 위해 구축된 Rust 기반의 멀티 에이전트 하네스(multi-agent harness)입니다. 핵심 약속은 다음과 같습니다: 에이전트가 충돌하더라도 조정 상태(coordination state)는 항상 복구 가능하며 감사(auditable)할 수 있습니다.
핵심 아이디어: 조정은 추가 전용(append-only) 이벤트 로그입니다
Brat은 가변 상태(mutable state) 파일을 유지하지 않습니다. 이는 git refs(refs/grite/wal)에 저장되는 추가 전용(append-only) 이벤트 로그인 grite를 기반으로 구축되었습니다. 조정 상태에 대한 모든 변경 사항은 해당 로그에 추가되는 이벤트입니다. 상태는 저장되는 것이 아니라, 이벤트를 재생(replaying)함으로써 도출됩니다.
이 단 하나의 결정이 충돌 안전성(crash-safety)을 제공합니다. 추가 전용 로그에는 손상될 수 있는 절반만 작성된 가변 레코드가 없습니다. 작업 도중 프로세스가 종료되면 마지막으로 알려진 양호한 지점(last known-good point)으로부터 결정론적으로 재구축할 수 있습니다. 또한 로그가 추적되는 파일이 아닌 git refs에 존재하기 때문에 작업 트리는 깨끗하게 유지됩니다. git status에 조정용 JSON이 나타나지 않으며, 코드 리뷰에 메타데이터 노이즈가 발생하지 않습니다.
자체 목록에서 명시적으로 목표로 하는 문제들은 다음과 같습니다:
| 문제 | Brat이 해결하는 방식 |
|---|---|
| 지저분한 작업 트리 (Dirty working trees) | 메타데이터가 추적되는 파일이 아닌 refs/grite/*에 존재함 |
| ... |
작동 방식: 소수의 역할 구성
Brat은 작업을 역할(roles)의 집합으로 모델링하며, 일단 역할을 이해하고 나면 사고 모델(mental model)이 명확해집니다:
- Mayor는 AI 오케스트레이터 (orchestrator)입니다. 코드베이스를 분석하고, 작업을 분해하며, 컨보이 (convoy)와 태스크 (task)를 생성합니다.
- Convoy는 관련된 태스크들의 그룹입니다. 스프린트 (sprint), 에픽 (epic), 또는 피처 브랜치 (feature branch)를 생각하면 됩니다.
- Task는 하나의 코딩 에이전트 (coding agent)에게 할당된 단일 작업 항목입니다.
- Witness는 에이전트 세션 (agent sessions)을 생성하고 모니터링합니다.
- Refinery는 머지 큐 (merge queue)를 관리하고, CI 체크를 실행하며, 통합 (integration)을 처리합니다.
- Deacon은 백그라운드 관리자 (janitor)입니다. 락 (lock)을 정리하고, 상태를 동기화하며, 고립된 세션 (orphaned sessions)을 감지합니다.
흐름은 위에서 아래로 진행됩니다. Mayor가 Task를 포함하는 Convoy를 생성합니다. Witness는 대기 중인 Task에 대해 에이전트를 생성합니다. Refinery는 완료된 작업을 머지 (merge)합니다. Deacon은 전체 시스템에서 락 누수나 고립된 세션이 발생하지 않도록 유지합니다.
그 밑단에서는 서브스트레이트 (substrate)가 화려하지 않지만 중요한 정확성 작업을 수행합니다. 이벤트 (events)는 불변 (immutable)입니다. 각 에이전트 (actor)는 자신만의 격리된 데이터 디렉토리를 가지므로, 한 에이전트의 쓰기 작업이 다른 에이전트의 작업을 덮어쓰지 않습니다. 엔진 (engine) 작업에는 제한적이고 설정 가능한 타임아웃 (timeout)이 있어, 멈춰버린 에이전트가 전체 하네스 (harness)를 멈추게 하지 않습니다. 리소스 조정 (resource coordination)에는 TTL 기반의 리스 락 (lease locks)을 사용하여, 충돌이 발생한 에이전트의 락이 데드락 (deadlock)을 일으키는 대신 결국 만료되도록 합니다.
또한 이는 엔진 불가지론적 (engine-agnostic)입니다. Brat은 어댑터 (adapter)를 통해 사용자가 선호하는 코딩 도구를 구동합니다:
| 엔진 (Engine) | 명령어 (Command) |
|---|---|
| Claude Code | claude |
| ... | ... |
.brat/config.toml에서 엔진을 선택하면 Brat이 그 주변의 오케스트레이션을 처리합니다.
구체적인 실행 예시
루프는 의도적으로 작게 설계되었습니다. 서브스트레이트와 하네스를 초기화하고, Mayor를 시작한 뒤, 코드 분석을 요청하고, Witness가 생성된 태스크를 실행하도록 합니다.
cd your-project
grite init # grite 서브스트레이트 초기화
brat init # Brat 하네스 초기화
...
조정 (coordination)이 git 내의 이벤트로 이루어지기 때문에, brat status는 취약한 로컬 파일을 읽는 것이 아니라, 언제든 로그로부터 재구축할 수 있는 파생된 상태 (derived state)를 쿼리하는 것입니다.
재사용 가능한 워크플로우 (workflows)를 선언할 수도 있습니다. 병렬 컨보이 (parallel convoy)는 단순히 팬 아웃 (fan out)되는 일련의 레그 (legs)와 결과를 하나로 모으는 합성 (synthesis) 단계일 뿐입니다:
name: code-review
type: convoy
legs:
...
세 명의 에이전트가 세 가지 서로 다른 관심사를 병렬로 검토하고, 네 번째 에이전트가 이를 합성합니다. 이것이 멀티 에이전트 (multi-agent) 작업이 실제로 원하는 형태이며, 컨보이 (convoys) 및 태스크 (tasks)에 깔끔하게 매핑됩니다.
적합하지 않은 부분
Brat은 자신이 "해결하지 못하는 것"에 대한 솔직한 목록을 함께 제공하며, 이것이 제가 Brat을 신뢰하는 주요 이유입니다. 트레이드오프 (trade-offs)가 핵심이기 때문에 이를 다시 반복하겠습니다.
-
엔진의 신뢰성을 해결하지 못합니다. API 속도 제한 (rate limits), 인증 실패 (auth failures), 벤더 중단 (vendor outages)은 Brat의 통제 범위를 벗어납니다. Claude나 GPT가 다운되면 Brat은 응답을 마법처럼 만들어낼 수 없습니다. Brat은 실패 자체를 복구하는 것이 아니라, 실패 주변의 조정 상태 (coordination state)를 복구할 수 있습니다.
-
실제 머지 충돌 (merge conflicts)을 해결하지 못합니다. Refinery가 머지 큐 (merge queue)와 정책을 관리합니다. 진정한 코드 충돌에는 여전히 인간의 판단이 필요합니다. Brat은 머지를 명령하고 게이트 (gate) 역할을 수행하지만, 두 개의 모순된 디프 (diffs)를 화해시킬 수 있을 만큼 당신의 코드를 잘 이해하지는 못합니다.
-
프롬프트 (prompts)를 작성해주지 않습니다. Brat은 에이전트를 오케스트레이션 (orchestrates)합니다. 프롬프트 품질은 여전히 당신의 몫입니다. 모호한 작업에 Brat을 투입하면, 깔끔하게 조정된 모호한 결과물을 얻게 될 뿐입니다.
-
CI를 대체하지 않습니다. Brat은 기존의 CI와 통합될 뿐, CI 자체가 되지는 않습니다.
-
초기 단계이며 Rust-native입니다. 소스에서 빌드하려면 Rust 툴체인 (toolchain)이 필요하며, 선결 조건으로
grite를 먼저 설치해야 합니다. 이것은 클릭 한 번으로 실행되는 소비자용 앱이 아니라, 여러 에이전트를 진지하게 실행하고자 하는 사람들을 위한 인프라 (infrastructure)입니다.
이 목록을 관통하는 패턴은 다음과 같습니다: Brat은 마법 지팡이가 아니라 조정 기질 (coordination substrate)이라는 점에 대해 솔직합니다. Brat은 상태를 크래시 안전 (crash-safe)하게 만들고 감사 가능 (auditable)하게 만듭니다. 하지만 에이전트를 훌륭하게 만들어주지는 않습니다.
요점 (Takeaways)
- 멀티 에이전트 코딩 (multi-agent coding)의 어려운 점은 병렬성 (parallelism)이 아니라 상태 (state)입니다. git refs의 append-only 이벤트 로그 (append-only event log)는 해당 상태를 충돌 복구 가능 (crash-recoverable)하게 만들며 작업 트리 (working tree)를 깨끗하게 유지합니다.
- 역할 (Roles: Mayor, Convoy, Task, Witness, Refinery, Deacon)은 실제 작업이 분해되는 방식과 일치하는 멘탈 모델 (mental model)을 제공합니다.
- 액터 격리 (Actor isolation), 제한된 타임아웃 (bounded timeouts), 그리고 TTL 임대 잠금 (TTL lease locks)은 하네스 (harness)가 충돌 상황에서도 생존할 수 있을지를 결정하는 지루하지만 중요한 정확성 (correctness) 세부 사항들입니다.
- 프로젝트가 해결하지 못하는 것이 무엇인지 공개할 때 그 프로젝트를 더 신뢰할 수 있습니다. Brat은 그렇게 합니다.
코드, 역할 문서, 그리고 데모는 여기에서 확인할 수 있습니다:
https://github.com/neul-labs/brat
이미 여러 개의 코딩 에이전트를 실행하고 있다면, 현재 작업 도중 발생하는 충돌 (mid-task crash)을 어떻게 처리하고 계신지 알고 싶습니다. 직접 테스트해 보시고, 이슈 (issues) 제보를 환영합니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기