
AI 에이전트 개발에 필요한 것은 똑똑한 작업자보다 재현 가능한 제어층이다
요약
AI 에이전트의 개별 성능보다 중요한 것은 여러 에이전트를 관리하고 통합하는 제어층(Control Layer)의 설계입니다. 저자는 Orchestune 개발 경험을 통해 자율성보다 추적 가능성과 결정론적 제어가 개발 공정의 신뢰성을 확보하는 핵심임을 강조합니다.
핵심 포인트
- 에이전트의 지능보다 태스크 분해 및 의존성 관리 등 제어 구조가 중요함
- 자율성(Autonomy)보다 추적 가능성(Traceability)을 우선시해야 함
- 병렬 작업 시 발생하는 충돌과 상태 관리 문제를 해결할 제어 모델 필요
- 실패 지점의 재현과 인간의 개입이 가능한 시스템 설계가 핵심
AI 코딩 에이전트의 성능은 급속도로 향상되고 있습니다.
Issue를 전달하면 코드를 작성하고, 테스트를 실행하며, Pull Request까지 생성합니다. 여러 에이전트를 병렬로 구동하는 것도 기술적으로는 그리 드문 일이 아니게 되었습니다.
하지만 실제로 여러 AI 에이전트에게 하나의 큰 개발 과제를 맡기면, 문제의 중심은 에이전트의 구현 능력이 아니게 됩니다.
중요해지는 것은 다음과 같은 질문들입니다.
- 큰 요구사항을 어떤 단위로 분해할 것인가
- 어떤 태스크를 병렬로 실행해도 괜찮은가
- 여러 변경 사항을 어떤 순서로 통합할 것인가
- 실행 도중 상태를 잃었을 경우, 어떻게 재개할 것인가
- LLM에 의한 판단과 결정론적인 제어(Deterministic Control)를 어디서 분리할 것인가
- 인간은 어느 시점에 개입해야 하는가
이것은 단순히 "AI에게 코드를 쓰게 하는 방법"의 문제가 아닙니다.
AI 에이전트에 의한 개발 공정 그 자체를 어떤 제어 모델로 운용할 것인가의 문제입니다.
저는 이 문제에 대한 하나의 접근법으로서, Orchestune이라는 개발 오케스트레이터(Orchestrator)를 만들고 있습니다.
Orchestune은 원래 AI 소설 집필 도구 개발을 보조하기 위한 메커니즘이었습니다.
하지만 구현과 운용을 진행하면서, 애플리케이션 본체보다 여러 AI 에이전트를 제어하는 메커니즘에 훨씬 더 일반적이고 본질적인 문제가 포함되어 있다는 것을 알게 되었습니다.
이 기사에서는 Orchestune의 기능 소개보다는, 그 개발을 통해 보이기 시작한 기술 사상에 대해 서술합니다.
AI 에이전트의 능력과 개발 공정의 신뢰성은 별개의 문제이다
고성능 AI 에이전트를 사용하면 개별 태스크를 완료할 확률은 높아집니다.
하지만 여러 AI 에이전트를 사용한 개발 전체의 신뢰성은 그것만으로 결정되지 않습니다.
설령 각각의 에이전트가 높은 확률로 올바른 구현을 생성할 수 있다고 하더라도, 다음의 문제들은 남습니다.
- 두 개의 태스크가 동일한 파일을 변경한다
- 한쪽 태스크가 만든 API를 다른 쪽이 서로 다른 전제로 이용한다
- 구현 중에 예정에 없던 공통 모듈이 필요해진다
- 상위 태스크의 변경으로 인해 하위 태스크의 전제가 무너진다
- Pull Request 단독으로는 성공했더라도, 다른 변경 사항과 통합하면 실패한다
- 에이전트는 완료했으나, commit이나 push가 올바르게 이루어지지 않았다
- 실행 프로세스가 사라지고 진행 상태만 남는다
이것은 작업자의 지능과는 다른 차원의 문제입니다.
인간 개발 팀에서도 우수한 엔지니어를 모으는 것만으로는 대규모 개발이 성립되지 않습니다.
필요한 것은 태스크 분해, 의존 관계 관리, 브랜치 전략, CI, 리뷰, 장애 대응, 진척 관리와 같은 제어 구조입니다.
AI 에이전트도 마찬가지입니다.
오히려 AI 에이전트는 인간보다 고속으로 병렬 작업을 할 수 있기 때문에, 제어 구조의 취약성이 더 빨리 현상화됩니다.
따라서 AI 개발의 핵심적인 질문은,
어떤 모델이 가장 똑똑한가
만이 아니라,
불완전하고 실패할 수 있는 작업자를 어떻게 하나의 성과로 수렴시킬 것인가
여야 합니다.
완전 자율성보다 추적 가능성을 우선한다
AI 에이전트 제품에서는 자율성(Autonomy)이 중요한 지표로 이야기됩니다.
인간의 지시 없이 얼마나 오랫동안 움직일 수 있는가. 얼마나 많은 판단을 스스로 내릴 수 있는가. 얼마나 넓은 범위의 작업을 완료할 수 있는가.
하지만 개발 공정에서 자율성은 단독으로는 가치가 되지 않습니다.
자율적으로 움직이더라도,
- 왜 그런 판단을 했는지 알 수 없다
- 어디까지 처리했는지 알 수 없다
- 실패 지점을 재현할 수 없다
- 다른 에이전트에게 인계할 수 없다
- 인간이 나중에 수정할 수 없다
라면 운용 가능한 시스템이라고 말하기 어렵기 때문입니다.
Orchestune에서는 다음과 같은 원칙을 두고 있습니다.
Traceability over autonomy
완전 자율성보다 추적 가능성(Traceability)을 우선한다
AI 에이전트의 내부 세션에만 상태를 갖게 하는 것이 아니라, Issue, Pull Request, branch, commit, CI와 같은 GitHub상의 성과에 상태를 남깁니다.
중요한 것은 단순히 인간이 화면에서 확인할 수 있다는 것이 아닙니다.
후속 시스템이 그곳에 남겨진 정보를 읽고, 다음에 수행해야 할 처리를 판단할 수 있는 것입니다.
추적 가능성은 감사를 위해서만 존재하는 것이 아닙니다.
그 자체로 장애 복구와 작업 지속의 기반이 됩니다.
GitHub를 진실 그 자체가 아닌, 영구적인 증거의 장부로 다룬다
Orchestune의 출발점은 단순했습니다.
GitHub상에서 상태가 보이게 된다면, 여러 AI 에이전트도 관리하기 쉬워지지 않을까
Issue로 태스크 (Task)를 표현하고, 라벨 (Label)로 진행 상황을 나타내며, 브랜치 (Branch)로 작업 영역을 나누고, Pull Request로 성과를 제출하며, CI로 검증합니다.
GitHub에는 개발을 관리하기 위한 도구들이 이미 갖춰져 있습니다.
하지만 실제로는 GitHub 상에 상태가 존재하는 것과 그 상태가 일관성을 유지하는 것은 별개의 문제입니다.
예를 들어, 다음과 같은 상태가 발생할 수 있습니다.
- Issue는 실행 중이지만, 대응하는 프로세스는 이미 중단됨
- Branch는 원격 (Remote)에 존재하지만, 로컬 (Local)에는 존재하지 않음
- Pull Request는 오픈 (Open) 상태지만, 해당 커밋 (Commit)은 이미 다른 경로로 통합됨
- CI 체크가 존재하지 않는 것인지, 아니면 가져오지 못한 것인지 알 수 없음
- 에이전트 (Agent)는 코드를 작성했지만, 푸시 (Push)에는 실패함
- 라벨 업데이트 후, 상태 파일 저장 전에 실행 환경이 소멸함
이때 Issue의 라벨만을 정답으로 취급할 수는 없습니다.
Pull Request의 존재만으로도 불충분합니다.
Branch의 존재나 CI 결과 또한 그것 단독으로는 진실을 나타내지 않습니다.
따라서 Orchestune에서는 GitHub를 유일한 진실 그 자체로 다루는 것이 아니라,
상태를 복원하기 위한 영속적인 증거가 저장되는 장소
로 취급합니다.
Issue, 라벨, Branch, Commit, Pull Request, CI의 정보를 조합하여, 결정론적인 규칙 (Deterministic rule)에 의해 현재의 유효한 상태를 도출합니다.
GitHub가 장부라면, Orchestune은 그 장부를 해석하는 리컨실러 (Reconciler)입니다.
상태 관리가 아니라, reconciliation을 설계한다
일반적인 애플리케이션에서는 상태가 데이터베이스에 저장됩니다.
현재의 상태를 하나의 값으로 기록하고 그 값을 업데이트합니다.
하지만 AI 에이전트에 의한 개발 공정에서는 단일 상태 값만으로는 불충분합니다.
외부에서 Branch가 업데이트될 수도 있습니다.
사람이 Pull Request를 머지 (Merge)할 수도 있습니다.
다른 에이전트가 Issue 라벨을 변경할 수도 있습니다.
CI의 완료는 비동기적 (Asynchronous)입니다.
로컬 실행 환경은 폐기될 수도 있습니다.
즉, 시스템 외부에서도 상태가 변화합니다.
이러한 환경에서는 올바른 상태를 한 번 저장하는 것보다,
관측 가능한 사실을 반복해서 다시 읽고, 바람직한 상태와의 차이(Difference)를 수정하는 것
이 중요해집니다.
이것이 reconciliation (조정/화해)의 사고방식입니다.
Orchestune에서는 개념적으로 다음 루프를 수행합니다.
- GitHub와 로컬 환경으로부터 현재 상태를 관측한다
- 태스크, Branch, Pull Request, CI의 관계를 재구성한다
- 현재 상태가 유효한지 검증한다
- 다음에 실행 가능한 태스크를 선택한다
- 필요에 따라 디스패치 (Dispatch), 중단, 재시도, 통합을 수행한다
- 다음 실행 시 다시 전체를 관측한다
이 설계에서는 한 번의 처리가 완전히 성공하는 것을 전제로 하지 않습니다.
도중에 중단되더라도, 다음 실행 시 상태를 재관측하여 처리를 계속할 수 있는 것을 목표로 합니다.
중요한 것은 처리의 성공률이 아니라, 반복 실행함으로써 안전한 상태로 수렴하는 성질입니다.
태스크를 풀기 전에, 풀 수 있는 구조로 분해한다
AI 에이전트는 큰 요구사항을 그대로 전달해도 어느 정도 자율적으로 분해할 수 있습니다.
하지만 하나의 에이전트가 내부적으로 수행한 분해는 외부에서 검증하기 어렵고, 여러 에이전트의 협업에도 활용하기 어렵다는 문제가 있습니다.
Orchestune에서는,
Decompose before solve
먼저 풀기보다 분해하여 관리 가능하게 만든다
라는 원칙을 채택하고 있습니다.
큰 요구사항을 구현하기 전에,
- 서브 태스크 (Sub-task)
- 변경 예정 파일
- 변경 예정 심볼 (Symbol)
- 명시적 의존 관계 (Explicit dependency)
- 공유 인터페이스 (Shared interface)
- 리스크 (Risk)
- 통합 순서
를 외부화합니다.
여기서 중요한 점은 분해가 단순한 할 일 목록 (ToDo list)이 아니라는 것입니다.
분해 결과는 후속되는 디스패치, 배타 제어 (Mutual exclusion), 통합, 복구에 이용되는 실행 계획입니다.
즉, 계획 문서인 동시에 기계가 해석하는 제어 구조이기도 합니다.
사람은 개별 에이전트 조작을 일일이 승인하는 것이 아니라, 이 구조가 타당한지를 확인합니다.
이를 통해 인간의 판단을 구현의 세부 사항이 아닌 시스템 전체의 구조에 집중시킬 수 있습니다.
병렬화의 본질은 동시 실행이 아니라 안전한 독립성의 증명이다
여러 에이전트를 동시에 구동하는 것은 쉽습니다.
어려운 것은 그것들이 정말로 독립되어 있는지를 판단하는 것입니다.
두 개의 태스크가 서로 다른 Issue로 기술되어 있더라도, 동일한 파일을 변경할 가능성이 있습니다.
서로 다른 파일을 변경하더라도, 동일한 공개 API (Public API)나 설정 파일에 의존할 수도 있습니다.
나아가, 현시점에는 존재하지 않는 공유 확장 포인트 (Shared extension point)를 각 에이전트가 개별적으로 새로 만들려고 시도하는 경우도 있습니다.
따라서 병렬화란 단순히 작업 수를 늘리는 것이 아닙니다.
여러 변경 사항이 서로의 전제를 해치지 않고 통합 가능한지를 어디까지 사전에 확인할 수 있는가
라는 문제입니다.
Orchestune에서는 변경 예정인 파일이나 심볼 (Symbol)을 풋프린트 (footprint)로 선언하고, 그 중복으로부터 암묵적인 의존 관계를 추정합니다.
하지만 문자열 일치만으로는 불충분합니다.
예를 들어 두 개의 태스크가 아직 존재하지 않는 형식 레지스트리 (Format registry)를 필요로 할 때, 한쪽은 format_registry.py를, 다른 한쪽은 serializers/__init__.py를 상정한다면 단순한 경로 비교만으로는 충돌을 감지할 수 없습니다.
그렇기 때문에 공유 확장점을 shared_contract로 명시하고, 이를 소유하는 태스크와 이에 의존하는 태스크를 분리합니다.
이는 파일 단위의 충돌 관리가 아니라, 설계상의 계약 단위로 병렬성을 관리하려는 시도입니다.
안전한 병렬화를 위해서는 코드의 현재 모습뿐만 아니라, 앞으로 만들어질 구조에 대한 이해가 필요합니다.
망가진 에이전트가 아니라, 망가진 계획을 수리한다
AI 에이전트가 실패했을 때 가장 단순한 대응은 재실행 (Re-execution)입니다.
하지만 여러 태스크를 병렬로 진행하고 있는 경우, 실패 원인이 해당 에이전트에게만 있는 것은 아닙니다.
예를 들어, 어떤 에이전트가 예정되지 않은 파일을 변경했다고 가정해 봅시다.
이때 다른 태스크와의 독립성이 상실되었을 가능성이 있습니다.
상위 태스크가 공개 API를 변경하면 하위 태스크의 전제가 무너집니다.
외부의 사람이 동일한 파일을 변경하고 있다면, 기존의 실행 계획은 안전하지 않습니다.
이 경우 재실행해야 하는 것은 동일한 태스크가 아닙니다.
검토해야 하는 것은 태스크 간의 관계입니다.
Orchestune에서는,
Reschedule instead of restart
망가지면 전부 다시 하는 것이 아니라, 국소적으로 재계획한다
라는 원칙을 세우고 있습니다.
변경된 풋프린트나 외부 작업의 상태를 재관측하고, DAG를 재계산하여 필요한 태스크만 정지하거나 재배치합니다.
에이전트의 실행을 중심으로 생각하면 실패 시의 조작은 재시도 (retry)가 됩니다.
계획을 중심으로 생각하면 실패 시의 조작은 조정 (reconcile)이 됩니다.
이 차이는 매우 크다고 생각합니다.
생성적인 구현과 결정론적인 통합을 분리한다
LLM은 구현에 있어 강력합니다.
모호한 요구사항을 해석하고, 기존 코드를 읽으며, 필요한 변경 사항을 추측할 수 있습니다.
반면, 다음과 같은 판단을 LLM에게만 맡기는 것은 위험합니다.
- 정말로 커밋 (commit)이 존재하는가
- CI가 통과되었다고 간주해도 되는가
- 브랜치 (branch)를 삭제해도 되는가
- Issue를 완료 처리해도 되는가
- Pull Request를 머지 (merge)해도 되는가
- 동일한 처리를 재실행해도 안전한가
이것들은 가능한 한 동일한 입력으로부터 동일한 출력을 얻어야 하는 판단들입니다.
Orchestune에서는,
Deterministic integration over heuristic judgment
직관적인 리뷰보다 결정론적인 통합을 우선한다
라는 원칙을 채택하고 있습니다.
LLM에 의한 코드 리뷰는 유익하지만, 그것을 유일한 품질 게이트 (Quality gate)로 삼지는 않습니다.
통합 전에 실제 브랜치를 가상 머지 (仮merge)하고, CI를 실행하며, 그 결과를 바탕으로 통합 여부를 결정합니다.
LLM은 의미론적인 모순이나 설계상의 우려를 지적할 수 있습니다.
하지만 기계적으로 판정할 수 있는 부분은 CI나 Git의 사실을 우선합니다.
여기서 목표로 하는 것은 LLM의 배제가 아닙니다.
LLM이 잘하는 판단과 결정론이 필요한 판단을 분리하는 것입니다.
LLM은 상태 수복을 위한 탐색 장치로 사용한다
실운용에서는 결정론적인 규칙만으로는 다룰 수 없는 상태가 발생합니다.
그럴 경우 LLM에게 Issue, Pull Request, branch, CI, 로그를 읽게 하고 "원인을 봐줘"라고 요청하면, 상당히 높은 확률로 타당한 가설을 제시합니다.
LLM은 여러 개의 약한 증거들을 조합하는 데 능숙합니다.
예를 들어,
- Issue 라벨은 실행 중
- Pull Request는 open
- 차분 (diff)은 비어 있음
- branch는 존재함
- CI는 일부만 누락됨
- 직전에 rebase됨
이러한 정보로부터, 단순한 구현 실패가 아니라 branch 참조의 불일치를 의심할 수 있습니다.
이 능력은 매우 유용합니다.
하지만 LLM의 판단에는 재현성(reproducibility) 문제가 있습니다.
동일한 상태라도 모델, 프롬프트(prompt), 획득된 컨텍스트(context)에 따라 서로 다른 복구안을 제시할 가능성이 있습니다.
따라서 Orchestune에서는 LLM을 최종적인 상태 결정자로서가 아니라,
미지의 상태에 대한 진단 및 복구 방법의 탐색 장치
로 위치시키는 것이 좋다고 생각합니다.
LLM이 제안한 복구는 가능하다면 나중에 다음과 같은 형태로 변환합니다.
- 명시적인 상태 전이 (state transition)
- 정합성 체크 (consistency check)
- fail-closed 방식의 판정
- retryable(재시도 가능)과 fatal(치명적)의 분류
- 멱등한 (idempotent) 복구 처리
- 회귀 테스트 (regression test)
이 순환을 정리하면 다음과 같습니다.
- LLM이 미지의 장애를 진단한다
- 인간 또는 시스템이 복구한다
- 원인과 복구 조건을 추출한다
- 결정론적인 (deterministic) 규칙으로 변환한다
- 회귀 테스트로 고정한다
- 기지의 장애로서 자동 처리한다
즉,
LLM은 복구 지식을 발견하고, 제어층은 그것을 재현 가능한 사양(specification)으로 바꾼다
라는 관계입니다.
같은 버그가 줄어드는 것보다, 미지의 장애를 흡수할 수 있는 것이 중요하다
Orchestune의 개발에서는 실제 운용을 시작한 후 많은 결함이 발견되었습니다.
Git의 remote 참조, CI 결과의 누락, 완료 판정, 상태 저장, worktree 뒷정리, 외부 락(lock), Pull Request 획득 건수 등, 경계 조건(boundary condition)이 차례차례 나타납니다.
이러한 종류의 시스템에서는 버그가 존재한다는 사실 자체만으로 설계가 실패했다고 단정할 수 없습니다.
중요한 것은 동일한 종류의 장애가 재발하고 있는가입니다.
같은 원인이 반복되고 있다면 시스템이 학습하지 못하고 있는 것입니다.
반면, 매번 다른 경계 조건이 발견되고 그때마다 불변 조건(invariant)이나 회귀 테스트가 추가되고 있다면, 미지였던 상태 공간(state space)을 탐색하고 있다고 볼 수 있습니다.
지향해야 할 수렴은 버그가 제로가 되는 것이 아닙니다.
새로운 장애가 발생하더라도 안전한 정지, 진단, 복구, 회귀 방지의 기존 경로 내로 수렴하는 비율이 높아지는 것
입니다.
신뢰성 높은 오케스트레이터(orchestrator)란 실패하지 않는 시스템이 아니라, 실패를 지식으로 변환할 수 있는 시스템이라고 생각합니다.
인간은 개별 작업이 아니라, 구조를 승인한다
AI 에이전트를 사용할 때 인간이 모든 조작을 확인하고 있다면 병렬화의 이점이 사라집니다.
반면, 완전히 자율화하면 잘못된 계획이 고속으로 실행될 위험이 있습니다.
이 사이의 균형을 맞추기 위해 Orchestune에서는,
Humans approve structure, not every action
인간은 개별 작업이 아니라, 구조를 승인한다
라는 사고방식을 채택하고 있습니다.
인간의 주요 승인 지점은 두 가지입니다.
첫 번째는 구현 전의 분해 구조입니다.
- 태스크 경계가 타당한가
- 의존 관계가 올바른가
- 병렬화해도 괜찮은가
- 공유 인터페이스가 명시되어 있는가
를 확인합니다.
두 번째는 모든 하위 태스크가 통합된 최종 Pull Request입니다.
중간의 하위 태스크마다 인간이 매번 merge 판단을 내리는 것이 아니라, CI를 통과한 변경 사항을 부모 branch에 통합하고 최종 성과만을 인간이 수락합니다.
이는 인간을 개발 공정에서 배제하는 설계가 아닙니다.
인간의 판단력을 국소적인 작업 확인이 아니라, 구조 설계와 최종 수락에 집중시키는 설계입니다.
실행 에이전트는 교체 가능하며, 제어층이 자산이 된다
AI 모델이나 코딩 에이전트는 앞으로도 급격하게 변화할 것입니다.
현재 가장 성능이 높은 에이전트가 몇 달 후에도 같은 위치에 있으리라는 보장은 없습니다.
특정 에이전트 내부에
- 태스크 상태
- 진척도
- 작업 이력
- 의존 관계
- 복구 지식
를 가두어 버리면, 에이전트를 변경했을 때 제어 구조까지 상실됩니다.
Orchestune에서는,
Workers are replaceable, orchestration is the asset
실행 에이전트는 교체 가능하며, 가치는 제어층에 있다
라는 원칙을 두고 있습니다.
구현을 담당하는 에이전트는 Claude Code든 Codex든, 혹은 다른 로컬 에이전트든 상관없습니다.
중요한 것은 누구에게 무엇을 할당하고, 어떤 상태에서 정지하며, 어떤 성과가 남고, 어떤 순서로 통합하는지가 에이전트 외부에 저장되어 있다는 점입니다.
이러한 구조가 있다면 작업자를 교체하더라도 개발 공정을 지속할 수 있습니다.
AI 개발에서의 장기적인 자산은 특정 모델에 대한 프롬프트가 아니라,
- 작업 분해 규칙
- 상태 전이 (State Transition)
- 안전성 조건
- 복구 규칙
- 통합 전략
- 장애 지식
이 된다고 생각합니다.
부모 브랜치를 사이에 두는 2층 모델로, 인간의 승인을 마지막 한 번으로 집약한다
여러 개의 하위 태스크를 병렬로 구현할 수 있더라도, 각각이 개별 Pull Request로서 main으로 향한다면, 인간은 모든 Pull Request를 순서대로 리뷰해야만 합니다.
이렇게 되면 구현을 AI 에이전트에게 병렬화하더라도, 마지막 통합 공정에서 인간이 병목 현상 (Bottleneck)이 됩니다.
Orchestune에서는 이 문제에 대해, 부모 Issue 전용 브랜치를 사이에 두는 2층 모델을 채택하고 있습니다.
예를 들어 부모 Issue가 #100이라면, 먼저 다음과 같은 부모 브랜치를 만듭니다.
parent/issue-100
각 하위 태스크의 브랜치는 직접 main에서 파생되는 것이 아니라, 이 부모 브랜치를 기준으로 만들어집니다.
하위 태스크의 구현이 완료되면, 해당 Pull Request는 main이 아니라 parent/issue-100으로의 통합을 목적으로 처리됩니다.
개념적으로는 다음과 같은 구조입니다.
하위 태스크의 변경 사항은 먼저 일시적인 통합 환경에서 부모 브랜치로 가마ージ (仮マージ, temporary merge)되어 CI를 통한 검증을 받습니다.
CI를 통과하면 해당 변경 사항은 부모 브랜치로 자동 반영됩니다. 하위 Issue도 완료된 것으로 처리되어, 인간이 하위 태스크마다 Pull Request를 열고 merge 버튼을 누를 필요가 없습니다.
반면, 모든 하위 태스크가 부모 브랜치로 통합된 후, parent/issue-100에서 main으로 향하는 최종 Pull Request가 생성됩니다.
이 최종 Pull Request만은 자동 머지되지 않습니다.
인간이 전체 변경 사항을 확인하고, 최종적으로 main에 반영할지를 판단합니다.
이 2층 구조를 통해 인간의 승인은,
각 하위 태스크의 Pull Request
하위 태스크 간의 통합
중간 브랜치 (Intermediate branch)의 업데이트
가 아니라, 최종 성과를 main에 반영하는 단 한 번의 판단으로 집약됩니다.
중요한 점은 단순히 리뷰 횟수를 줄이는 것이 아니라는 것입니다.
하위 태스크를 인간이 확인하지 않는 대신, 부모 브랜치로 통합하기 전에는 실제 변경 사항을 조합한 상태에서 CI를 실행합니다.
즉, 품질 게이트 (Quality Gate)를,
하위 태스크별 인간의 육안 리뷰
에서,
실제 통합 결과에 대한 결정론적인 CI 검증
으로 옮기고 있습니다.
이를 통해 AI 에이전트가 생성한 여러 변경 사항을 인간이 일일이 조작하지 않아도, 하나의 부모 성과로 단계적으로 수렴시킬 수 있습니다.
인간이 확인하는 것은 개별 작업 과정이 아니라, 최종적으로 구성된 '커다란 돌덩이' 전체입니다.
이 2층 모델은,
"Humans approve structure, not every action"
이라는 Orchestune의 설계 원칙을 Git의 브랜치 구조로 구현한 것이기도 합니다.
GitHub Ops형 AI 오케스트레이션
Orchestune을 만드는 과정에서, 저는 이 설계 영역을 가칭 'GitHub Ops형 AI 오케스트레이션'이라고 부르고 있습니다.
GitHub를 단순한 코드 호스팅이나 결과물 제출처가 아니라,
- 영속적인 상태 장부 (State Ledger)
- 태스크 큐 (Task Queue)
- 감사 로그 (Audit Log)
- 인간과의 협업 면
- CI를 통한 검증 면
- 장애 복구의 증거
- 에이전트 제어의 입력
으로서 다루는 사고방식입니다.
Issue에서 태스크를 읽고, branch와 Pull Request로부터 실행 결과를 관측하며, CI로부터 통합 가능성을 판단하고, 불일치가 있으면 재조정합니다.
이는 AI 소프트웨어 개발을 위한 GitHub 네이티브한 reconciliation engine (조정 엔진)이라고 표현할 수 있습니다.
GitHub Ops형이라는 이름 자체가 중요한 것은 아닙니다.
중요한 것은,
AI 에이전트의 내부 세션이 아니라, 외부화된 개발 상태를 중심으로 제어계를 설계한다
라는 사상입니다.
오케스트레이터는 AI 개발자의 상위에 있는 제어 평면 (Control Plane)이다
코딩 에이전트는 코드를 작성하는 작업자입니다.
오케스트레이터는 작업자들을 모아놓은 채팅방이 아닙니다.
그 책무는,
- 과제를 관리 가능한 단위로 분해한다
- 병렬 실행의 안전성을 판단한다
- 의존 관계를 유지한다
- 외부 변경 사항을 관측한다
- 실행 상태를 재구성한다
- 실패 시 계획을 수정한다
- 여러 성과를 하나로 통합한다
- 인간이 판단해야 할 지점을 한정한다
것입니다.
이러한 관점에서 Orchestune은 multi-agent coding tool이라기보다,
coding agent를 위한 개발 제어 평면 (Control Plane)
에 가깝습니다.
개별 AI가 똑똑해질수록, 동시에 실행할 수 있는 작업량도 늘어납니다.
그리고 작업량이 늘어날수록 의존성 (Dependency), 경합 (Conflict), 통합 (Integration), 복구 (Recovery)의 중요성은 높아집니다.
따라서 에이전트의 성능 향상은 오케스트레이터 (Orchestrator)를 불필요하게 만드는 것이 아니라, 오히려 그 필요성을 증가시킬 가능성이 있습니다.
요약
AI 에이전트 개발에서 가장 중요한 것은 에이전트를 몇 대나 움직일 수 있느냐가 아닙니다.
중요한 것은,
불완전하고 실패할 수 있는 여러 작업자를 재현 가능한 방법으로 하나의 결과물로 수렴시킬 수 있는가
입니다.
이를 위해서는 다음과 같은 사항이 필요합니다.
- 문제를 풀기 전에 구조화할 것
- 완전 자율성보다 추적 가능성 (Traceability)을 우선할 것
- 상태 (State)를 저장할 뿐만 아니라, 반복적으로 재조정할 것
- 병렬화하기 전에 독립성을 검증할 것
- 실패한 작업자가 아니라, 망가진 계획을 수리할 것
- 생성적인 구현과 결정론적인 (Deterministic) 통합을 분리할 것
- LLM의 진단을 재현 가능한 규칙으로 변환할 것
- 인간은 개별 조작이 아니라 구조를 승인할 것
- 실행 에이전트가 아니라 제어층 (Control Plane)에 지식을 축적할 것
Orchestune은 AI 소설 집필 도구의 보조 기구로 시작되었습니다.
하지만 그곳에서 발견한 본질적인 문제는 소설 집필에 국한된 것이 아니었습니다.
그것은 AI가 작업자가 되는 시대에, 개발 공정을 어떻게 설계할 것인가에 대한 문제였습니다.
AI 에이전트가 개발자라면, 그 위에는 계획, 상태, 경합, 복구, 통합을 담당하는 제어층이 필요합니다.
그리고 그 제어층에 요구되는 것은 더 높은 지능이 아니라,
재현성 (Reproducibility), 추적 가능성 (Traceability), 멱등성 (Idempotency), 그리고 안전하게 수렴하는 메커니즘
이라고 생각합니다.
GitHub 리포지토리
본 기사에서 소개한 Orchestune은 GitHub에 공개되어 있습니다.
아직 개발 단계에 있지만, AI 에이전트에 의한 개발 공정을 재개 가능하고, 추적 가능하며, 재현 가능한 형태로 제어하기 위한 구현과 시행착오를 공개하고 있습니다.
Discussion

AI 자동 생성 콘텐츠
본 콘텐츠는 Zenn AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기