
요즘은 하나의 AI 코딩 에이전트만 사용하는 대신 역할을 나눠 여러 에이전트를 동시에 활용하는 워크플로우가 점점 자연스러워지고 있다.
예를 들어 Codex에는 기능 구현을 맡기고, Claude Code에는 설계 검토를 요청하고, 또 다른 에이전트에는 테스트 케이스를 찾아달라고 할 수 있다. 터미널을 세 개 열고 같은 저장소에서 각 에이전트를 실행하면 겉보기에는 멀티 에이전트 환경이 완성된 것처럼 보인다.
하지만 실제로 해보면 곧 다른 문제가 생긴다.
결국 에이전트를 여러 개 실행하는 것과 여러 에이전트를 하나의 팀처럼 조율하는 것은 다른 문제다.
이 글에서는 이 차이를 중심으로 Orca Orchestration이 어떤 역할을 하는지 살펴본다.
Orca는 여러 AI 코딩 에이전트를 나란히 실행하고 관리하는 개발 환경이다. Orca 자체가 새로운 AI 모델인 것은 아니다. Codex, Claude Code, Cursor CLI, OpenCode처럼 이미 사용하고 있는 CLI 에이전트를 실행하고, 각각의 작업 공간과 터미널, 변경 사항을 한곳에서 관리한다.
Orca의 중요한 특징은 Git worktree를 작업 공간의 중심으로 사용한다는 점이다.
각 작업은 필요에 따라 실제 Git worktree를 가질 수 있다. worktree마다 별도의 브랜치와 파일, 에이전트 터미널, 브라우저 탭이 연결된다. 덕분에 여러 에이전트가 서로 다른 접근을 동시에 시도하더라도 같은 작업 디렉터리를 덮어쓸 가능성을 줄일 수 있다.
공식 문서가 소개하는 기본 흐름은 단순하다.
저장소 추가
→ 작업별 worktree 생성
→ 에이전트 실행
→ 결과 diff 검토
→ 선택한 결과를 commit / push / PR
여기까지만 보면 Orca는 멀티 에이전트용 IDE처럼 보인다. Orchestration은 여기에 누가 작업을 맡았고, 현재 어떤 상태이며, 언제 끝났는지를 관리하는 규칙을 추가한다.
에이전트 세 개에게 각각 프롬프트를 보내는 것은 병렬 실행이다. 하지만 누가 무엇을 맡았는지, 지금 몇 번째 실행이 진행 중인지, 언제 완료된 것으로 인정할지를 시스템이 추적하지 않는다면 조율은 여전히 사람의 몫이다.
Orca Orchestration은 이 상태를 명시적으로 관리한다.
| 단순 병렬 실행 | Orca Orchestration |
|---|---|
| 에이전트에게 프롬프트만 전달한다 | Task와 Dispatch를 만들어 작업을 추적한다 |
| 사람이 터미널 출력을 보고 완료를 판단한다 | Worker가 worker_done을 보내 완료를 보고한다 |
| 질문이 생기면 해당 터미널에서 멈춘다 | ask와 reply로 전체 진행을 관리하는 에이전트에게 질문한다 |
| 재시도와 기존 시도의 관계가 불분명하다 | Task는 유지하고 새로운 Dispatch로 다시 실행한다 |
| 여러 대화를 사람이 기억한다 | Run의 메시지함과 작업 관계도가 상태를 보존한다 |
따라서 Orca Orchestration을 한 문장으로 표현하면 다음과 같다.
Orca Orchestration은 여러 에이전트 사이에서 누가 어떤 작업을 맡았는지, 몇 번째로 실행 중인지, 언제 완료됐는지를 기록하고 관리하는 장치다.
터미널이 조용하다고 실패한 것은 아니다. 반대로 에이전트가 자연어로 “끝났습니다”라고 출력했다고 무조건 완료된 것도 아니다. Orca에서는 현재 유효한 Dispatch에 연결된 worker_done이 작업 완료의 기준이 된다.
Orca Orchestration은 네 가지 개념을 이해하면 전체 구조가 보인다.
Run
├─ Task A
│ └─ Dispatch A-1 ── Worker A
├─ Task B
│ └─ Dispatch B-1 ── Worker B
└─ 관리 에이전트의 메시지함
Run은 하나의 오케스트레이션에 속한 작업 정보를 한데 모아 계속 보관하는 공간이다. 전체 진행을 관리하는 에이전트가 받는 메시지함 역할도 한다.
다만 Run이 알아서 작업 에이전트를 배치하거나 실행 순서를 정해주는 것은 아니다. 어떤 Task를 만들고 어느 에이전트에게 맡길지는 전체 진행을 관리하는 에이전트가 결정한다.
Task는 수행해야 할 작업 자체다. 무엇을 해야 하는지 적은 설명, 먼저 끝나야 하는 다른 Task, 현재 진행 상태를 함께 가진다.
Task 상태에는 다음과 같은 값이 있다. 실제 명령에서는 영문 상태값을 사용하지만 의미는 어렵지 않다.
pending(대기)
→ ready(시작 가능)
→ dispatched(에이전트에게 할당됨)
→ completed(완료)
└→ failed(실패)
진행에 필요한 조건이 해결되지 않으면 blocked(진행 불가) 상태가 될 수 있다.
예를 들어 “로그인 과정의 race condition을 수정한다”가 하나의 Task가 될 수 있다.
Dispatch는 특정 Task를 특정 터미널의 Worker에게 맡긴 한 번의 실행 시도다.
Task와 Dispatch의 차이가 중요하다. “로그인 버그를 수정한다”는 Task이고, “Codex에게 첫 번째 해결을 시도하게 한다”는 Dispatch다. 첫 번째 시도가 실패하더라도 Task 자체를 버릴 필요는 없다. 새로운 Dispatch를 만들어 다른 에이전트나 다른 worktree에서 재시도할 수 있다.
Orca는 현재 Dispatch를 맡은 에이전트가 보낸 완료 보고와 상태 신호만 유효한 것으로 처리한다. Task ID와 Dispatch ID를 함께 확인하기 때문에 이전 실행의 뒤늦은 완료 메시지가 현재 실행을 잘못 완료시키는 문제를 줄일 수 있다.
Worker는 실제 작업을 수행하는 Codex, Claude Code 등의 작업 에이전트다. Orca에서는 이 에이전트가 실행되는 터미널까지 하나의 작업 단위로 관리한다.
Orca는 Worker를 시작할 때 “어떤 Task의 몇 번째 실행을 맡았는지, 질문과 완료 보고는 어떻게 보내야 하는지”가 적힌 안내문을 자동으로 전달한다. Worker는 작업 중 질문이 생기면 전체 진행을 관리하는 에이전트에게 묻고, 작업이 끝나면 정확히 한 번 worker_done을 전송한다.
현재 Orca에는 Settings → Orchestration에서 관련 스킬의 설치 상태와 사용 예시를 확인할 수 있다.
CLI가 현재 실행 중인 Orca 앱과 통신할 수 있는지도 확인한다.
command -v orca
orca status --json
Orca의 설치된 스킬 파일에는 언제 이 기능을 사용해야 하는지만 간단히 적혀 있다. 실제 명령어 설명은 현재 실행 파일이 직접 제공한다. 공개 스킬 파일에 명령어를 고정해두면 앱을 업데이트한 뒤 명령과 문서가 서로 어긋날 수 있기 때문이다.
따라서 실제 오케스트레이션 상태를 변경하기 전에는 현재 설치된 바이너리에서 전체 가이드를 불러오는 것이 안전하다.
orca skills get orchestration --full
에이전트가 결과를 파싱해야 하는 명령에는 가능한 한 --json을 사용하는 것이 권장된다.
예시로 로그인 오류를 조사하고 수정하는 작업을 하나 만들어보자.
먼저 전체 목표를 담는 Run을 만든다.
orca orchestration run-create \
--objective "로그인 오류를 수정하고 검증한다" \
--json
Run은 이후 생성되는 Task와 관리 에이전트의 메시지가 모이는 공간이 된다.
Worker가 수행해야 할 작업을 Task로 등록한다.
orca orchestration task-create \
--spec "로그인 토큰 갱신 과정의 race condition을 조사하고 수정한 뒤 관련 테스트를 실행한다" \
--json
응답에 포함된 task_id는 다음 단계에서 사용한다.
현재 worktree에 새로운 Codex 터미널을 만들고 Task를 맡긴다. Orca에서는 이렇게 Task를 특정 Worker에게 맡긴 한 번의 실행을 Dispatch라고 부른다.
orca orchestration worker-start \
--task <task_id> \
--worktree current \
--agent codex \
--json
worker-start는 관리 에이전트가 진행 상황을 계속 추적해야 할 때 권장되는 방식이다. 필요한 터미널을 준비하고 Task를 연결한 다음, Worker에게 질문과 완료 보고 방법을 자동으로 안내한다.
작업을 별도 worktree로 격리하고 싶다면 다음처럼 실행할 수 있다.
orca orchestration worker-start \
--task <task_id> \
--worktree new-child \
--name fix-login-race \
--agent codex \
--setup run \
--json
현재 작업과 무관한 독립적인 작업이라면 new-child 대신 new-top-level을 사용한다.
전체 진행을 관리하는 에이전트는 일정한 간격으로 터미널을 들여다보는 대신, 완료·도움 요청·질문 같은 필요한 메시지가 올 때까지 기다릴 수 있다.
orca orchestration check \
--wait \
--types worker_done,escalation,question \
--timeout-ms 900000 \
--json
여기서 정해둔 대기 시간이 끝나도 곧바로 Worker가 실패한 것은 아니다. 긴 코딩 작업은 15분 이상 걸릴 수 있다. 대기 시간이 끝났다는 것은 Worker를 종료하라는 신호가 아니라 상태를 한 번 더 확인할 시점에 가깝다.
check는 관리 에이전트가 아직 확인하지 않은 메시지 묶음 중 가장 먼저 도착한 것을 반환한다. 한 묶음에 여러 메시지가 들어 있다면 전부 처리한 뒤 ack 옵션으로 확인 처리를 해야 한다.
orca orchestration check \
--ack <delivery_id> \
--wait \
--types worker_done,escalation,question \
--timeout-ms 900000 \
--json
작업을 마친 Worker는 자신의 터미널에서 worker_done이라는 완료 보고를 정확히 한 번 보낸다.
orca orchestration send \
--type worker_done \
--subject "로그인 오류 수정 완료" \
--body "토큰 갱신 경쟁 조건을 수정하고 관련 테스트를 통과했습니다." \
--task-id <task_id> \
--dispatch-id <dispatch_id> \
--outcome succeeded \
--files-modified "src/auth/session.ts,tests/auth/session.test.ts" \
--json
실패했을 때도 보고는 필요하다. 이 경우 설명에만 실패라고 적지 말고 결과값을 --outcome failed로 명시한다.
관리 에이전트가 유효한 worker_done을 처리한 뒤에는 해당 Worker 터미널을 어떻게 할지 정해야 한다.
worker-release한다.worker-retain한다.orca orchestration worker-release \
--dispatch <dispatch_id> \
--json
worker-release는 무작정 터미널을 종료하는 명령이 아니다. 나중에 확인할 수 있도록 출력은 보존하면서, 해당 작업을 위해 생성했던 정확한 에이전트 터미널만 정리한다. 이후 출력이 필요하면 worker-read로 다시 확인할 수 있다.
독립적인 Task를 차례로 만들고 하나씩 기다리면 병렬 처리의 이점을 얻기 어렵다. Orca 가이드는 먼저 독립 Task를 모두 생성한 뒤 모든 worker를 시작하고, 그다음 완료를 기다리는 흐름을 권장한다.
Task A: 오류 원인 분석 ─────→ Codex
Task B: 테스트 누락 조사 ───→ Claude Code
Task C: 보안 영향 검토 ─────→ Cursor
↓
관리 에이전트가 결과 취합
개념적인 명령 흐름은 다음과 같다.
orca orchestration run-create --objective "로그인 오류를 다각도로 분석한다" --json
orca orchestration task-create --spec "오류의 재현 조건과 원인을 조사한다" --json
orca orchestration task-create --spec "관련 테스트의 누락 케이스를 찾는다" --json
orca orchestration task-create --spec "수정이 인증 보안에 미칠 영향을 검토한다" --json
orca orchestration worker-start --task <task_a> --worktree current --agent codex --json
orca orchestration worker-start --task <task_b> --worktree current --agent claude --json
orca orchestration worker-start --task <task_c> --worktree current --agent cursor --json
다만 같은 worktree의 worker들이 같은 파일을 동시에 수정하면 충돌할 수 있다. 읽기 전용 조사처럼 변경 범위가 겹치지 않는 작업은 같은 worktree에서 수행할 수 있지만, 서로 다른 구현을 동시에 시도한다면 별도 worktree가 더 적합하다.
Orca가 Task를 자동으로 잘게 나누거나 파일 충돌 가능성을 대신 판단하는 것은 아니다. 무엇을 병렬로 처리할지, 어떤 순서로 실행할지, 같은 worktree를 공유해도 되는지는 전체 진행을 관리하는 에이전트가 설계해야 한다.
작업 중 중요한 선택이 필요할 수 있다.
예를 들어 Worker가 “공용 인증 모듈까지 수정할지, 현재 로그인 화면만 수정할지” 결정하지 못했다고 해보자. 이때 각자의 터미널 화면에서 사용자의 답을 기다리게 하면 관리 에이전트는 Worker가 왜 멈췄는지 알기 어렵다.
진행 상황을 추적받는 Worker는 ask를 사용해 관리 에이전트에게 질문을 보낼 수 있다.
orca orchestration ask \
--question "공용 인증 모듈까지 수정할까요?" \
--options "공용 모듈 수정,현재 화면만 수정" \
--timeout-ms 600000 \
--json
관리 에이전트는 도착한 질문에 답한다.
orca orchestration reply \
--id <message_id> \
--body "현재 화면만 수정해주세요" \
--json
답을 기다리는 시간이 끝나도 질문 자체는 대기 상태로 남는다. 같은 질문을 다시 만들어 중복시키기보다 기존 메시지 ID를 사용해 이어서 기다려야 한다.
Orca에는 작업 중 질문을 보내는 ask와 다음 단계 진행 여부를 정하는 decision gate가 있다. 둘 다 질문처럼 보이지만 방향과 목적이 다르다.
ask: Worker가 작업을 계속하기 위해 관리 에이전트에게 묻는 질문decision gate: 관리 에이전트가 여러 Task의 진행 순서를 잠시 멈추고, 다음 단계에 필요한 결정을 기록하는 장치예를 들어 구현 Task가 끝난 뒤 “공용 컴포넌트 변경을 다음 단계에 포함할 것인가?”라는 결정이 내려져야 배포 Task를 시작할 수 있다면 decision gate가 어울린다.
orca orchestration gate-create \
--task <task_id> \
--question "공용 컴포넌트 변경을 포함할까요?" \
--options '["yes","no"]' \
--json
orca orchestration gate-resolve \
--id <gate_id> \
--resolution "yes" \
--json
Worker의 단순 질문에 gate를 사용하거나, 여러 Task의 진행 순서를 결정하는 문제를 ask로 대신하지 않는 것이 좋다.
Orca 문서에서 특히 강조하는 부분이 작업을 완전히 넘기는 방식(full handoff)과 계속 진행 상황을 관리하는 방식(supervised orchestration)의 구분이다.
Handoff는 다른 에이전트에게 작업 책임을 완전히 넘기고 기존 에이전트는 더 이상 진행 상황을 확인하지 않는 흐름이다.
“이 작업은 별도 worktree를 만들어 Codex에게 넘겨줘.”
이 경우 기존 에이전트가 결과를 기다리는 것이 아니므로 Task나 Dispatch, worker_done 같은 진행 상태 보고 절차를 만들 필요가 없다. worktree를 만들면서 새 에이전트에게 프롬프트를 전달하고 작업을 완전히 넘기면 된다.
orca worktree create \
--name fix-login \
--no-parent \
--agent codex \
--prompt "로그인 오류를 조사하고 수정해주세요" \
--setup run \
--json
반면 다음 요청은 관리 에이전트가 계속 작업 상태를 확인해야 한다.
“Codex와 Claude에게 원인 분석과 테스트 설계를 나눠 맡기고, 두 작업이 끝나면 결과를 취합해서 알려줘.”
이때는 Run과 Task를 만들고 각 Worker에게 작업을 맡긴 뒤 완료 보고, 질문, 도움 요청을 기다리는 Orchestration이 필요하다.
간단히 구분하면 다음과 같다.
작업을 넘기고 빠지면 handoff, 결과를 기다리고 다음 단계를 조정하면 orchestration이다.
“Worker 하나당 무조건 worktree 하나”라고 이해하기 쉽지만 항상 그런 것은 아니다.
새 worktree가 현재 작업에 이어지는 변경이라면 new-child, 독립 작업이라면 new-top-level을 선택할 수 있다. 여기서 parent 관계는 Orca 화면에서 작업 공간 사이의 상하 관계를 나타낼 뿐이다. 어느 Git 브랜치에서 시작할지는 별도로 정한다.
Worktrees 공식 문서에서 실제 worktree의 생성과 격리 모델을 더 자세히 확인할 수 있다.
check --wait의 대기 시간이 끝났거나 터미널이 잠시 입력을 기다리는 상태라고 해서 Worker를 바로 종료해서는 안 된다. 코딩 작업은 예상보다 오래 걸릴 수 있다. Worker가 보내는 “아직 작업 중” 상태 신호는 명령어에서 heartbeat라고 부르며, 이는 완료 신호가 아니다.
Worker가 보낸 유효한 worker_done에는 Task ID, Dispatch ID, 성공 또는 실패를 나타내는 결과값이 포함돼야 한다. 자연어 출력만으로 완료를 추측하지 않는 것이 핵심이다.
완료된 Worker는 다음 Task에 재사용하거나, 사용자의 요청에 따라 터미널을 유지하거나, worker-release로 정리해야 한다. 넓은 범위의 terminal close로 대신하면 관련 없는 터미널까지 닫을 수 있다.
Task 사이의 선후 관계를 표현할 수 있다고 해서 모든 절차를 길게 연결할 필요는 없다. 공식 가이드 역시 관리 에이전트가 task-list --ready로 지금 시작할 수 있는 작업을 확인하고, 독립 작업을 묶어 병렬로 실행하되 앞뒤로 이어지는 단계는 대체로 3~4단계보다 깊어지지 않도록 권장한다.
Worktree는 여러 에이전트가 같은 파일을 덮어쓰는 문제를 줄여주는 실행 격리 단위다. 그러나 에이전트가 저장소 밖의 파일이나 외부 시스템에 접근하는 것까지 막아주는 보안 샌드박스는 아니다. 에이전트의 권한과 외부 작업 범위는 별도로 관리해야 한다.
다음과 같은 상황에서는 오케스트레이션의 이점이 크다.
반대로 다음과 같은 경우에는 일반 터미널 명령이나 handoff만으로 충분할 수 있다.
에이전트 수가 늘어날수록 항상 생산성이 높아지는 것도 아니다. 여러 결과를 검토하고 충돌을 조정하는 비용, 모델 사용량도 함께 증가한다. 오케스트레이션은 무조건 많은 worker를 만드는 기술이 아니라, 독립적으로 나눌 가치가 있는 작업을 명확한 책임 경계로 운영하는 방법에 가깝다.
Orca Orchestration의 핵심은 에이전트 수를 늘리는 데 있지 않다.
여러 에이전트가 동시에 실행되는 환경에서 다음 질문에 시스템이 답할 수 있게 만드는 것이 핵심이다.
Git worktree가 파일 변경의 충돌을 줄여준다면, Run·Task·Dispatch는 에이전트 사이의 책임과 상태 충돌을 줄여준다.
단순히 터미널 여러 개를 열어두는 수준에서 한 단계 더 나아가 Codex, Claude Code, Cursor 같은 에이전트들을 하나의 개발 팀처럼 운영하고 싶다면 Orca Orchestration을 살펴볼 만하다.
다만 CLI 명령과 Worker의 질문·상태·완료 보고 규칙은 Orca 버전에 따라 바뀔 수 있다. 오래된 블로그 글의 명령을 그대로 복사하기보다 현재 설치된 Orca에서 다음 명령을 실행해 지금 버전에 맞는 가이드를 먼저 확인하자.
orca skills get orchestration --full