Pi Durable
Pi Durable — 장시간 실행과 복구를 지원하는 에이전트 하네스
Pi Durable은 중단 뒤에도 작업을 이어가고 여러 사용자가 함께 조작하는 에이전트 애플리케이션을 만들기 위한 TypeScript 프레임워크입니다. 작업 체크포인트, 재실행 정책, 대화별 문서와 확장 기능을 제공하며, 현재는 API가 바뀔 수 있는 실험 단계입니다.
- 주제
에디터 노트
Pi 1.0의 다음 소식입니다. 에이전트 자체가 아니라 에이전트를 오래 돌리는 하네스입니다. 중단 복구, 체크포인트, 한 번의 제출 처리, 대화 포크까지 갖춘 TypeScript 프레임워크입니다. HN의 @lukebuehler 지적이 재밌습니다. LangChain Deep Agents, Vercel Eve, OpenAI Agents API, Anthropic Managed Agents까지 주요 업체가 모두 이 영역에 제품을 만들고 있다고 합니다. 무인 장기 실행, 하네스와 컴퓨팅 분리, 다중 사용자 때문입니다. 다만 @zmmmmm의 아쉬움도 있습니다. 샌드박싱이 일급 기능이 아니라는 점입니다. 신뢰 경계에 걸친 기능이라 하네스 기본에 들어가야 한다는 주장입니다.
AI 요약
Pi 팀은 Pi 1.0과 함께 장시간 실행하는 에이전트 애플리케이션을 위한 실험용 패키지 Pi Durable을 공개했습니다. 기존 Pi 코딩 에이전트는 한 사람이 자기 머신의 터미널에서 사용하고, 프로세스가 끝나면 상황을 살펴 이어서 지시하는 형태입니다. Pi Durable은 이 에이전트를 대체하지 않습니다. 대신 여러 실행 환경과 클라이언트에서 접근하고, 프로세스 장애를 복구하며, 여러 사람이 같은 에이전트를 조작하는 애플리케이션을 만드는 하네스입니다.
하네스와 저장소
Pi Durable에서 하네스는 대화 기록과 대규모 언어 모델을 실행하는 데 필요한 도구·실행 환경을 함께 관리합니다. 도구는 노트북, 원격 가상 머신, 메모리 샌드박스 등 대화별 실행 환경에서 작동합니다. 모델 호출부터 도구 실행까지 하네스가 처리하는 작업은 모두 태스크로 기록합니다.
저장소 구현으로 메모리, SQLite, JSONL을 제공합니다. SQLite와 JSONL 코드는 Node API에 의존하지 않아 어댑터를 붙이면 Bun이나 Cloudflare Durable Object에서도 실행할 수 있습니다. 저장소 인터페이스도 작게 설계해 키-값 저장소나 PostgreSQL을 연결할 수 있습니다. SQLite 사용 시 메모리에는 활성 대화 기록과 실행 중인 태스크, 제출 대기 중인 요청만 둡니다. 이전 대화는 컨텍스트 한도에 가까워지면 요약하므로 수만 개의 메시지가 쌓여도 전체 기록을 메모리에 올리지 않습니다. 저장소 하나는 한 프로세스가 소유하고, 다른 클라이언트는 그 프로세스에 접속합니다.
중단 복구와 동시 실행
실행 단계마다 체크포인트를 저장합니다. 프로세스가 종료되면 새 프로세스가 같은 저장소를 열어 미완료 태스크를 마지막 체크포인트부터 이어갑니다. 중간에 끊긴 모델 요청은 다시 보내고, 일부 응답은 중단된 상태로 대화 기록에 남깁니다. 도구는 재실행이 안전하다고 선언한 경우에만 다시 호출합니다. 배포처럼 반복 실행이 위험한 도구는 모델에 중단 사실을 알립니다. requestId를 지정한 제출은 정확히 한 번만 처리하므로, 클라이언트가 장애 뒤 재시도해도 같은 제출 결과를 돌려받습니다.
하나의 하네스에서 여러 대화를 동시에 실행할 수도 있습니다. 대화는 특정 시점의 기록을 기준으로 분기할 수 있으며, 분기 대화는 부모 기록을 복사하지 않고 해당 지점까지 공유합니다. 예를 들어 Slack 채널과 스레드를 각각 대화로 만들면 둘은 서로의 처리를 막지 않고 병렬로 동작합니다. 대화마다 모델, 도구, 추가 지침, 작업 디렉터리를 따로 설정할 수 있습니다.
확장 기능과 태스크
확장 기능은 시스템 프롬프트 구간, 도구, 훅, 태스크를 묶습니다. 대화는 확장 기능과 도구의 이름만 저장합니다. 같은 이름의 확장 기능을 새 코드로 교체하면 실행 중인 도구 호출은 기존 코드로 마무리하고, 다음 호출부터 새 코드를 사용합니다. 시스템 프롬프트는 모델 요청 전에 다시 구성하며, 내용이 바뀌면 바뀐 지점을 기록해 복구나 분기 뒤에도 모델이 당시 본 내용을 재현합니다.
훅은 모델 요청 전후나 도구 호출, 컨텍스트 요약 같은 태스크에 개입합니다. 예를 들어 배포 도구를 호출하기 전에 승인을 묻고, 그 결과를 메모에 저장해 재시작 뒤에도 같은 결정을 사용하게 만들 수 있습니다. 사용자 정의 태스크도 단계별 체크포인트와 타이머, 다른 태스크의 완료 대기를 지원합니다. 태스크와 대화는 소유 관계를 형성합니다. 부모 태스크를 중단하면 자식 작업을 아래에서부터 중단하고 정리합니다. 전경 태스크는 현재 대화가 끝나기 전에 완료해야 하지만, 백그라운드 태스크는 대화를 먼저 유휴 상태로 돌려놓을 수 있습니다.
요약과 애플리케이션 상태
컨텍스트가 한도에 가까워지면 이전 메시지를 요약하는 작업을 백그라운드에서 시작합니다. 다음 요청이 한도 안에 들어오지 않을 때만 대화가 요약을 기다립니다. 요약해도 이전 기록은 저장소에 남습니다. 직접 새 컨텍스트를 시작하거나 인계 메모를 남기는 기능도 있어, 오래된 대화는 보존하면서 새 맥락으로 작업을 이어갈 수 있습니다.
할 일 목록이나 티켓 같은 애플리케이션 상태는 타입이 지정된 JSON 문서로 저장합니다. 문서는 대화 기록과 같은 원자적 커밋으로 갱신하므로 상태와 대화가 따로 기록되는 일을 피합니다. 분기 대화는 부모의 분기 시점 상태를 이어받거나, 현재 상태 또는 초기 상태를 기준으로 시작하도록 설정할 수 있습니다. 여러 클라이언트는 현재 대화 화면을 받아 구독하고, 실행 중인 도구와 출력, 대기 메시지를 확인하거나 새 요청으로 작업을 조정합니다.
실험 단계와 공개 코드
저장소에는 메모리·SQLite·JSONL 구현 외에 자체 저장소용 적합성 테스트와 벤치마크가 포함됩니다. 테스트를 제외한 소스 코드는 약 1만 5천 줄이며, 작성자는 이를 GPT 기준 약 15만 토큰, Claude 기준 약 25만 토큰으로 설명합니다. 공개 예제에는 코딩 에이전트와 휴가 계획 에이전트가 있습니다. 현재 TypeScript로 개발하며, 작성자는 부팅하기 가장 쉬운 언어라 선택했다고 밝혔습니다. Pi Durable은 실험 단계라 API가 바뀔 수 있습니다.
Hacker News 반응
- @lukebuehler — Pi도 내구성 있는 에이전트 하네스를 만드는 모습을 보니 반갑습니다. 저도 이 분야에서 한동안 만들고 있는데, 정말 흥미롭게 발전하는 곳입니다. 자기 머신에서 쓰는 코딩 에이전트만큼 화제가 되지는 않지만 LangChain Deep Agents, Vercel Eve, OpenAI Agents API, Anthropic Managed Agents 같은 주요 업체가 모두 제품을 만들고 있습니다. 이유는 세 가지입니다. 장시간 무인 실행과 복구·모니터링이 쉬워지고, 하네스와 컴퓨팅을 분리하면 안전성과 확장성이 좋아지며, 여러 사람이 함께 쓰기도 쉬워집니다.
- @the_mitsuhiko — 파고들기에 꽤 흥미로운 문제입니다. 잘 알려진 문제이면서도 세부적인 난점이 아주 많습니다. 최종 설계에 도달하기까지 이전 설계를 몇 번이나 뜯어고쳤는지 셀 수도 없습니다. 앞으로 더 배울 점이 나와도 놀랍지 않습니다.
- @lukebuehler — 출시 글을 보니 깊이 고민하신 게 느껴집니다. 태스크를 이용한 구조화된 동시성 방식이 좋습니다. Lightspeed에서 제가 쓰는 방식과도 비슷합니다. 문서로 내구성 있는 상태를 관리하는 설계도 깔끔합니다. 다만 저장소를 직접 읽고 쓰는 대신 이를 추상화해 Redux식 리듀서 패턴으로 숨기지 않은 이유가 궁금합니다.
- @the_mitsuhiko — 정말 여러 방식을 시도했습니다. 어느 순간 복잡성이 너무 커졌습니다. 한때는 Automerge 프록시 시스템의 절반 정도를 넣기도 했습니다. 결국 지금 방식이 적당한 경계라고 판단했지만, 더 지켜봐야 합니다.
- @badlogic — 아직 답이 정해진 건 아닙니다. API는 저장소 입출력처럼 보이지만 실제로는 Immer의 draft에 더 가깝습니다. 다만 다른 인코딩을 씁니다. JSON Patch는 우리가 다루는 종류의 데이터에서 메모리와 성능을 적정하게 유지하기 어렵습니다. 낮은 수준의 API 위에 편리한 추상화를 덧씌우기는 쉽습니다.
- @vmg12 — 다중 사용자 기능이 가장 마음에 듭니다. durable application state가 JSON 문서에만 한정되지 않았으면 합니다. 대화 상태와 외부 저장소를 동기화하는 outbox 패턴을 통합하는 방법도 있으면 좋겠습니다.
- @badlogic — 태스크를 쓰면 어느 정도 구현할 수 있습니다. 대화 기록에서 답변 ID를 가져와 백그라운드 태스크를 내구성 있게 예약하고, 태스크가 PostgreSQL에 같은 ID로 upsert하면 됩니다. 아직 부족한 부분은 문법을 간단하게 만드는 일입니다. 상태 변경과 원자적인 outbox 기록, 순서가 보장되는 전달, 커서가 있는 내구성 있는 변경 피드가 필요합니다.
- @rsalus — 흥미롭지만 질문이 많습니다. 샌드박싱은 사용자가 직접 준비해야 하는 것처럼 보입니다. 정책 엔진이나 NVIDIA OpenShell을 확장 기능으로 연결하는 방법이 있으면 좋겠습니다. SQLite에서도 JSON 문서를 저장하고 메모리 사용량을 줄이는 방식이 내구성의 대부분을 맡는 것처럼 보입니다. 저는 JSONL 이벤트 저장소를 쓰는 프로세스를 실험한 뒤 I/O 마찰을 피하려고 메모리에 두는 편을 선호하게 됐습니다. DB 파일 하나를 유지하는 쪽이 낫다고 생각하는 제가 잘못된 걸까요?
- @azuanrb — 온콜과 지원 채널용 Slack 하네스를 만들고 있습니다. Pi SDK 위에 구축했고 지금까지 잘 작동합니다. 처음에는 Codex를 썼지만 Pi가 더 손보기 쉽고 기본적으로 특정 업체에 종속되지 않는 점이 마음에 듭니다. Kubernetes에서 돌릴 수는 있지만 JSONL 세션 파일을 관리하고 파드가 중단돼도 세션을 유지하는 일이 복잡합니다. 지금은 DBOS를 쓰는데 잘 작동하긴 해도 과한 느낌이 있습니다. 딱 맞는 시점에 나온 도구라, 이제 불필요한 부분을 없애고 구조를 단순하게 만들 생각입니다. Pi 팀에 감사드립니다.
- @phainopepla2 — 사람들이 무한히 실행되는 에이전트를 어디에 쓰나요?
- @rubslopes — 여러 프로젝트를 감시하는 cron 작업을 돌립니다. 문제가 생기면 claw 에이전트가 Telegram으로 알려줍니다. 메시지를 받은 뒤 같은 대화에서 문제를 해결하라고 요청할 수 있습니다.
- @shepherdjerred — 무한 실행이 필요한 경우는 잘 모르겠습니다. 다만 특정 이벤트가 생기면 PR을 열거나 매일 알림을 분류하도록 예약 에이전트를 운영하고 있습니다.
- @ernsheong — 이건 정말 복잡합니다. 기본 Pi 인스턴스 여러 개를 조율하는 하네스만 만들려 해도 꽤 골치 아팠습니다. 복잡성을 감수할 가치가 있는지는 모르겠지만, 시도한 점과 실험적이라고 표시한 점은 좋습니다.
- @lemming — 기존 Pi와 크게 달라 보이는 결정 하나는 대화 트리 분기를 지원하지 않고, 조상 정보가 있는 대화 포크만 지원한다는 점입니다. 왜 이렇게 했는지, 내구성 보장에 꼭 필요한지 궁금합니다. 분기 대화도 불변 자료 구조로 표현할 수 있을 것 같은데 제가 놓친 부분이 있을까요?
- @zmmmmm — 흥미로운 개념입니다. Gastown의 일부를 재현하는 데 가까워 보입니다. 다만 샌드박싱을 일급 기능으로 다루지 않는 점은 아쉽습니다. 에이전트 실행 규칙을 선언적으로 정하고 신뢰할 수 없는 컨텍스트를 오염된 상태로 표시하고 싶습니다. 확장성만으로 해결되는 문제인지 궁금하지만, 신뢰 경계에 걸친 기능이라 하네스에 기본으로 들어가야 할 것 같습니다.
- @jlkuester7 — Pi Durable의 세부 사항은 잘 모르지만 Pi의 샌드박싱 전략은 조금 실험했습니다. 완전히 플러그인 가능하고 스스로 수정할 수 있게 만드는 데 집중하는 하네스 안에 샌드박싱을 넣어도 신뢰하기 어려울 것 같습니다. Pi로 Pi 확장 기능을 만들 때는 별도의 운영체제 수준 샌드박스 안에서 실행하는 편이 안심됩니다.
- @LeBit — 여러 선택지를 살펴본 뒤 저도 같은 결론을 내렸습니다. 샌드박스는 분리하는 편이 낫습니다. 상황에 따라 nono나 smolvm을 쓰거나 둘 다 쓸 수 있어야 합니다. 하네스가 자체 정책을 집행하는 방식은 원하지 않습니다.
원문: Earendil / 번역·요약: Trawling