중단된 코딩 에이전트를 로그에서 이어 가는 durable-harness
함수 중단 뒤 작업을 복구하는 로그·큐 구조와, 중복 실행을 막기 위해 개발자가 정해야 할 조건을 설명합니다.
쉽게 말하면비유하자면 요리사가 갑자기 교대해도 주문서에 어디까지 했는지 적혀 있어, 다음 요리사가 끝난 일은 건너뛰고 끊긴 곳부터 이어 가는 방식이다. 다만 결제처럼 두 번 하면 안 되는 일은 실제로 했는지 확인하는 절차를 따로 둬야 한다.
- 왜 봐야 하나
- 코딩 에이전트를 클라우드 서비스로 운영하다 실행 시간 제한 때문에 작업이 끊기는 팀이 살펴볼 도구다. 다만 초기 실험 버전이라 API가 바뀔 수 있고, 성능이나 복구 시간을 잰 수치는 원문에 없다.
이 글은 10월 19일 공개된 durable-harness를 다룬 10월 27일의 새 한국어 해설이다. Vercel이 만든 TypeScript 어댑터 모음으로, 코딩 에이전트의 대화와 호출 기록을 로그에 남겨 함수가 중단돼도 다른 함수가 작업을 이어가게 한다. 결과가 로그에 남은 호출과 끝났는지 불확실한 호출을 구분하는 것이 핵심이다. 해설은 로그·큐의 역할, 도구별 재실행 규칙, 실행 위치와 보안 경계, 셀프 호스팅 조건을 설명한다. 성능을 측정한 연구 논문이 아니라 초기 개발 도구를 이해하기 위한 안내다.
알아낸 것
- 작업의 의도와 결과를 로그에 남기고, 큐가 중단된 턴을 새 함수에 넘깁니다.
- 완료 기록과 중단된 호출을 구분하며 재실행 규칙은 도구와 하네스에 따라 다릅니다.
- Claude Code와 Codex는 자체 서버를 써도 세션별 Vercel Sandbox가 필요합니다.
한계와 주의할 점
- 새 논문이나 성능 실험이 아닌 기존 기술의 새 해설입니다.
- 초기 실험 버전이며 외부 작업의 중복 방지는 멱등성 설계와 결과 확인도 필요합니다.
용어 풀이
- 하네스(Harness)
- 코딩 에이전트를 구동하는 루프로, 프롬프트, 도구, 컨텍스트 관리를 담당한다. durable-harness는 하네스 자체를 고치지 않고 외부에서 내구성을 덧붙인다.
- World
- Workflow SDK의 저장소·큐·스트리머를 묶은 인터페이스. durable-harness는 이 인터페이스에만 의존해 Vercel, 로컬 파일, Postgres 등 다양한 저장소를 선택할 수 있다.
- Vercel Sandbox
- 세션 전용 가상 머신으로, Claude Code와 Codex는 반드시 이 안에서만 실행된다. 파일은 Sandbox보다 오래 남는 Drive의 /workspace에 저장된다.
- 가상 워크스페이스(virtual)
- 함수 안의 just-bash 셸을 가상 파일시스템 위에서 실행하는 환경. 함수의 파일, 프로세스, 환경 변수에는 접근할 수 없고, 파일은 세션 로그에 보존된다.
더 깊이 읽기 읽는 데 약 7분
배경과 문제
코딩 에이전트를 노트북에서 돌릴 때는 하네스가 작업 디렉터리와 세션 기록을 같은 디스크에서 계속 읽을 수 있어, 작업이 끊겨도 사람이 '이어서 해 줘'라고 다시 지시하면 된다. 하지만 에이전트를 클라우드에서 상시 실행하면 사정이 달라진다. 대부분의 하네스는 진행 중인 턴을 그 턴을 실행하는 프로세스의 메모리에 두기 때문에, 서버리스 함수가 시간 제한에 걸리거나 메모리가 부족해 죽으면 그 턴도 함께 사라진다.
가상 머신(VM)과 영구 저장소를 붙이는 것만으로는 어떤 모델 호출과 도구 호출이 끝났는지 기록하거나, 중단된 턴을 다른 프로세스에서 자동으로 이어주지 않는다. Vercel은 이 빈자리를 메우려 durable-harness를 만들었다고 설명한다. 파일이 남아 있다는 것과 진행 중인 작업의 상태를 정확히 복구할 수 있다는 것은 다른 문제다.
기존 접근의 한계
가장 가까운 기존 시도는 durable-harness의 권장 Pi 연결 방식이 그대로 쓰는 Pi Durable이다. Pi Durable은 모델 요청과 도구 호출을 체크포인트를 남기는 태스크로 실행하고, 같은 replay: 'safe' 규칙으로 도구 재실행을 정한다. 다만 SQLite나 JSONL 같은 저장소를 한 번에 한 프로세스만 소유하고 프로세스 사이의 잠금이 없어서, 여러 서버로 나눠 실행하려면 소유권을 애플리케이션이 직접 조율해야 한다.
durable-harness는 Pi Durable의 저장소를 Workflow SDK의 World 인터페이스 위에 올리고 큐를 붙여, 다른 머신의 함수가 세션을 넘겨받을 수 있게 한다. World는 로그를 저장하는 Storage, 끊긴 턴을 다시 배달하는 Queue, 지켜보는 클라이언트에게 이벤트를 보내는 Streamer를 하나의 인터페이스로 묶어 두었다.
동작 방식을 단계별로
durable-harness는 기존 하네스의 동작을 외부에서 기록한다. 호출 의도(Intent)와 완료 결과(Outcome)를 남기고, 턴마다 큐 메시지를 연결한다. 함수를 잃으면 큐가 새 함수에 턴을 넘기고 새 함수가 로그를 읽는다. 다만 실행 전에 로그 기록을 항상 기다리는 것은 아니다. strict 모드는 기다리지만 on 모드의 재실행 가능한 호출은 기록을 기다리지 않고 시작할 수 있다. never 호출은 모든 하네스에서 의도 기록을 기다린 뒤 실행한다.
재개 규칙은 로그를 기준으로 한다. 결과가 로그에 있는 호출은 다시 실행하지 않고 결과를 읽어 오며, 실행 중이던 모델 호출은 다시 실행한다. 크래시 직전에 끝났지만 아직 로그에 기록되지 않은 호출은 실행 중이던 호출로 취급한다. 실행 중이던 도구 호출은 그 도구의 재실행 규칙을 따른다.
재실행 규칙도 하네스에 따라 다르다. replay: 'safe'이면 Pi는 중단된 도구를 자동으로 다시 실행하지만, Claude Code·Codex·OpenCode는 재실행이 안전하다는 정보를 모델에 전달해 판단하게 한다. replay: 'never'이면 하네스가 같은 중단 호출을 스스로 반복하지 않고, 호출이 실행됐을 수도 있다는 상태를 모델에 알려 확인하게 한다. 외부 결제나 메일 전체에 대해 정확히 한 번 실행을 보장하는 규칙은 아니므로, 외부 시스템의 멱등 키와 결과 확인도 필요하다.
결과와 숫자의 의미
소개글이 확인한 npm 패키지는 0.0.1-beta.6이며, 이것이 최초 공개 버전이나 현재 최신 버전이라는 뜻은 아니다. 공식 README는 0.0.x 실험 단계라 릴리스 사이에 API가 바뀔 수 있다고 밝힌다. Claude Code와 Codex 연결도 실험 기능으로 표시된다. 이런 버전 숫자는 성능 결과가 아니라 호환성과 안정성 상태를 읽는 단서다.
지원 대상은 Pi, OpenCode, Codex, Claude Code이고, Vercel이 만든 Zig 기반 코딩 에이전트 하네스 fx용 도구도 포함된다. 같은 회사의 에이전트 프레임워크 eve와 fx는 처음부터 내구성을 갖추고 있으므로, durable-harness는 그렇지 않은 하네스에 같은 성질을 덧붙이는 역할을 한다.
소개글이 정리한 환경은 Node.js 22 이상이고 Agent Runs 연동은 Node.js 24를 요구한다. 하네스의 세션 파일 형식에 의존하므로 패키지 버전도 맞춰야 한다. 글에 나온 Claude Agent SDK 0.3.296, Codex 0.160.0, OpenCode 2.0.22 등의 값은 해당 안내 시점의 조건이다. 실제 도입 때에는 선택한 어댑터의 현재 호환 조건을 다시 확인해야 한다.
구체적인 예시
Vercel의 데모는 에이전트가 코드를 고친 뒤 CI 검사를 기다리는 중 함수가 시간 제한에 걸리는 상황을 보여준다. 일반 방식은 사람이 알아채고 다시 시작할 때까지 멈춘다. 내구성 방식에서는 새 함수가 앞서 완료한 단계의 결과를 로그에서 읽고, 중단된 대기 단계부터 이어 간다. 이는 동작을 보여주는 데모이며 평균 복구 시간을 측정한 실험은 아니다.
블로그의 예제는 주문 조회 도구에 safe, 환불 도구에 never 규칙을 붙인다. 조회는 반복해도 보통 같은 정보를 읽지만, 환불은 중복 실행되면 실제 돈이 두 번 움직일 수 있기 때문이다. never 규칙으로 중단 호출을 자동 재실행하지 않더라도, 모델이 새 환불 요청을 만들거나 외부 응답이 유실될 수 있으므로 같은 업무를 식별하는 멱등 키와 처리 결과 확인이 함께 필요하다.
한계와 오해하기 쉬운 점
durable-harness가 Vercel 인프라와 얼마나 묶여 있는지는 하네스마다 다르다. Pi, OpenCode, fx는 세션 저장과 명령 실행을 Postgres World와 가상 워크스페이스로 Vercel 밖에 둘 수 있지만, Claude Code와 Codex는 직접 운영하는 서버에서도 Vercel Sandbox에서만 실행된다. 서버가 턴을 구동하고 로그를 쓰되, CLI는 Vercel 액세스 토큰으로 실행한 Sandbox 안에서 돌아간다.
보안 측면에서 Sandbox는 기본적으로 모든 외부 통신을 허용하므로, 프롬프트 인젝션에 걸린 모델이 자기 세션의 파일을 외부로 보낼 수 있다. sandbox({ network: 'deny-all' }) 또는 허용 호스트 목록으로 막아야 한다. Codex는 builtins: true일 때 자체 샌드박스를 시작하지 못하면 Sandbox 안에서 전체 권한으로 명령을 실행할 수 있어, 모델의 명령이 함수를 거쳐 개발자의 AI Gateway 크레딧으로 모델을 직접 호출할 수 있다.
성능 수치나 비용 절감률, 복구 시간에 대한 구체적인 벤치마크는 원문에서 확인할 수 없다. Vercel은 블로그에서 끝난 모델 호출의 토큰 비용이 두 번 청구되지 않는다고 설명하지만, 실행 중이던 모델 호출을 다시 실행할 때의 비용에 대한 별도 언급은 없다. 편집자 해석으로는 다시 보낸 요청만큼 토큰을 다시 쓴다고 보는 것이 자연스럽다.
실제로 어떻게 활용할까
durable-harness가 맞는 경우는 코딩 에이전트를 여러 사용자에게 서비스로 제공하면서, 함수 시간 제한이나 재배포 때문에 턴이 끊기는 문제를 겪는 팀이다. 이미 Next.js와 Vercel로 앱을 운영하고 있다면 withDurableHarness 설정 한 줄과 채팅 라우트로 큐 라우트까지 구성되고, Agent Runs 화면에서 세션별 모델 호출과 도구 호출을 추적할 수 있다.
개인 터미널 작업에서 이 구조가 꼭 필요한지는 사용 방식에 따라 다르다. 원문의 편집자는 사람이 중단을 확인해 다시 지시할 수 있다면 얻는 이득이 작을 수 있다고 평가한다. 반면 이 두 하네스는 로컬 개발에서도 Vercel Sandbox 비용이 생긴다. 초기 API의 변경 가능성과 외부 인프라 의존성을 감수할 이유가 있는지 먼저 따져야 하며, 여기서는 설치나 복구 실험을 직접 실행하지 않았다.
원문에서 확인한 근거 5곳
- durable-harness는 호출 의도와 결과를 로그에 기록하고 큐로 중단된 턴을 다른 함수에서 이어 간다.Logs and queues
- 결과가 로그에 있는 호출은 다시 실행하지 않고 결과를 읽어 오며, 실행 중이던 모델 호출은 다시 실행한다. 크래시 직전에 끝났지만 아직 로그에 기록되지 않은 호출은 실행 중이던 호출로 취급한다.Recovery
- 중단된 safe 도구는 Pi가 다시 실행하지만 다른 세 하네스는 모델에 안전성을 알린다. never 호출은 같은 중단 호출을 자동 반복하지 않고 실행 여부가 불확실함을 알린다.What happens to a tool call after a crash
- Claude Code와 Codex는 직접 운영하는 서버에서도 Vercel Sandbox에서만 실행된다. 서버가 턴을 구동하고 로그를 쓰되, CLI는 Vercel 액세스 토큰으로 실행한 Sandbox 안에서 돌아간다.Claude Code, Codex, and OpenCode
- Sandbox는 기본적으로 모든 외부 통신을 허용하므로, 프롬프트 인젝션에 걸린 모델이 자기 세션의 파일을 외부로 보낼 수 있다. sandbox({ network: 'deny-all' }) 또는 허용 호스트 목록으로 막아야 한다.What these controls don't cover
10월 28일(수) 정리 · AI가 쓰고 원문과 대조
AI 목록