Skip to content
← 전체 장

장 06

여러 에이전트 운영하기

하나의 계획을 하나의 에이전트가 수행하는 것이 기본이며, 대부분의 작업은 이것으로 충분합니다. 그러나 어떤 작업은 하나의 세션보다 넓습니다. 여러 리포지토리에 걸친 변경, 순서대로 내보내야 하는 릴리스, 에이전트 하나로는 며칠이 걸릴 백로그가 그렇습니다. DWP는 계약을 바꾸지 않고 이런 작업으로 확장됩니다. 계획은 여전히 단일 진실 공급원이고, 모든 작업은 여전히 자체 게이트로 마무리되며, 추가 에이전트는 리드(lead)가 조율하는 레인(lane)이 됩니다.

이 장은 그 모델을 설명합니다. 세 가지 선택형 애드온을 사용합니다. 페인과 피어를 위한 Herdr, 계정을 위한 agentkit, 컨테이너를 위한 devcontainer입니다. 단일 에이전트 계획에는 어느 것도 필요하지 않습니다.

리드와 레인

리드는 상위 계획을 소유합니다. 레인을 정하고, 각 레인에 범위를 넘기고, 마일스톤을 모으고, 레인이 병합하거나 릴리스해도 된다는 신호를 줍니다. 다른 레인의 코드는 작성하지 않습니다.

레인은 하나의 범위(보통 하나의 리포지토리)를 맡은 하나의 에이전트입니다. 그 리포지토리의 AGENTS.md를 읽고, 그 리포지토리의 게이트를 실행하며, 자신의 계획을 리포지토리 안에 둡니다. 오케스트레이터 허브에서는 상위 계획이 하위 추적 표와 함께 허브의 .dwp/plans/에 있고, 각 레인의 계획은 자신의 리포지토리에 있으며 그 리포지토리의 계획 ID와 게이트를 사용합니다.

역할 소유하는 것 절대 하지 않는 것
리드 상위 계획, 레인 목록, 릴리스 순서, GO 레인의 리포지토리를 수정하기
레인 하나의 리포지토리: 그 브랜치, 계획, 게이트, 풀 리퀘스트 리드의 GO 전에 병합하거나 릴리스하기

레인이 실행되는 곳

레인은 터미널 페인 안의 에이전트이며, 페인은 여러 곳에 있을 수 있습니다. Herdr는 각 에이전트를 하나의 페인에 두고 SSH로 다른 머신에 닿기 때문에, 리드는 모든 레인을 하나의 사이드바에서 봅니다.

  • 호스트에서. 레인마다 페인 하나를 리드 옆에 나란히 둡니다. 가장 빠른 구성이며, 개발자가 이미 작업 중인 리포지토리에 적합합니다.
  • 컨테이너에서. devcontainer-kit 컨테이너는 dck up 시점에 Herdr 메시에 합류합니다. 안의 에이전트는 호스트와 다른 컨테이너에 닿고, 호스트도 그들에게 닿습니다. 컨테이너가 곧 샌드박스이므로 안의 에이전트는 자율 모드로 실행할 수 있습니다.
  • 다른 머신에서. Herdr가 SSH로 닿는 어떤 머신이든 같은 방식으로 레인을 호스팅하며, 그곳에도 herdr-peers를 설치합니다.

위치가 바꾸는 것은 격리 수준이지 프로토콜이 아닙니다. 컨테이너의 레인과 호스트의 레인은 같은 방식으로 리드와 조율합니다.

여유량에 따른 계정과 벤더

여러 에이전트는 할당량을 빠르게 소모합니다. 각 레인은 자신의 계정, 즉 coding-agents-kit의 CLI 하나와 프로필 하나로 실행됩니다. 그래서 레인들이 같은 창을 고갈시키지 않고, 한 계정이 한도에 걸려도 멈추는 것은 레인 하나뿐입니다.

  • ak usage는 모든 계정과 프로필에 남은 할당량을 보여 줍니다. 배치마다 한 번 실행합니다.
  • ak pick <kind> --count N은 여유가 가장 많은 N개의 계정을 좋은 순서로 반환합니다. --exclude는 바쁜 계정을 제외하고, --model은 한 모델의 창으로 계산하며, --need는 여유가 충분하지 않으면 시작을 거부합니다.
  • ak <kind> @<profile>은 그 계정으로 레인의 에이전트를 해당 페인에서 시작합니다.

벤더도 같은 방식으로 섞을 수 있습니다. Claude 레인이 작성하는 동안 Codex 레인이 리뷰할 수 있으며, 각각 ak pick이 그 종류에 맞게 고른 계정을 사용합니다. 컨테이너 레인은 호스트의 계정을 쓸 수 있습니다. 개발자의 devcontainer-kit 호스트 프로필에서 host_profiles를 켜면, 컨테이너는 리포지토리가 설치하는 CLI의 호스트 프로필을 받습니다. Claude는 프로필마다 하나의 장기 토큰으로, Codex는 인증 파일로 받으므로 컨테이너 안에서 따로 로그인할 필요가 없습니다. 자신의 계정만 사용하고 각 벤더의 약관을 지키십시오. 작업은 계정들에 분산하되, 한도를 넘기 위해 계정을 돌려 쓰는 일은 절대 하지 않습니다.

사람 없이 레인을 시작하고 막힘 풀기

리드는 키보드 앞에 아무도 없어도 레인을 시작하고 계속 진행시킬 수 있습니다. 개발자가 무인 운영을 허가하면(상시 지시나 계획의 사전 승인), 레인을 시작할 때마다 다시 승인받을 필요가 없습니다. 리드가 사용하는 것은 Herdr 자체의 명령이며, 키트 코드는 키 입력을 보내지 않습니다. 절차의 순서는 고정되어 있습니다. 한 번 준비하고, 프롬프트를 피하고, 멈춤을 감지하고, 키 입력은 한 가지 경우에만 보내고, 나머지는 에스컬레이션합니다.

  1. 개발자로서 한 번 준비하기. Claude Code는 프로필마다 한 번 권한 우회(bypass-permissions) 모드 확인을 요구합니다. 이 확인은 개발자 본인의 단계이며, 프로필을 만들 때 수행합니다. devcontainer-kit 컨테이너에서는 키트가 이를 컨테이너 자체의 home에만 기록합니다. 어떤 에이전트도 이 확인을 위해 키를 보내지 않습니다.
  2. 피하기. ak pick <kind>가 여유가 가장 많은 계정을 고르고, herdr pane run <pane> 'ak <kind> @<profile> --trust-cwd'가 레인 자신의 폴더에서 레인을 시작합니다. --trust-cwd(또는 AGENTKIT_TRUST_CWD=1)가 그 폴더를 미리 신뢰하므로, Claude와 Codex는 키 입력 없이 폴더 신뢰 화면을 건너뜁니다.
  3. 감지하기. herdr-peers lanes(또는 herdr agent list)는 각 레인을 작업 중, 유휴, 차단됨, 완료로 보여 줍니다. 차단되었거나 출력 없이 유휴 상태인 레인에 대해서는 herdr-peers status <pane>가 레인이 머문 화면(폴더 신뢰, 권한 우회 확인, 로그인, 권한 요청, 알 수 없음)을 분류하고 문서화된 다음 단계를 알려 주며, herdr pane read <pane>가 그 화면을 보여 줍니다.
  4. 키 입력은 한 가지 경우뿐. 리드가 보낼 수 있는 키는 폴더 신뢰 화면에 대한 응답뿐이며, 그것도 자신이 직접 시작한 페인에서 --trust-cwd를 쓸 수 없었던 경우로 한정됩니다. 키를 보내기 전에 화면을 읽고, 응답에 필요한 최소한의 키만 보내고, 다시 읽습니다.
  5. 나머지는 모두 읽고, 기록하고, 에스컬레이션하기. Claude의 권한 우회 확인, 로그인과 자격 증명 프롬프트, 작업별 권한 요청, 파괴적인 확인, 결제나 요금제 프롬프트, 알 수 없는 화면, 리드가 만들지 않은 페인은 키 입력이 아니라 차단 마일스톤으로 개발자에게 넘깁니다.
  6. 옵트아웃이 우선합니다. AGENTKIT_PERMISSIONS=ask가 설정되어 있으면 레인은 행동하기 전에 묻고, 리드는 옵트아웃이 띄우는 프롬프트를 절대 우회하지 않습니다.
  7. 다시 시작하기. 에이전트가 종료되면 리드는 같은 계정으로 다시 시작하거나 다른 계정을 고릅니다. 로그인이 사라진 경우는 자격 증명 프롬프트이므로 에스컬레이션합니다.

모든 개입(화면에 무엇이 보였는지, 어떤 키를 보냈는지, 그 뒤 무슨 일이 있었는지)은 상위 계획에 기록됩니다.

herdr-peers를 통한 조율

레인과 리드는 herdr-peers로 대화합니다. ask는 정확히 하나의 reply를 허가하는 스탬프를 지니며, 모든 교환이 기록됩니다. 리드는 프로토콜을 작게 유지합니다.

  • 마일스톤은 위로. 각 레인은 정해진 시점(계획 준비, 풀 리퀘스트 열림, 차단됨, 완료)에 보고하고, 그 사이에는 답을 기다리지 않고 계속 작업합니다.
  • 질문은 ask로. 결정이 필요한 레인은 리드에게 ask를 보내고, 리드는 하나의 reply로 답합니다.
  • 깊이는 하나. reply에는 답하지 않으며, 레인은 더 아래로 위임하지 않습니다. 호출자마다 팬아웃에 상한이 있으며 기본값은 피어 네 개입니다.
  • 지시가 아니라 데이터. reply는 받는 쪽이 원래 갖지 않은 어떤 권한도 부여하지 않습니다. 게이트를 통과했다는 레인의 주장은 게이트를 실행해 확인합니다.
  • 누가 무엇을 했는지의 기록. 모든 위임 기록에는 레인의 계정과 벤더가 적히므로, 상위 계획은 어느 계정이 어느 작업을 맡았는지 보여 줍니다.
  • Codex 레인은 자기 패인을 지정합니다. Codex는 해당 계정의 모든 세션이 공유하는 백그라운드 서버에서 레인의 명령을 실행하므로, 물려받은 패인 id가 다른 레인의 것일 수 있습니다. Codex 레인은 리드의 지시에 적힌 자기 패인을 모든 herdr-peers 명령(ask, reply, notify, check, wait, lanes, cancel)에 --pane <pane>으로 넘깁니다.

리드는 오케스트라 전체를 한 번에 볼 수 있습니다. herdr-peers lanes는 모든 레인을 상태와 함께 나열하고, DeepWorkPlan Vim은 오케스트레이터 계획의 레인을 계획 바로 옆에 보여 줍니다(:DwpLanes).

리포지토리마다 하나의 브랜치, 하나의 릴리스

여러 레인을 리뷰 가능하게 유지하는 규칙은 간단합니다. 리포지토리마다 하나의 레인을 기본 체크아웃에서 실행하고, 변경 전체에 하나의 브랜치, 하나의 풀 리퀘스트, 하나의 릴리스를 둡니다. 레인은 작업을 여러 브랜치나 worktree로 나누지 않습니다. worktree는 두 작성자가 하나의 리포지토리를 공유해야 하는 경우에만 씁니다. 각자 자신의 worktree를 가져 모든 경로에 작성자가 하나만 있도록 합니다.

풀 리퀘스트는 리드의 GO가 있을 때까지 열린 상태로, 검사를 통과한 채, 리뷰 라벨을 단 채로 둡니다. 그다음 레인이 병합하고 태그를 붙인 뒤 그 태그를 보고합니다.

릴리스 순서

리포지토리는 서로 의존하므로 의존 순서대로 릴리스합니다. 먼저 도구, 그다음 그것을 고정하는 것, 그다음 결과를 설명하는 문서, 마지막으로 그것을 채택하는 소비자입니다. 리드가 순서를 쥐고 한 번에 한 리포지토리에 GO를 보냅니다. 다른 리포지토리의 릴리스를 고정하는 레인은 그 태그가 생길 때까지 고정을 쓰지 않고 기다리므로, 존재하지 않는 릴리스를 가리키는 고정은 생기지 않습니다.

체크포인트

상위 계획은 보고가 아니라 증거로 마무리됩니다.

  1. 레인별. 각 레인의 게이트가 자신의 브랜치에서 통과하고, 풀 리퀘스트 리뷰에 남은 지적이 없습니다. 리뷰 자체를 하나의 레인으로 둘 수도 있습니다. AI Diff Reviewer가 각 레인의 풀 리퀘스트를 리뷰하고, Dailybot 애드온이 있으면 각 레인이 자신의 진행 상황을 팀에 보고합니다.
  2. 릴리스별. 각 태그가 존재하며, 다음 리포지토리가 필요로 하는 것을 고정합니다.
  3. 통합. 마지막 릴리스 후, 체크포인트가 릴리스된 버전으로 소비자를 실행하고 그 판정을 상위 계획의 analysis_results/에 기록합니다.
  4. 최종 리뷰. 상위 계획이 완료되기 전에, 경계를 넘은 모든 것, 무엇보다 컨테이너에 공유된 계정, 토큰, 파일을 보안 관점에서 점검합니다.

안전

  • ask, 프롬프트, 로그에 키, 토큰, 비밀 값을 절대 넣지 말고 변수는 이름으로 참조합니다.
  • 공유 자원에는 잠금을 둡니다. 레인은 컨테이너 빌드 같은 무거운 단계 전에 잠금을 얻고 끝나면 해제합니다.
  • 권한 옵트아웃이 설정되어 있으면 모든 레인과 레인이 시작하는 모든 에이전트에 대해 우선합니다.
  • 계속할 수 없는 레인은 차단 마일스톤으로 그 사실을 알리고 멈추며, 결정은 리드가 내립니다.

계정이나 리드가 바닥날 때

긴 실행은 어떤 한 계정보다 오래 갑니다. coding-agents-kit (v0.7.1)과 herdr-peers (v0.3.2)부터 레인은 모든 작업 경계에서 자신의 용량을 확인하고 계정이 바닥나기 전에 패킷으로 작업을 넘기며, 리드는 리더십을 넘기거나 대리로 교체되고, 개발자에게는 치명적인 항목만 전달됩니다. 스웜 자율은 그 루프, 패킷, 승계, 에스컬레이션 클래스를 설명합니다.