dev.to

I forked a live AI agent three ways, and every copy came up with its web server already running

실행 중인 AI 에이전트를 세 갈래로 포크했더니 복사본마다 웹 서버가 그대로 살아 있었습니다

DigitalOcean Managed Agents의 마이크로VM을 체크포인트하고 세 갈래로 포크해 실행 상태가 복제되는지 실험했습니다. 복사본마다 같은 PID의 웹 서버가 실행 중이었고, 롤백 뒤에는 삭제한 파일과 종료한 프로세스도 복구됐습니다. 재실행보다 정확한 상태 보존이 포크의 장점이지만 체크포인트 시간과 세션별 이력 제한도 확인했습니다.

AI 요약

코딩 에이전트 작업에서 다시 얻기 어려운 것은 최종 결과물만이 아닙니다. 탐색과 실패, 파일 수정이 쌓여 만들어진 작업 상태도 가치가 있습니다. DigitalOcean Managed Agents는 세션마다 마이크로VM을 실행하고 머신 전체를 체크포인트한 뒤 포크하거나 롤백하는 기능을 제공합니다. 글쓴이는 이 기능이 실제로 어떤 상태를 보존하는지 작은 웹 앱으로 시험했습니다.

체크포인트와 포크

OpenCode와 DeepSeek v4 Pro에 가상의 커피 로스터리 상태 대시보드를 만들도록 요청했습니다. 외부 리소스 없이 단일 HTML 파일로 작성하는 작업이었고, 첫 생성은 91.6초 걸렸습니다. 샌드박스 안에서 Python 웹 서버를 실행한 뒤 런타임 포트 포워딩으로 로컬 브라우저에 연결했습니다. 터널은 로컬호스트에만 열리고 샌드박스 내부 서비스는 외부에 공개되지 않았습니다.

작동하는 대시보드를 체크포인트하는 데 25.23초가 걸렸고, 체크포인트 하나에서 세 세션을 포크하는 데 15.29초가 걸렸습니다. 포크한 뒤 별도 지시를 내리기 전 확인하니 세 복사본 모두 PID 593의 웹 서버가 실행 중이었고, 각각 같은 6,695바이트 파일을 HTTP 200 응답으로 제공했습니다. 단순히 디스크를 복사한 뒤 새로 부팅한 것이 아니라, 체크포인트 시점에 살아 있던 프로세스까지 포함한 실행 중인 머신을 복제한 결과입니다.

세 포크에는 각각 스칸디나비아풍 미니멀 디자인, 복고풍 녹색 CRT 터미널 디자인, 기존 디자인에 7일 차트를 추가하는 작업을 맡겼습니다. 작업 시간은 25.6~46.7초였습니다. 서버는 파일을 요청할 때마다 디스크에서 읽었기 때문에 에이전트가 파일을 수정하는 동안에도 계속 변경된 내용을 제공했습니다. 다만 차트를 추가한 결과는 겉보기와 달리 축의 수치와 막대 길이가 맞지 않았습니다. 실행 상태를 그대로 복제해도 결과물의 정확성까지 보장하지는 않는다는 사례입니다.

재실행과 롤백 비교

글쓴이는 같은 모델에 같은 프롬프트를 새 세션에서 다시 줬지만 다른 앱이 나왔습니다. 색상과 헤더, 재고량과 주문 수, 배치 번호가 모두 달랐습니다. 새 실행은 31.3초가 걸렸습니다. 처음에는 포크가 설정 시간을 아껴 준다고 주장하려 했지만, 두 번의 생성 시간 차이가 커 그런 결론은 뒷받침되지 않았습니다. 글에서 남긴 포크의 장점은 속도가 아니라 원하는 작업 상태를 정확히 이어받는다는 점입니다. 프롬프트를 다시 실행하면 같은 결과를 보장하지 않습니다.

롤백 시험에서는 부모 세션의 웹 서버를 종료하고 앱 디렉터리도 삭제했습니다. 터널 연결이 끊긴 뒤 세션을 체크포인트로 되돌리는 데 5.59초, 준비 상태가 될 때까지 6.04초가 걸렸습니다. 파일은 복구됐고, 종료했던 서버도 PID 593으로 다시 실행됐습니다. 원래 화면과 롤백 뒤 화면을 픽셀 단위로 비교하니 792,000픽셀 중 88픽셀만 달랐습니다. 차이는 CSS 애니메이션으로 움직이는 상태 표시 점에만 있었습니다.

세션 생성에는 15.4초, 실행 중 세션 체크포인트에는 약 25.2초가 걸렸습니다. 실험에 든 비용은 27센트였으며, 대부분 추론 비용이었습니다. 글쓴이는 체크포인트가 플랫폼 작업 중 가장 오래 걸리므로 자주 생성할 때 시간을 고려해야 한다고 설명합니다.

확인한 제약과 운영상 실수

포크한 세션에서 부모 세션이 만든 체크포인트로 롤백하려 하자 404 오류가 났습니다. 체크포인트 기록은 생성한 세션에만 속합니다. 포크는 부모의 머신 상태를 물려받지만 체크포인트 이력은 물려받지 않습니다. 포크 내부에서 되돌릴 지점을 만들려면 해당 포크에서 별도로 체크포인트해야 합니다.

정리 과정에서는 pkill -f "harness-runtime port-forward" 명령이 실행 중인 셸 명령행까지 찾아 셸을 종료했습니다. 그 결과 세션 삭제 스크립트가 끝까지 실행되지 않아 다섯 세션이 남았습니다. 글쓴이는 정리 스크립트를 신뢰하기보다 실행 뒤 세션 목록을 확인해야 한다고 덧붙입니다. 서비스는 당시 한 지역에서 제공하는 공개 프리뷰였고, 체크포인트는 세션 간 공유되지 않았습니다.

dev.to 반응

  • @dhruv_malaviya — 세 포크에서 PID가 똑같이 유지된 점은 재시작이 아니라 메모리 상태까지 복제했다는 증거입니다. 재부팅 후 재생성했다면 PID가 달라졌을 테니 이 부분을 명시할 가치가 있습니다. 디스크 체크포인트는 파일, 설치된 의존성, 설정, 빌드 캐시와 Git 상태를 보존합니다. 코딩 에이전트 작업에서 비용이 큰 부분은 대개 여기에 있습니다. 메모리 체크포인트는 실행 중인 서버, 열린 소켓, 워밍된 JIT, RAM에만 있는 상태를 추가로 보존합니다. 작업 결과의 여러 갈래를 살피려면 보통 디스크 상태면 충분하지만, 진행 중인 실행을 이어가려면 메모리 상태가 필요합니다. 체크포인트 당시 메모리에 있던 자격 증명도 포크마다 복사된다는 위험도 있습니다. 세 복사본의 신원이 같은지, 각각 달라지는지 확인했나요?
  • @mateo_ruiz_6992b1fce47843 — 가장 흥미로운 점은 체크포인트가 파일 시스템뿐 아니라 런타임 상태까지 저장한다는 것입니다. 저장소 복제와 달리 프로세스와 의존성, 이미 만들어진 실행 상태까지 분기합니다. 실제 에이전트 작업에서는 체크포인트를 단순한 편의 기능이 아니라 복구 경계로 다루겠습니다. 중요한 도구 호출이나 아키텍처 변경 전에 정상 상태를 저장하면 상황을 다시 구성하는 대신 결정적으로 롤백할 수 있습니다. 포크가 머신 상태는 물려받지만 체크포인트 이력은 물려받지 않는다는 점도 중요합니다. 상태 상속과 복구 이력은 서로 다른 개념입니다. 차트 오류도 재현 가능한 상태가 정확한 결과를 보장하지 않는다는 점을 잘 보여줍니다.
  • @anh_nguynvn_0478e614ba — PID가 그대로라는 점은 디스크 스냅샷이나 컨테이너 재시작이 아니라 실제 메모리 체크포인트라는 강한 증거입니다. 재시작했다면 커널이 곧바로 새 PID를 할당했을 것입니다. 이 차이는 에이전트가 작성한 코드뿐 아니라 워밍된 캐시와 활성 네트워크 소켓을 포함한 전체 실행 환경을 보존한다는 뜻입니다. 디스크 스냅샷은 코딩 작업의 진행 상황을 저장하는 데 좋고, 메모리 포크는 실행 환경의 상태를 잃지 않은 채 에이전트의 사고 흐름을 분기하는 데 적합합니다. 난수와 엔트로피도 살펴야 합니다. 특정 PRNG 상태를 쓰는 에이전트라면 메모리 복제로 포크들이 지나치게 같은 방식으로 동작할 수 있습니다. labagent.tech/
  • @hayrullahkar — PID 593에는 실제 작업을 포크하기 전에 시험해 볼 점이 있습니다. 메모리를 복사하면 모든 난수 생성기의 상태도 복사합니다. 시드가 고정된 장기 실행 프로세스나 Python random 모듈은 체크포인트 이후 세 포크에서 같은 수열을 만들 수 있습니다. /dev/urandom이 새로 읽힐 때도 반복되는지는 게스트 커널이 VM generation ID 같은 신호를 받아 복제 사실을 알고 재시드하는지에 달려 있습니다. 각 포크가 깨어난 직후 head -c 16 /dev/urandom | xxd를 실행해 비교하면 확인할 수 있습니다. 바이트가 같으면 서로 다른 포크에서 만든 UUID, 세션 토큰, 멱등성 키가 충돌할 수 있습니다. 롤백에도 같은 경계가 있습니다. 마이크로VM 내부는 되돌리지만 외부로 이미 보낸 API 호출, 푸시, 메시지는 취소하지 않습니다. 위험한 작업 앞에 체크포인트를 두면 머신은 보호하지만, 이미 외부에 전달한 내용까지 되돌리지는 못합니다.
  • @argumentmoney8117 — “포크는 순간을, 스냅샷은 작업물을 보존한다”는 표현이 기억에 남았습니다. 디스크 스냅샷은 읽을 수 있는 상태를 저장하고, 메모리 포크는 PID 593처럼 파일에 없는 상태도 저장합니다. 다만 실행 중인 자격 증명 문제가 실제 운영에서 쓰기 전에 해결해야 할 중요한 주의점입니다. 비밀 정보를 가진 머신을 포크한다면 신원 관리 방안을 먼저 마련해야 합니다.

원문: dev.to / 번역·요약: Trawling