내가 AI 소프트웨어 팩토리를 운영하는 방법: 분산 에이전트, 경계 검사, 그리고 증거 추적
요약
AI 코딩 에이전트를 대규모로 운영할 때 발생하는 리스크를 관리하기 위해 'AI 소프트웨어 팩토리' 개념을 제안합니다. 모델 자체보다 실행의 경계(입력, 권한, 계약, 최종 검사)를 결정론적인 CLI 도구로 검증하는 구조적 접근법을 설명합니다.
핵심 포인트
- 에이전트 운영의 핵심 리스크는 모델이 아닌 실행의 경계(Edges of the run)에 있음
- 물리적 공장처럼 입고, 권한, 계약, 최종 검사 단계의 경계 검사가 필요함
- 검사 도구는 LLM의 추측이 아닌 결정론적이고 재현 가능한 로컬 CLI여야 함
- handoff-lint를 통해 작업 지침의 구조적 완전성을 사전에 검증함
아래에서 언급되는 네 가지 도구는 github.com/officialwhitebird에서 오픈 소스로 제공됩니다.
AI 코딩 에이전트 (AI coding agents)를 한 번에 하나의 프롬프트 (prompt)씩 실행할 때는 모델 (model)이 관찰의 대상이 됩니다. 하지만 수많은 작은 작업들을 에이전트에게 맡기고, 그것들이 디프 (diffs), 파일, 결과 기록으로 돌아오는 대량의 작업을 실행할 때는 모델이 더 이상 흥미로운 리스크 (risk)가 아닙니다. 흥미로운 리스크는 **실행의 경계 (edges of the run)**로 이동합니다. 즉, 무엇이 입력되었는지, 무엇이 돌아왔는지, 에이전트가 무엇을 건드릴 수 있도록 허용되었는지, 그리고 나가는 과정에서 무엇이 대중에게 공개되는 복사본 (copy)에 작성되었는지가 중요해집니다.
이는 물리적인 공장 (physical factory)이 주의를 기울이는 곳과 동일합니다. 단일 기계에 집중하는 것이 아니라, 스테이션 (stations) 사이의 경계에 집중합니다. 즉, 입고 검사 (incoming inspection), 작업 권한 부여 (work authorization), 각 스테이션이 충족해야 하는 계약 (contract), 그리고 제품이 출하되기 전의 최종 검사 (final inspection)와 같은 것들입니다. 그럴싸해 보이는 출력을 생성하지만 이러한 경계 검사 (boundary checks) 중 하나라도 통과하지 못한 실행은 성공이 아닙니다. 그것은 완성된 것처럼 보일 뿐인 결함 (defect)입니다.
이 글은 제가 AI 코딩 실행을 위해 이러한 규율을 어떻게 구조화하는지, 그리고 각 경계를 막연한 느낌이 아닌 명시적이고 결정론적인 (deterministic) 단계로 만들기 위해 사용하는 소수의 로컬 오프라인 커맨드 라인 검사기 (command-line checkers)들에 대한 설명입니다.
AI 실행의 네 가지 경계
단일 AI 코딩 실행에는 네 가지 실질적인 경계가 있습니다. 각각은 실행이 조용히 잘못될 수 있는 지점이며, 모델이 무엇을 하기 전이나 후에 기계적으로 검사할 수 있는 지점입니다.
| 경계 (Boundary) | 질문 (The question) | 검사 (The check) |
|---|---|---|
| 입력 (Input) | 작업 지침 (work instruction)이 구조적으로 완전한가? | handoff-lint |
| ... |
이 도구들 중 그 어떤 것도 모델을 호출하지 않습니다. 그 어떤 것도 파일을 호스팅된 서비스로 전송하지 않습니다. 각각은 파일을 읽고, 결정론적 규칙 (deterministic rules)을 적용하며, 종료 코드 (exit code)와 발견된 항목 목록을 반환하는 작은 로컬 CLI (Command Line Interface)입니다. 검사 자체가 지루하고, 오프라인이며, 재현 가능하다는 이 속성이 핵심입니다. 다시 실행했을 때 동일한 결과를 얻을 수 있는 검사여야만 인간의 결정 앞에 둘 수 있는 검사가 됩니다. 검사 자체가 LLM의 추측이라면, 그것은 단지 감사 (audit)를 위해 한 번 더 실행해야 할 또 다른 작업일 뿐입니다.
1. 입력 경계 (Input boundary) — 에이전트가 확인하기 전의 지침
대부분의 잘못된 실행은 에이전트가 시작되기도 전에 이미 잘못되어 있습니다. 작업 지침 (work instruction)에 수락 기준 (acceptance criteria)이 누락되었거나, 범위 제한 (scope bounds)이 없거나, 에이전트가 _하지 말아야 할 것_을 명시한 섹션이 없는 경우입니다. handoff-lint는 작업 지침을 읽고 그것이 구조적으로 완전한지 검사합니다. 즉, 에이전트가 작업 범위 내에 머물기 위해 필요한 메타데이터, 섹션, 경계값 등을 확인합니다.
이 도구는 지침이 _좋은 아이디어인지_를 판단하지 않습니다. 지침이 _인계하기에 충분히 완전한지_를 검사합니다. 이 둘은 서로 다른 질문이며, 이 둘을 분리하여 유지하는 것이 검사의 정직함을 유지하는 비결입니다.
2. 실행 권한 경계 (Execution-authorization boundary) — 실행 전의 명령
에이전트가 명령 (command)을 제안합니다. 어떤 명령은 감독 없이 실행해도 괜찮습니다. 어떤 명령은 절대 실행해서는 안 됩니다. 어떤 명령은 그 중간에 위치합니다. 외부 연결, 유료 서비스, 파괴적인 작업, 또는 공개적인 작업 등 인간이 명시적으로 승인해야 하는 것들이 이에 해당합니다. policy-lint는 제안된 명령을 선언된 로컬 정책 (local policy)에 따라 분류하고, 허용 (allow), 소유자 승인 필요 (owner-gate), 거부 (reject), 금지 (forbidden) 중 하나의 판결을 반환합니다.
내가 가장 중요하게 생각하는 판결은 _owner-gate_입니다. 이것은 아무것도 차단하지 않습니다. 대신 "사람이 이것을 결정한다"는 순간을 로그를 읽고 있는 누군가에게 맡기는 대신, 가시적이고 기계적인 절차로 만듭니다. 권한은 사람에게 머뭅니다. 도구는 단지 그 결정이 침묵 속에 이루어지는 것을 거부할 뿐입니다.
3. 실행 계약 경계 (Execution-contract boundary) — 신뢰하기 전의 결과물
에이전트(agent)가 돌아와서 작업이 완료되었다고 말합니다. 무엇에 대해 완료된 것일까요? 실행 전, 나는 계약(contract)을 선언합니다: 존재해야 할 출력물, 수행되었어야 할 검증(verification), 준수되었어야 할 게이트(gates)들입니다. 실행 후, contract-lint는 기록된 결과와 선언된 계약을 비교하여 서로 일치하지 않는 부분을 보고합니다.
이것은 에이전트 작업에서 가장 비용이 많이 드는 실패 모드(failure mode)를 잡아내는 경계입니다: 즉, 실제로는 자신의 조건을 충족하지 못했음에도 불구하고, 자신감 있고 잘 작성된 결과 기록을 내놓는 경우입니다. 차이점(diff)은 깔끔해 보일 수 있지만 여전히 계약의 절반을 놓칠 수 있습니다. 이 둘을 결정론적(deterministically)으로 비교하는 것이 "완료된 것처럼 보이는 것"을 검증 가능한 "완료되었으며, 여기 그 기록이 있음"으로 되돌리는 방법입니다.
4. 출력 경계 (Output boundary) — 외부로 나가기 전의 공개 복사본
마지막 경계는 작업이 외부에서 어떻게 보이는지를 결정하는 경계입니다. README, 릴리스 노트(release note), 포스트 등이 이에 해당합니다. 여기서 두 가지 문제가 일상적으로 발생합니다: 실행 자체의 증거(evidence)로 뒷받침되지 않는 주장(claims), 그리고 공개되어서는 안 될 내부 명칭이나 비공개 경로(private paths)입니다. claim-lint는 설정된 규칙 세트에 따라 공개용 텍스트를 스캔하여 이 두 가지를 모두 보고합니다.
나는 내 작업물에도 이를 실행합니다. 이 네 가지 도구를 하나로 묶어주는 팩(pack)의 README는 게시되기 전에 이러한 방식으로 스캔되었습니다. 여기에는 내부 명칭이나 비공개 경로가 포함되지 않았는지 확인하는 절차도 포함되었습니다. 이 확인 작업은 단순한 예의가 아닙니다. 이는 문서를 게시하는 것과 버퍼(buffer)에 들어있던 무엇이든을 게시하는 것 사이의 차이입니다.
왜 "다른 모델에게 묻기"가 아니라 결정론적이고 로컬(local)이어야 하는가
이 모든 것에 대한 명백한 대안은 두 번째 LLM (Large Language Model)에게 첫 번째 모델의 작업물을 검토하도록 요청하는 것입니다. 저는 작업 자체에는 모델을 사용합니다. 하지만 세 가지 이유로 인해 경계 검사 (boundary checks)에는 모델을 사용하지 않습니다.
- 재현성 (Reproducibility). 결정론적인 (deterministic) 검사는 동일한 입력에 대해 매번 동일한 판결을 내립니다. 저는 그 판결을 결정의 근거로 삼고 나중에 이를 방어할 수 있습니다.
- 감사 가능성 (Auditability). 종료 코드 (exit code)와 결과 목록은 기록이 됩니다. "검토 모델이 보기에 괜찮다고 느꼈다"는 기록이 될 수 없습니다.
- 호스팅된 의존성 없음 (No hosted dependency). 모든 검사는 작업과 동일한 머신에서 오프라인으로 실행됩니다. 경계 검사 과정에서 실행 결과나 코드를 어디론가 전송해야 할 필요가 전혀 없습니다.
목표는 인간을 제거하는 것이 아닙니다. 오히려 그 반대입니다. 각 검사는 인간이 결정을 내려야 하는 바로 그 순간에 깨끗하고 기계적인 결과물을 인간 앞에 제시하기 위해 존재하며, 모든 것이 완료된 것처럼 보인다는 이유로 그 순간을 건너뛰지 않도록 보장하기 위해 존재합니다.
이것이 의도적으로 하지 않는 것
주장의 경계를 정확히 하는 것은 이 규율의 일부이므로, 다음과 같습니다:
- AI 코딩 실행을 수행하지 않습니다.
- 샌드박싱 (sandboxing)이나 보안 경계를 강제하지 않습니다.
- 출력이 의미론적으로 (semantically) 올바르다는 것을 증명하지 않습니다.
- 외부의 유료, 파괴적 또는 공개적인 작업에 대한 인간의 승인을 대체하지 않습니다.
- 호스팅된 서비스로 그 어떤 것도 전송하지 않습니다.
각 도구는 하나의 경계를 결정론적으로 검사하고 결정을 다시 돌려줍니다. 이러한 좁은 범위는 의도적인 것입니다. 더 많은 일을 할 수 있는 척하는 검사기는, 검사기들이 잡아내기 위해 존재하는 바로 그 '자신감 넘치지만 검증되지 않은 출력물'과 정확히 일치할 것이기 때문입니다.
더 큰 형태
이 네 가지 도구 중 어느 것도 단독으로는 인상적이지 않습니다. 이 도구들이 합쳐져서 만드는 것은 분산된 반자율적 작업(에이전트에게 맡겨진 작업)을 실행하는 방법입니다. 여기서 시스템을 하나로 묶어주는 것은 모든 단계를 지켜보는 중앙 컨트롤러가 아니라, 어떤 스테이션의 출력이 유효한 것으로 인정받기 전에 반드시 통과해야 하는 일련의 경계 검사와 증거 추적 (evidence trail)입니다.
그러한 구조는 소프트웨어에만 국한된 것이 아닙니다. 중앙 집중식 감독(central supervision) 대신 명시적인 경계 검사(boundary checks)와 검증 가능한 기록(checkable record)에 의해 결합되어 실제 작업을 수행하는 분산된 단위(distributed units)라는 동일한 개념은, 일반적인 조정된 생산(coordinated production)이 작동하는 방식이기도 합니다. 저는 오늘날 엔드 투 엔드(end-to-end)로 구축할 수 있는 영역인 소프트웨어 분야에서 이를 구축하고 있습니다. 위에 언급된 도구들은 그 구조의 첫 번째이자 가장 작으며, 완전히 작동하는 버전입니다.
이것들은 github.com/officialwhitebird에 게시된 로컬 오프라인 명령줄 검사기(command-line checkers)입니다. 각 검사기는 하나의 경계를 검사하며, 최종 결정권은 인간 운영자(human operator)가 보유합니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기