코딩 에이전트에게 수정 위치를 추측하게 하는 것을 그만둔 이유
요약
코딩 에이전트가 저장소의 구조와 소유권을 잘못 추측하여 발생하는 실수를 방지하기 위해, 결정론적인 데이터 기반의 핸드오프(handoff) 방식인 Doc Bridge를 제안합니다. 에이전트에게 추론을 맡기는 대신 읽기 시작할 위치, 수정 가능 범위, 검증 방법 등의 명확한 컨텍스트를 제공하는 것이 핵심입니다.
핵심 포인트
- 에이전트의 실수는 코드 자체보다 잘못된 컨텍스트 파악에서 시작됨
- 전역 지침(AGENTS.md)만으로는 대규모 저장소의 패키지 경계를 관리하기 어려움
- Doc Bridge를 통해 에이전트에게 명확한 작업 범위와 검증 데이터를 제공
- LLM 없이도 작동하는 결정론적 계층을 통해 에이전트의 추론 정확도 향상
코딩 에이전트(coding agents)에게서 보이는 대부분의 실수는 잘못된 코드에서 시작되지 않습니다.
그것은 한 단계 더 앞선 지점에서 시작됩니다.
에이전트는 잘못된 문서를 열고, 인접한 패키지가 변경 사항을 소유하고 있다고 가정하며, 범위(scope) 밖이어야 할 디렉토리를 수정하고, 마지막에는 자신이 변경한 패키지에 대해 거의 알려주지 않는 저장소 전체 테스트(repository-wide test)를 실행하며 마무리합니다.
AGENTS.md에 문단을 하나 더 추가하는 것도 도움이 되지만, 대규모 저장소(repository)의 모든 패키지 수준 질문에 답할 수는 없습니다. 전역 지침 파일(global instruction file)은 "패키지 경계를 존중하라"라고 말할 수는 있습니다. 하지만 어떤 패키지가 인증(authentication)을 담당하는지, 어떤 파일을 먼저 읽어야 하는지, 또는 어떤 두 가지 체크가 인증 변경이 안전하다는 것을 증명하는지를 에이전트에게 항상 알려줄 수는 없습니다.
저는 그 답이 조언(advice)이 아닌 데이터(data)가 되기를 원했습니다.
수정 전 내가 원했던 핸드오프 (handoff)
auth 패키지와 관련된 작업을 수행할 때, 유용한 컨텍스트(context)는 놀라울 정도로 작습니다:
{
"startHere": "docs/for-agents/packages/auth.md",
"editRoots": ["packages/auth"],
...
이것은 에이전트에게 작업을 어떻게 해결할지 알려주는 것이 아닙니다. 창의력이 필요하지 않은 네 가지 질문에 답하는 것입니다:
- 어디서부터 읽기 시작해야 하는가?
- 어디를 수정할 수 있는가?
- 어떤 체크가 변경 사항을 증명하는가?
- 어떤 사용자용 가이드가 동일한 기능을 설명하는가?
그 차이가 중요합니다. 저는 여전히 에이전트가 구현(implementation)에 대해 추론하기를 원합니다. 하지만 에이전트가 저장소의 소유권(ownership)을 스스로 만들어내기를 원하지는 않습니다.
1분 만에 아이디어 재현하기
저는 이러한 핸드오프를 중심으로 Doc Bridge를 구축했습니다. 이 결정론적 계층(deterministic layer)은 LLM이나 API 키를 필요로 하지 않습니다.
저장소를 준비할 필요 없이 번들로 제공되는 모노레포(monorepo) 피스처(fixture)를 실행할 수 있습니다:
npx --yes @agentskit/doc-bridge@1.2.4 demo --fixture monorepo --text
데모는 실패 모드(failure mode)로 시작합니다:
Before (agent guesses package)
✗ edits packages/billing when task mentions "auth"
✗ runs repo-wide test instead of package checks
그다음 핸드오프를 해결합니다:
After (handoff.resolve / query --agent)
✓ target: auth (packages/auth)
✓ start: docs/for-agents/packages/auth.md
...
이 피스처(fixture)는 게이트(gate)가 누락된 인덱스에서 새로운 인덱스로 이동하는 모습도 보여줍니다. 이 부분이 중요합니다. 6개월 전에 생성된 올바른 핸드오프(handoff)가 오늘날에도 반드시 올바른 것은 아닙니다.
실제 모노레포(monorepo)에 대한 해답
저는 공개된 AgentsKit 모노레포에서도 동일한 쿼리를 실행해 보았습니다:
pnpm exec ak-docs query package core --agent
관련 출력 결과는 다음과 같습니다:
{
"target": {
"type": "package",
...
이 결과는 유용합니다. 왜냐하면 core는 저장소 내의 대부분의 패키지보다 더 엄격한 규칙을 가지고 있기 때문입니다. core는 런타임 의존성(runtime dependencies)이 전혀 없으며 크기 예산(size budget)이 정해져 있습니다. 그곳에서 작업하는 에이전트는 형제 패키지(sibling package)를 변경하거나 잘못된 테스트를 실행한 후에야 이러한 제약 사항을 발견해서는 안 됩니다.
글로벌 규칙(global rules)은 여전히 중요합니다. 핸드오프는 readBeforeEditing에 AGENTS.md를 명시적으로 포함합니다. 핵심은 저장소 지침(repository instructions)을 대체하는 것이 아니라, 작업을 지침의 올바른 부분으로 라우팅(route)하는 것입니다.
문서 드리프트(Documentation drift)는 눈에 보이게 실패해야 합니다
인덱스를 생성하는 것만으로는 충분하지 않습니다. 소유권이 변경됩니다. 패키지가 이동합니다. 사람이 작성한 가이드의 이름이 바뀝니다. 팀은 어제의 저장소를 가리키는, 세련되게 기계가 읽을 수 있는(machine-readable) 답변을 갖게 될 수도 있습니다.
그렇기 때문에 저는 최신성(freshness)을 CI(지속적 통합) 문제로 취급합니다:
pnpm docs:bridge:gate
동일한 AgentsKit 체크아웃 상태에서 게이트는 다음과 같이 보고했습니다:
- 인덱스가 최신 상태임;
- 25개의 사람용 문서(human-documentation) 링크가 해결됨;
- 25개의 핸드오프가 시작 문서, 편집 루트(edit roots), 체크 사항 및 사람용 링크를 보유함;
- 필수적인 7가지 Documentation Standard v1 규칙을 모두 통과함.
인덱스가 재생성되지 않은 상태에서 입력값이 변경되면, 최신성 해시(freshness hash)가 변경되어 게이트가 실패합니다. CI 내부에서 파일을 조용히 재빌드하고 커밋된 컨텍스트가 최신인 것처럼 가장하지 않습니다.
이러한 동작은 의도된 것입니다. 검사하기 전에 스스로의 증거를 수정해 버리는 게이트는, 원래 감지해야 했던 드리프트(drift)를 숨길 수 있기 때문입니다.
왜 RAG로 시작하지 않았는가
저장소 검색(Repository search)과 RAG는 질문이 개방형(open-ended)일 때 유용합니다:
- 속도 제한(rate limiting)에 대한 논의는 어디에 있는가?
- 인증(authentication) 설계에서 무엇이 변경되었는가?
- 어떤 문서들이 마이그레이션(migration)을 언급하고 있는가?
소유권(Ownership)은 다른 종류의 질문입니다. 만약 저장소가 이미 packages/auth가 인증을 담당한다는 것을 알고 있다면, 의미론적 유사성(semantic similarity)이 packages/billing이 거의 관련이 있는 것처럼 결정하도록 허용해서는 안 됩니다.
제가 선호하는 순서는 다음과 같습니다:
- 정확한 소유권 이관(ownership handoff)을 해결합니다.
- 지정된 시작 문서(starting documents)를 읽습니다.
- 추가적인 컨텍스트(context)를 위해 검색 또는 RAG를 사용합니다.
- 선언된 루트(declared roots) 내부에서만 편집합니다.
- 선언된 체크(checks)를 실행합니다.
결정론적인(deterministic) 답변이 먼저 나옵니다. 확률론적인(probabilistic) 검색은 이를 대체하는 것이 아니라 확장합니다.
이 접근 방식의 비용
이 계약(contract)은 작지만, 공짜는 아닙니다.
누군가는 소유권을 정의해야 합니다. 패키지 체크(Package checks)는 정확해야 합니다. 사람이 작성한 문서 링크가 존재해야 합니다. 인덱스(index)는 커밋되어야 하며 최신 상태로 유지되어야 합니다. 제대로 관리되지 않는 라우팅 맵(routing map)은 에이전트에게 잘못된 확신을 주며, 이는 답을 모른다고 인정하는 것보다 더 나쁠 수 있습니다.
또한 정당한 경계를 넘나드는 작업들도 있습니다. 파괴적인 계약 변경(breaking contract change)은 여러 패키지에서의 조율된 편집을 요구할 수 있습니다. 이 경우, 이관(handoff) 과정에서 더 넓은 범위를 설명하거나 인간의 결정을 강제해야 합니다. 횡단 관심사(cross-cutting) 변경 사항을 하나의 편리한 디렉토리에 억지로 끼워 넣어서는 안 됩니다.
목표는 모든 작업을 로컬(local)로 만드는 것이 아닙니다. 범위를 명시적으로 만드는 것입니다.
에이전트 스택을 변경하지 않고 추가하기
가장 작은 도입 경로는 다음과 같습니다:
npm install --save-dev @agentskit/doc-bridge@1.2.4
npx ak-docs init
npx ak-docs index
...
그 후 동일한 이관(handoff) 정보를 CLI 또는 MCP를 통해 노출할 수 있습니다. 코딩 에이전트에게 Doc Bridge 전용의 추론 전략이 필요한 것은 아닙니다. 에이전트에게 필요한 것은 편집하기 전에 이관(handoff)을 해결하고, startHere를 읽고, editRoots 내부에 머물며, checks를 실행하는 것입니다.
저는 Emerson Braun이며, Doc Bridge를 만들고 유지 관리하고 있으므로 이 도구에 대해 중립적인 관찰자는 아닙니다. 제가 이 컨트랙트(contract)를 공유하는 이유는 제품 설명(product description)을 신뢰하지 않고도 쉽게 테스트할 수 있기 때문입니다. 픽스처(fixture)를 실행하고, JSON을 검사하고, 인덱스(index)를 오래된 상태(stale)로 만든 뒤, 게이트(gate)가 실패하는 것을 지켜보기만 하면 됩니다.
만약 귀하의 리포지토리(repository)가 이 컨트랙트가 제대로 처리하지 못하는 형태를 가지고 있다면, 저는 추상적으로 작성된 또 다른 기능 요청(feature request)을 받기보다 차라리 그 사례를 보고 싶습니다. 어색한 리포지토리들이야말로 라우팅 모델(routing model)이 더욱 정직해지는 지점입니다.
준비 과정에 대한 공개: 저는 이 초안을 정리하고 비판하는 데 AI 도구들을 사용했습니다. 저는 명령어를 직접 실행했고, 캡처된 출력값을 공개 리포지토리(public repositories)와 대조하여 확인했으며, 모든 기술적 주장(technical claim)을 검토하였고, 최종 텍스트에 대해 책임을 집니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기