버그를 잡아주는 AI 에이전트, 재현 단계부터 자동으로 구축하는 방법
스스로 버그를 고치는 AI 에이전트는 단 하나의 규칙을 지킬 때 작동합니다: 재현하지 못하면, 고치지 않는다. 에이전트는 버그 리포트를 오늘 실패하는 테스트로 바꾸고, 격리된 브랜치에서 코드를 패치한 뒤, 해당 테스트와 전체 스위트를 다시 실행하고, 모든 것이 그린일 때만 보고를 돌려줍니다. 병합은 여전히 사람이 합니다. 버그를 재현할 수 없다면 에이전트는 조용히 넘어갑니다.
DeepSeek Harness 팀은 2026년 11월 1일 슈퍼 에이전트 설계에 대한 에세이에서 이 아이디어를 많은 독자에게 선보였습니다. 이 가이드는 그것을 이번 주 안에 구축할 수 있는 파이프라인으로 바꾼 것으로, 재현은 에이전트가 직접 만들어 터미널에서 실행하는 API 테스트로 작성됩니다.
재현(repro) 없이는 “에이전트야, 이거 고쳐"가 실패하는 이유
코딩 에이전트에게 버그 리포트의 수정을 요청하면 보통 자신감 넘치는 diff를 받게 됩니다. 하지만 그것이 당신의 버그를 고친 것인지, 에이전트가 상상한 버그를 고친 것인지, 아니면 아무것도 고치지 않은 것인지 알 수 없습니다.
재현 단계가 없으면 세 가지 문제가 생깁니다:
- 에이전트가 원인을 추측합니다. 에러 메시지에서 가장 가능성 높은 줄을 골라 수정합니다.
- "수정됨"의 정의가 없습니다. 유일한 증거는 에이전트 자신의 요약입니다.
- 회귀가 몰래 들어옵니다. 공유 validator에 대한 패치가 하나의 엔드포인트는 고치고 네 개는 망가뜨릴 수 있습니다.
실패하는 테스트는 이 세 가지를 모두 해결합니다. 버그를 고정하고, 완료(done)를 정의하며, 회귀 검사로 스위트에 남습니다.
“조용히 재현하고 수정한다”는 아이디어의 출처
"Exploring Super-agent Design"에서 DeepSeek Harness 팀은 자신들의 사용자 그룹에서 나온 정책을 소개합니다: 누군가 버그를 보고하면 에이전트가 백그라운드에서 재현을 시도하고, 확인된 간단한 수정책이 있을 때만 말을 건다. 그렇지 않으면 아무 말도 하지 않는다는 것입니다.
이 에세이는 이를 스페클레이티브 실행(speculative execution)이라 부르며, 여기서 재사용할 두 가지 요소와 짝을 이룹니다. 워커(worker)는 작업당 하나의 격리된 세션을 받고, 전체 도구와 가장 강력한 모델을 사용하며, 사람이 아니라 라우터에 보고합니다. 왓치독(watchdog)은 각 워커가 진전을 이루고 있는지, 아니면 방황하고 있는지 확인하는 별도의 세션입니다.
한 가지 주의할 점: 이 에세이는 아키텍처를 설명한 것이지 출시된 DeepSeek Harness 기능이 아닙니다. 일부는 프로토타입 플러그인인 dsh-superagent-prototype에 담겨 있으며, 저자들은 이것이 공식 DeepSeek 제품이 아니라고 말합니다. 라우터와 워커 구조에 대해서는 슈퍼 에이전트 구축 방법을 참고하세요.
5단계 버그 수정 에이전트 파이프라인
자가 수정 에이전트는 매번 동일한 루프를 두 개의 게이트와 함께 실행합니다:
- 접수(Intake): 리포트, 실패한 요청, 그에 대한 응답을 수집합니다.
- 재현(Reproduce): 보고된 이유로 실패하는 테스트를 작성합니다. 실패하는 테스트가 없으면 수정하지 않습니다.
- 수정(Fix): 격리된 브랜치나 worktree에서 코드를 패치합니다.
- 재실행(Re-run): 새 테스트가 통과해야 하고, 기존 스위트도 통과해야 합니다.
- 전달(Deliver): 증거와 함께 풀 리퀘스트를 열거나, 조용히 넘어갑니다.
1단계: 버그 리포트 접수
에이전트는 “결제가 또 깨졌어"라는 말만으로는 재현할 수 없습니다. 접수 단계에 고정된 형식을 부여하세요:
| 필드 | 예시 | 중요한 이유 |
|---|---|---|
| 엔드포인트 | POST /orders | 어떤 핸들러를 봐야 하는지 |
| 요청 | "coupon": null이 포함된 본문 | 버그를 유발한 정확한 입력 |
| 실제 응답 | 500, {"error":"internal"} | 테스트가 실패로 봐야 하는 것 |
| 기대 응답 | 주문 id와 함께 201 | 테스트가 단언(assert)하는 것 |
| 환경 | staging | 재현이 실행되는 위치 |
필드가 누락되면 에이전트는 한 번 묻거나 로그에서 요청을 가져옵니다. RFC 9457 problem details 형식을 따르는 에러 본문은 에러 타입이 예측 가능한 형태로 도착하기 때문에 도움이 됩니다.
2단계: 버그를 실패하는 API 테스트로 재현하기
여기가 바로 그 게이트입니다. 에이전트는 접수 기록을 두 개의 단언, 즉 기대하는 상태 코드와 응답에 포함되어야 할 필드를 가진 테스트 케이스로 바꾸고, 실제 환경에서 실행합니다. 세 가지 결과가 가능합니다:
- 보고된 이유로 실패합니다. 재현이 확보된 것입니다. 다음으로 진행합니다.
- 통과합니다. 설명된 대로는 재현되지 않는 버그입니다. 로그에 기록하고 중단합니다.
- 다른 이유로 실패합니다 (인증 에러, 데이터 누락, 타임아웃). 그것은 깨진 재현이지 확인된 버그가 아닙니다. 중단합니다.
첫 번째 경우만 수정을 허용합니다. “조용히"라는 말의 실제 의미가 바로 이것입니다: 나머지 두 경우는 사용자의 채팅에 메시지를 보내는 대신, 큐를 검토하는 담당자를 위한 로그 항목만 남깁니다.
재현은 단위 테스트가 아닌 API 테스트로 작성하세요. 에이전트가 사용자가 사용한 것과 동일한 인터페이스를 호출하기 때문에, 우연히 다른 버그를 재현하는 일이 없습니다.
3단계: 격리된 브랜치에서 코드 수정하기
재현이 빨간불이 되면, 워커는 코드의 자체 사본을 받습니다. git worktree가 가장 가벼운 방법입니다. 새 브랜치에 두 번째 작업 디렉터리를 만드는 것이므로 에이전트의 수정이 당신의 체크아웃에 절대 영향을 주지 않습니다. 거기서 서비스를 실행하고 테스트 환경이 그곳을 가리키게 하세요.
두 가지 제약을 엄격하게 유지하세요. 수정은 작아야 합니다: 3개 파일 또는 50줄 변경 같은 한도를 정하고, 그보다 큰 것은 사람에게 넘길 보고로 취급합니다. 그리고 수정은 재현을 대상으로 해야 합니다: 리팩터링, 이름 변경, 정리 작업은 금지입니다. 모든 추가 변경은 검토자가 확인해야 할 항목 하나가 되기 때문입니다.
4단계: 재현 테스트와 전체 스위트 재실행하기
두 번째 게이트는 두 부분으로 구성됩니다. 먼저 에이전트는 2단계의 동일한 테스트 케이스를 그대로 다시 실행하며, 반드시 통과해야 합니다. 만약 에이전트가 통과하기 위해 단언을 수정했다면 수정은 실패합니다. 파이프라인이 테스트 파일의 실행 전후 diff를 비교해 이를 잡아냅니다.
둘째, 기존 스위트가 그린을 유지해야 합니다. 하나의 테스트를 그린으로 만들고 세 개를 빨간으로 만드는 수정은 3단계로 되돌아갑니다. 루프에 시간 제한을 두세요. 예를 들어 3회 시도 또는 20분을 넘기면 중단하고 시도한 내용을 기록합니다. 왓치독이 빛을 발하는 순간이 바로 여기입니다. 같은 줄만 계속 수정하거나 재현이 전혀 건드리지 않은 파일로 방황하는 워커를 종료시킬 수 있습니다.
5단계: 확인된 간단한 수정만 전달하기
두 게이트가 모두 그린이면, 에이전트는 이야기가 아니라 증거와 함께 풀 리퀘스트를 엽니다: 리포트, 실패한 실행, diff, 그리고 스위트 결과가 포함된 통과한 실행입니다. 사람이 검토하고 병합합니다. Protected branches를 사용하면 에이전트의 토큰이 브랜치를 푸시할 수는 있지만 main에 병합하는 일은 결코 못하게 됩니다. 어떤 게이트라도 실패하면 보고자는 아무런 소식을 듣지 못합니다. 에이전트는 로그 한 줄을 남기고 다음으로 넘어갑니다.
자가 수정 AI 에이전트를 위한 가드레일
첫 무인 실행 전에 이 울타리들을 세워두세요:
| 가드레일 | 설정 | 방지되는 것 |
|---|---|---|
| 범위 | 수정당 최대 파일 수와 줄 수 | 수정으로 둔갑시킨 전면 재작성 |
| 시간 제한 | 버그당 최대 시도 횟수와 시간 | 토큰을 태우는 무한 루프 |
| 자격 증명 | staging 전용, 프로덕션 키 금지 | 실제 주문을 생성하는 재현 |
| 병합 권한 | 브랜치 푸시만, 병합 금지 | 검토되지 않은 코드가 main에 도달 |
| 테스트 무결성 | 테스트 파일의 실행 전후 diff 비교 | 통과하기 위해 단언을 수정하는 행위 |
| 침묵 | 실패 시 사용자에게 메시지 없음 | 소음과 반쯤 확인된 주장 |
자격 증명이 가장 중요합니다. 재현은 API를 실제로 호출하므로 staging이나 시드된 로컬 데이터를 사용하세요.
Apidog CLI로 코딩 에이전트가 재현을 만들게 하기
2단계가 파이프라인의 핵심이며, 바로 Apidog CLI가 만들어진 목적입니다. 코딩 에이전트(Claude Code, Codex, Cursor, OpenCode)가 테스트 케이스를 JSON으로 작성하고, Apidog 프로젝트에 생성한 뒤 터미널에서 실행합니다. 당신은 프롬프트 하나만 작성하면 됩니다.
한 번만 설정하세요:
npm install -g apidog-cli@latest apidog auth login --with-token <YOUR_TOKEN> npx -y skills add https://apidog.com # pick your agent when prompted 그런 다음 에이전트에게 버그 리포트와 이 프롬프트를 넘기세요:
Here is a bug report for POST /orders in Apidog project <projectId>. Turn it into an Apidog test case that fails today: assert status 201 and that $.id exists. Run it against staging and confirm it fails for the reported reason. If it does, fix the handler on a new worktree branch until the same test passes, run the endpoint's other cases, and open a PR with both JSON reports. If it doesn't reproduce, stop and log why. 에이전트는 기억에 의존해 페이로드를 만들지 않습니다. 스키마를 읽고, 카테고리를 찾고, 파일을 검증한 후에야 케이스를 생성합니다:
apidog cli-schema get test-case-create apidog test-case category --project <projectId> apidog cli-schema validate test-case-create --file repro-orders.json apidog test-case create --project <projectId> --file repro-orders.json 에이전트가 작성하는 파일은 다음과 같습니다 (ID는 프로젝트에서 가져옵니다):
{ "name": "Repro: POST /orders with null coupon returns 500", "apiDetailId": 123456, "categoryId": 1, "method": "post", "path": "/orders", "parameters": {}, "commonParameters": {}, "requestBody": { "type": "application/json", "data": "{\"items\":[{\"sku\":\"A-100\",\"qty\":1}],\"coupon\":null}" }, "postProcessors": [ { "type": "assertion", "defaultEnable": true, "enable": true, "data": { "name": "status is 201", "subject": "httpCode", "comparison": "equal", "path": "", "value": "201" } }, { "type": "assertion", "defaultEnable": true, "enable": true, "data": { "name": "order id exists", "subject": "responseJson", "comparison": "exists", "path": "$.id" } } ] } 이제 버그를 증명하는 빨간 실행입니다:
apidog run --test-case <caseId> --project <projectId> -e <stagingEnvId> -r cli,json --out-file repro-before CLI 리포터는 500에서 상태 단언이 실패하는 모습을 보여주고, repro-before.json이 apidog-reports/에 저장됩니다. 수정 후에는 에이전트가 --out-file repro-after로 동일한 명령을 실행하고 두 단언 모두 통과합니다. 이 두 파일이 풀 리퀘스트의 증거입니다. 4단계를 위해 엔드포인트의 모든 케이스를 실행해 수정이 조용히 이웃을 깨뜨리지 못하게 합니다:
apidog test-case run --project <projectId> --endpoint <endpointId> -e <stagingEnvId> -r cli,json --upload-report를 추가하면 실행 결과를 Apidog 앱에서 볼 수 있습니다. 병합 후에는 재현 케이스가 회귀 테스트로 프로젝트에 남고, -r junit을 붙인 동일한 apidog run이 CI에 그대로 들어갑니다. 자세한 내용은 CI/CD 파이프라인에서 Apidog CLI 실행하기를 참고하세요. 추가 설정은 Apidog CLI 에이전트 워크플로와 Claude Code에서의 Apidog CLI를 확인하세요. Apidog Free는 최대 4명의 사용자까지 지원하므로 유료 플랜 없이 전체 루프를 시도해볼 수 있습니다.
FAQ
AI 에이전트가 정말 사람 없이 버그를 고칠 수 있나요?
많은 간단한 버그를 스스로 재현하고, 패치하고, 증명할 수 있지만 병합까지 해서는 안 됩니다. 병합은 사람이 담당하고, 브랜치 보호로 이를 강제하세요.
에이전트가 버그를 재현하지 못하면 어떻게 되나요?
중단하고 시도한 내용을 기록합니다. 재현할 수 없는 버그는 확인할 수 없는 수정이므로, 어떤 패치든 추측에 불과합니다. 이후 사람이 리포트에 세부 정보를 추가하거나 닫습니다.
에이전트가 테스트를 통과하도록 수정하는 것을 어떻게 막을 수 있나요?
테스트 케이스가 처음 실패했을 때 사본이나 해시를 저장하고, 수정을 수락하기 전에 비교하세요. 테스트 파일을 워커가 수정할 수 있는 경로 밖에 두세요.
이것을 만들려면 DeepSeek Harness가 필요한가요?
아니요. 에세이는 설계를 설명한 것이고, 그 프로토타입 플러그인은 공식 DeepSeek 제품이 아닙니다. 셸 명령을 실행할 수 있는 어떤 코딩 에이전트든 작동합니다. GitHub Actions의 Claude Code를 포함해서요. 거기서 시도해보고 싶다면 DeepSeek Harness란 무엇인가를 참고하세요.


