장애를 기록했습니다. 이제 수정 사항이 실제로 작동함을 증명하세요.
요약
AI 에이전트의 운영 중 장애를 재현하고 수정 사항을 검증하는 효과적인 방법론을 제시합니다. 모델을 결정론적으로 만드는 대신, 실행 당시의 프롬프트, 도구 호출, 검색 결과 등을 기록하여 장애 지점에 새로운 코드를 삽입하는 '재생(Replay)' 방식을 권장합니다.
핵심 포인트
- 에이전트 장애 해결을 위해 모델이 아닌 실행 과정을 기록(Record the run)해야 함
- 단순 재실행은 새로운 샘플링과 검색 결과로 인해 버그 재현을 방해함
- 기록된 장애 데이터의 특정 시점을 경계(Boundary)로 설정하여 수정 코드를 삽입하는 방식 권장
- 재생 방식을 통해 모델 호출 비용 없이 결정론적인 버그 수정 검증 가능
Your Agent Failed in Prod. Good Luck Reproducing It의 파트 2입니다.
이 작업은 Susheem Koul과 Tisha Chawla에 의해 AI Engineer World's Fair 2026에서 발표되었습니다.
파트 1에서 에이전트(Agent)는 9:04에 잘못된 레코드를 삭제했으며, 당신은 이를 재현할 수 없었습니다. 해결책은 모델을 결정론적 (Deterministic)으로 강제하는 것이 아니었습니다. 그것은 바로 실행을 기록하는 것 (record the run) 이었습니다. 즉, 정확한 프롬프트 (Prompt), 샘플링된 완성본 (Sampled completion), 도구 호출 (Tool calls), 검색된 청크 (Retrieved chunks), 고정된 모델 버전 (Pinned model version)을 기록하는 것이었습니다. 모델이 아니라 실행을 동결(Freeze)하십시오.
그래서 당신은 그렇게 했습니다. 이제 장애는 디스크 위의 파일이 되었습니다. 당신은 그 파일을 열어 그날 밤 에이전트가 정확히 무엇을 결정했는지 확인할 수 있습니다.
이제 아무도 말하지 않는 부분이 나옵니다. 당신은 여전히 버그를 수정해야 합니다. 그리고 수정 사항이 작동한다는 것을 증명해야 합니다. 바로 이 지점에서 대부분의 팀은 방금 빠져나온 늪으로 조용히 다시 되돌아갑니다.
다시 한번 빠지는 함정
당신은 코드를 수정합니다. 이제 수정이 완료되었는지 확인하고 싶습니다. 그래서 에이전트를 다시 실행하고 지켜봅니다.
멈추세요. 당신은 방금 함정 속으로 다시 걸어 들어갔습니다.
수정 사항을 확인하기 위해 재실행(Re-run)하는 순간, 당신은 재생성(Regenerating)하고 있는 것입니다. 모델은 새로운 경로를 샘플링합니다. 검색(Retrieval)은 약간 다른 청크를 반환합니다. 엔드포인트(Endpoint)의 배치 형태 (Batch shape)는 9:04 당시의 배치 형태와 다릅니다. 당신의
기록된 장애(Incident)를 가져오세요. 그것을 재생(Replay)하세요. 하지만 하나의 경계(Boundary)를 절단 지점(Cut-point)으로 표시합니다. 그 지점의 상류(Upstream)에 있는 모든 것은 기록으로부터 제공되며, 에이전트(Agent)가 그날 밤 보았던 입력값과 바이트 단위로 완전히 동일합니다. 당신이 변경한 경계는 새로운 코드를 실시간(Live)으로 실행합니다. 그 하류(Downstream)의 모든 것 역시 실시간으로 실행되므로, 당신의 수정 사항이 나머지 실행 과정에 어떤 영향을 미치는지 관찰할 수 있습니다.
당신은 에이전트를 다시 실행하는 것이 아닙니다. 얼어붙은(Frozen) 장애의 중간에 당신의 새로운 코드를 떨어뜨리고 단 하나의 질문을 던지는 것입니다: 이 시점까지 정확히 일어난 일을 바탕으로 할 때, 나의 변경 사항이 이제 올바르게 작동하는가?
모델 호출(Model call)도 없습니다. API 비용도 없습니다. 불안정성(Flakiness)도 없습니다. 매번, 영원히, 동일한 장애를 마주하게 됩니다.
단계별 실행 과정
여기에 파트 1에서 사용한 삭제 에이전트(Deletion agent)가 있습니다. 두 개의 경계가 있습니다: 모델이 결정하고, 도구(Tool)가 실행합니다.
from chronicle import boundary, reset_session, ReplayPlan
from chronicle.envelope.store import EnvelopeStore
...
당신은 이미 장애를 기록했고 이를 피스처(Fixture)로 고정했습니다:
session = reset_session()
session.store = EnvelopeStore(".chronicle/runs/incident.jsonl")
session.begin_trace("deletion-incident-001")
...
기록된 그래프는 정확히 예상했던 대로입니다:
agent@1 -> delete_file@1 (deleted prod) -> agent@2
이제 수정 사항입니다. 도구 내에 하나의 가드(Guard)를 추가합니다:
@boundary("delete_file", kind="tool")
def delete_file(path: str, environment: str) -> dict:
if environment == "production":
...
그리고 실제 장애를 대상으로 이를 증명하는 테스트는 다음과 같습니다:
session = reset_session()
session.load_trace("fixtures/traces/deletion-incident-001/")
session.enable_replay(
...
계획(Plan)을 다시 읽어보세요. 이것이 핵심이기 때문입니다. agent@1은 스텁(Stubbed) 처리되었습니다: 모델은 실행되지 않으며, 그날 밤 실제로 내렸던 결정을 재생합니다. delete_file@1은 실시간(Live)으로 실행됩니다: 당신의 새로운 가드가 정확히 해당 인자(Arguments)를 대상으로 실행됩니다. agent@2 또한 실시간(Live)으로 실행됩니다: 에이전트가 성공적인 삭제 대신 거부된 삭제에 어떻게 반응하는지 직접 확인할 수 있습니다.
당신은 하나의 경계(boundary)를 변경했고 나머지 이력은 그대로 유지했습니다. 만약 가드(guard)가 삭제를 차단한다면, 수정 사항은 작동하는 것입니다. 단순히 "한 번 작동했다"가 아닙니다. API 키 없이도, CI 환경에서, 기록된 사고(incident)에 대해 결정론적(deterministically)으로 작동합니다.
두 가지 계층의 활용
Part 1에서는 두 가지 계층에서의 테스트를 주장했습니다. 컷포인트 리플레이(Cut-point replay)는 Layer 1의 실제 작동 사례입니다. 이는 구조적이고 결정론적이며, 제어 흐름(control flow)과 도구 안전성(tool safety)에 관한 것입니다. 올바른 도구가 호출되었는가? 인자(arguments)가 올바르게 구성되었는가? 파괴적인 동작이 거부되었는가? 이 중 어느 것도 모델을 필요로 하지 않으므로, 결과가 불안정하게 변하는 플레이크(flake) 현상이 발생하지 않습니다.
Layer 2는 구조가 답할 수 없는 질문들을 위한 것입니다. 만약 당신의 수정 사항이 프롬프트 재작성(prompt rewrite)이나 모델 업그레이드(model bump)였다면, "출력이 여전히 정확한가"는 동등성 검사(equality check)가 아닌 판단(judgment)의 영역입니다. 바로 그 지점에서 LLM-as-judge가 바이트(bytes) 단위가 아닌 의미(meaning)를 기준으로, 기록된 골드 데이터(gold one)와 새로운 완성본을 비교하여 점수를 매깁니다. Layer 1을 사용하여 기계적 메커니즘이 올바름을 증명하세요. Layer 2를 사용하여 단어들이 여전히 적절함을 증명하세요.
사고가 회귀 테스트(regression test)가 되다
이것이 조용히 찾아오는 보상입니다. fixtures/traces/ 아래에 있는 해당 픽스처(fixture)는 git에 커밋됩니다. 이제 이것은 영구적인 테스트가 되었습니다. 6개월 후, 누군가 도구 라우터(tool router)를 리팩터링하여 가드가 조용히 작동을 멈추더라도, 이 테스트는 고객의 운영 데이터베이스(production database)가 아니라 그들의 풀 리퀘스트(pull request)에서 빨간색으로 표시될 것입니다.
오전 9시 4분에 재현할 수 없었던 실패가 모든 커밋에서 실행되는 초록색 체크 표시가 됩니다. 이것이 사고(incident)와 회귀 테스트(regression test)의 차이입니다. 하나는 당신이 말하는 이야기이고, 다른 하나는 당신의 CI가 강제하는 실체입니다.
커밋하기 전에: 비식별화(redact)
기록된 실행(recorded run)은 운영 환경(production)의 충실한 복사본입니다. 여기에는 조립된 프롬프트, 검색된 청크(retrieved chunks), 도구 인자(tool arguments)가 포함되어 있습니다. 이는 에이전트가 접촉한 고객 이름, 이메일, API 키, 내부 URL 등 무엇이든 포함될 수 있음을 의미합니다.
이를 git에 가공되지 않은 상태로 커밋해서는 안 됩니다. 보안 및 법무 팀이 이를 차단하는 것은 정당하며, 픽스처에서 비밀 정보(secret)가 유출되는 것 자체가 또 다른 실제 사고가 됩니다.
따라서 비식별화 (Redaction)는 기록 경로에서 있으면 좋은 기능 (nice-to-have)이 아니라, 반드시 거쳐야 하는 관문 (gate)입니다. 봉투 (envelope)가 기록되기 전에 비밀 정보 (secrets)와 개인정보 (PII)를 제거하되, 테스트가 검증하는 형태와 구조는 유지하고 민감한 값만 삭제하십시오. 안전하게 커밋할 수 없는 기록은 결국 사용하지 않게 될 기록입니다.
이것이 해결하지 못하는 것
이 기술의 한계에 대해 스스로에게 솔직해지십시오.
컷포인트 리플레이 (Cut-point replay)는 라우팅 (routing), 가드 (guards), 인자 조립 (argument assembly), 도구 안전성 (tool safety), 오케스트레이션 (orchestration) 등 코드 내의 버그를 수정합니다. 이는 해당 상황을 완벽하게 재현하여 저렴한 비용으로 수정 사항을 검증할 수 있게 해줍니다.
하지만 잘못된 생성 (bad generation)을 해결하지는 못합니다. 만약 모델이 환불 금액을 환각 (hallucination)했다면, 리플레이는 그 환각을 그대로 다시 보여줄 것입니다. 이를 수정하는 작업은 결정론적 리플레이 (deterministic replay)가 아니라, 레이어 2 (Layer 2) 및 프롬프트 (prompt)와 모델 작업 영역에서 이루어져야 합니다.
픽스처 (Fixtures) 또한 드리프트 (drift)가 발생합니다. 이를 스냅샷 테스트 (snapshot tests)처럼 취급하십시오. 프롬프트나 스키마 (schema)가 의도적으로 변경되면, 픽스처도 의도적으로 다시 기록되어야 합니다. 또한 호스팅된 모델의 드리프트는 여전히 통제 범위를 벗어나 있으며, 바로 그렇기 때문에 봉투 (envelope)에 버전을 고정 (pin)하여 최소한 언제 변경되었는지는 알 수 있도록 해야 합니다.
요약 (TLDR;)
- 경계 (boundary)에서 기록하십시오. 프롬프트뿐만 아니라 전체 실행 과정을 기록해야 합니다. (파트 1 참조)
- 모델 호출 없이 기록을 리플레이하여 사고를 재현하십시오.
- 변경한 경계를 선택하십시오. 그것이 당신의 컷포인트 (cut-point)입니다.
- 기록의 상류 (upstream)에 있는 모든 것을 스텁 (stub) 처리하십시오. 컷포인트를 라이브로 실행하고 하류 (downstream)를 관찰하십시오.
- 최종 산출물 (prose)이 아니라 컷포인트 결과, 차단 플래그 (blocked flag), 도구 호출 (tool call), 인자 (argument)를 검증 (assert)하십시오.
- 사고가 조용히 다시 발생하지 않도록 트레이스 (trace)를 회귀 테스트 (regression test)로 커밋하십시오.
- 커밋하기 전에 반드시 비식별화 (redact)하십시오. 항상 말입니다.
직접 도구를 구축하는 대신 이미 만들어진 도구를 사용하고 싶다면, 기록, 컷포인트 리플레이, 그리고 2계층 검증 기능을 Chronicle이라는 오픈 소스 라이브러리에 담아두었습니다: github.com/theagentplane/chronicle. 아직 초기 단계이며 한계점에 대해서도 솔직하게 공개하고 있습니다. 이슈 제보나 경험담(war stories)은 언제나 환영합니다.
에이전트 워크플로우 (agentic workflow)를 기록하고 재생하려면 설치하세요
pip install agent-chronicle
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기