본문으로 건너뛰기

수명 주기 및 스냅샷

샌드박스를 부트스트랩하는 작업(저장소 복제, 종속성 설치, setup 실행)은 실행에서 비용이 가장 많이 드는 부분입니다. 수명 주기 설정을 사용하면 이 비용을 한 번만 지불하고 결과를 재사용할 수 있습니다. 스레드마다 샌드박스 하나를 유지하고, 설정 후 스냅샷을 저장한 다음, 다음 실행에서는 다시 부트스트랩하는 대신 재개합니다.

샌드박스가 사라진 후 파일도 복구해야 한다면 다시 로드한 후 파일 유지를 설정합니다. 프로바이더 네이티브 스냅샷은 부트스트랩을 더 빠르게 만듭니다. 이식 가능한 스냅샷은 완료된 워크스페이스를 영속적인 애플리케이션 데이터로 저장합니다.

import { defineSandbox, defineWorkspace, githubRepo } from '@tanstack/ai-sandbox'
import { dockerSandbox } from '@tanstack/ai-sandbox-docker'

const sandbox = defineSandbox({
id: 'repo-agent',
provider: dockerSandbox({ image: 'node:22' }),
workspace: defineWorkspace({
source: githubRepo({ repo: 'owner/app' }),
setup: ['corepack enable', 'pnpm install'],
}),
lifecycle: {
reuse: 'thread', // one sandbox per threadId ('none' = fresh per run)
snapshot: 'after-setup', // snapshot once bootstrapped (provider-permitting)
keepAlive: '30m', // hint to keep the sandbox warm between runs
destroyOnComplete: false, // keep it for the next run
},
})

수명 주기 객체

필드제어하는 내용
reuse'thread'threadId마다 샌드박스 하나를 유지하고, 'none'은 실행마다 새 샌드박스를 프로비저닝합니다.
snapshot스냅샷을 지원하는 프로바이더에서 부트스트랩이 완료되면 'after-setup'이 워크스페이스를 스냅샷으로 저장합니다.
keepAlive실행 간 샌드박스를 웜 상태로 유지할 시간을 나타내는 기간 힌트입니다(예: '30m'). 현재 @tanstack/ai-sandbox의 어떤 부분도 이를 읽지 않으며, 프로바이더와 호스트 앱을 위한 힌트입니다. 프로바이더 유휴 타이머는 프로바이더 설정에 있습니다.
destroyOnCompletefalse이면 다음 실행에서 재개할 수 있도록 샌드박스가 실행 후에도 유지됩니다.
snapshotMaxAge저장된 스냅샷을 오래된 것으로 간주하고 다시 생성할 때까지의 기간입니다(예: '24h').

이 필드는 취소가 아닌 완료를 제어합니다

keepAlivedestroyOnComplete은 실행이 완료될 때 발생하는 일을 설명합니다. 이 설정은 중단 중에 샌드박스를 계속 유지하지 않습니다. 에이전트의 IO 스트림을 닫아도 에이전트 프로세스가 종료되지 않으므로, 명시적으로 취소하면 destroyOnComplete 값과 관계없이 샌드박스가 삭제되며, 이것이 에이전트가 토큰을 계속 소비하는 것을 멈추는 유일하게 신뢰할 수 있는 방법입니다.

연결 해제는 세 번째 경우이며 취소와 동일하지 않습니다. 사용자가 중지를 누르는 경우와 탭을 닫는 경우에는 동일한 연결 종료가 발생합니다. 영속성이 연결된 실행에서는 연결 해제가 완료도 삭제도 일으키지 않습니다. 샌드박스는 유지되고 에이전트는 계속 작업하며, 나중에 요청이 인계할 수 있도록 실행 레코드가 분리됨으로 표시됩니다. 영속성이 연결되지 않은 경우 연결 해제는 중단과 정확히 동일하게 샌드박스를 삭제합니다. 인계 및 분리된 실행을 참조합니다.

설정 후 스냅샷

프로바이더가 스냅샷을 지원하면(프로바이더 참조), 부트스트랩이 setup 완료 후 자동으로 스냅샷을 저장합니다. 스냅샷은 완전히 부트스트랩된 워크스페이스(종속성이 설치된 복제된 저장소)를 캐시하므로, 이후 실행에서는 설정 단계를 다시 실행하는 대신 여기서 재개하여 콜드 스타트 시간을 크게 줄입니다.

프로바이더가 스냅샷 지원을 보고하는 경우 snapshot: 'after-setup'이 기본값이므로 일반적으로 명시적으로 설정하지 않습니다. 스냅샷을 지원하지 않는 프로바이더(예: localProcessSandbox)는 스냅샷 단계를 조용히 건너뜁니다.

import { defineSandbox, defineWorkspace, githubRepo } from '@tanstack/ai-sandbox'
import { dockerSandbox } from '@tanstack/ai-sandbox-docker'

const sandbox = defineSandbox({
id: 'repo-agent',
provider: dockerSandbox({ image: 'node:22' }),
workspace: defineWorkspace({
source: githubRepo({ repo: 'owner/app' }),
setup: ['corepack enable', 'pnpm install'],
}),
lifecycle: {
reuse: 'thread',
// 'after-setup' is the default when the provider supports snapshots.
snapshot: 'after-setup',
// Optional: re-create (re-bootstrap) when the snapshot is older than this.
snapshotMaxAge: '24h',
},
})

오래된 스냅샷

snapshotMaxAge는 기간 문자열('24h', '30m' 등)을 받습니다. 저장된 스냅샷이 제한보다 오래되면 샌드박스는 이를 오래된 것으로 간주하고 처음부터 다시 생성하여 설정을 다시 실행하고 새 스냅샷을 저장합니다. 스냅샷을 무기한 유지하려면 설정하지 않은 상태로 둡니다.

샌드박스 인스턴스 키

샌드박스는 다음과 같은 복합 sandboxInstanceKey를 키로 사용합니다.

sandboxInstanceKey = hash(threadId + sandbox.id + provider + workspaceHash + tenant?)

키에는 워크스페이스 해시, 프로바이더, 선택적 테넌트가 포함됩니다. 캐시된 환경을 무효화하는 입력, 즉 저장소, setup 단계, 프로바이더 이미지 또는 테넌트를 변경하면 다른 키가 생성됩니다. 따라서 설정과 스냅샷이 더 이상 일치하지 않는 오래된 샌드박스를 재개하는 대신 안전하게 샌드박스를 시작합니다. 같은 웜 샌드박스를 계속 사용하려면 실행 간에 이러한 입력을 안정적으로 유지합니다.

확인 순서

실행에 샌드박스가 필요하면 레이어는 다음 순서로 확인합니다.

  1. 키에 해당하는 실행 중인 샌드박스가 이미 있으면 실행 중인 샌드박스를 재개합니다.
  2. 최신 스냅샷을 복원하고, 설정을 건너뛰면서 가장 최근 스냅샷에서 다시 생성합니다.
  3. 새로 생성하고 부트스트랩하여 복제하고, 설치하고, setup을 실행한 다음 스냅샷을 저장합니다.

앞 단계가 불가능한 경우에만 다음 단계로 넘어갑니다. 이 과정을 통해 웜 스레드는 거의 즉시 시작되고 콜드 스레드는 전체 부트스트랩을 수행합니다.

이 수명 주기 작업 후에 이식 가능한 샌드박스 스냅샷이 실행됩니다. 저장된 워크스페이스는 새로 생성된 비공개 샌드박스에만 복원합니다. 실행 중인 재개된 샌드박스를 절대 덮어쓰지 않습니다. 이식 가능한 스냅샷을 참조합니다.

영속 디스크, 스냅샷, ID를 통한 재개를 지원하는 프로바이더는 프로바이더에 나열되어 있습니다.

영속 디스크나 스냅샷이 없는 프로바이더(예: 임시 컨테이너)는 동일한 식별자 아래에서 다시 생성하고 다시 부트스트랩합니다. sandboxInstanceKey는 안정적으로 유지되지만, 재개할 수 있는 영속적인 대상이 없으므로 모든 실행에서 부트스트랩 비용이 발생합니다.