본문으로 건너뛰기

빠른 시작

이미 chat()을 호출하는 앱과 XAI_API_KEY가 있습니다(또는 grok.com에 로그인했습니다). 이 가이드를 마치면 Grok Build 에이전트가 리포지토리를 Docker 샌드박스에 복제하고 버그를 수정한 뒤 결과 git diff를 다시 스트리밍합니다.

개념을 먼저 확인하려면 개요를 읽으세요. 그렇지 않다면 여기서 시작하세요.

1. 패키지 설치

npm i @tanstack/ai @tanstack/ai-grok-build @tanstack/ai-sandbox @tanstack/ai-sandbox-docker
  • @tanstack/ai: 핵심 chat() 파이프라인입니다.
  • @tanstack/ai-grok-build: Grok Build 하네스 어댑터입니다.
  • @tanstack/ai-sandbox: defineSandbox, defineWorkspace, withSandbox.
  • @tanstack/ai-sandbox-docker: 컨테이너에서 에이전트를 실행하는 Docker 프로바이더입니다.

로컬에서 Docker가 실행 중이어야 하며, 샌드박스 이미지에서 grok CLI를 사용할 수 있어야 합니다(Grok Build 하네스가 샌드박스 내부에서 이를 실행합니다). Docker가 없나요? 아래의 로컬 프로세스 대안을 참조하세요. 컨테이너 대신 마이크로VM을 사용하려면 Docker Sandboxes를 참조하세요.

2. 샌드박스 정의

샌드박스는 세 가지를 묶습니다. 프로바이더(격리 기본 요소이며 여기서는 Docker), 워크스페이스(에이전트가 보는 대상이며 여기서는 복제된 git 리포지토리와 설정 단계), 수명 주기(재사용, 스냅샷 생성 및 종료 시점)입니다.

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

export const repoSandbox = defineSandbox({
id: 'bug-fixer',
provider: dockerSandbox({ image: 'node:22' }),
workspace: defineWorkspace({
// Where the working tree comes from (shallow clone by default).
source: githubRepo({ repo: 'owner/buggy-app' }),
packageManager: 'pnpm',
// Commands that run once during bootstrap.
setup: ['corepack enable', 'pnpm install'],
// Injected into the sandbox env at create/resume, never persisted to
// snapshots, the sandbox store, or the event log.
secrets: createSecrets({
XAI_API_KEY: process.env.XAI_API_KEY ?? '',
}),
}),
lifecycle: { reuse: 'thread', snapshot: 'after-setup', keepAlive: '30m' },
})

snapshot: 'after-setup'(프로바이더가 스냅샷을 지원할 때의 기본값)은 다음 실행이 다시 복제하고 재설치하는 대신 pnpm install 이후의 스냅샷에서 재개된다는 의미이므로, 콜드 스타트 비용은 첫 실행에서만 발생합니다.

defineWorkspace()로 설명할 수 있는 모든 항목, 패키지 관리자 자동 감지, 병렬 설정 그룹 및 복제 깊이는 워크스페이스를 참조하세요.

3. 하네스 어댑터로 chat() 호출

Grok Build 어댑터는 샌드박스 기능을 requires한다고 선언합니다. withSandbox(...)는 이를 제공하는 미들웨어로, 수명 주기에 따라 샌드박스를 재개하거나 생성하고 워크스페이스를 부트스트랩한 뒤 종료합니다.

import { chat } from '@tanstack/ai'
import { grokBuildText } from '@tanstack/ai-grok-build'
import { withSandbox } from '@tanstack/ai-sandbox'
import { messages, threadId } from './chat-context'
import { repoSandbox } from './sandbox'

const stream = chat({
threadId,
adapter: grokBuildText('grok-build'),
messages,
middleware: [withSandbox(repoSandbox)],
})

여기서 messages는 대화(예: 에이전트에게 버그 수정을 요청하는 사용자 턴)이고, threadId는 샌드박스의 키이므로 같은 스레드가 같은 컨테이너를 재사용합니다. grok은 샌드박스 내부에서 실행되며 해당 이벤트는 일반적인 chat() 청크로 다시 스트리밍됩니다.

4. 결과 스트리밍 및 diff 읽기

하네스 실행은 표준 AG-UI 청크(텍스트, 도구 호출, 추론)와 네임스페이스가 지정된 CUSTOM 이벤트를 함께 방출합니다. 실행이 완료되면 Grok Build 어댑터는 작업 트리의 git diff를 담은 file.changed 이벤트를 방출합니다.

import { stream } from './my-run'

for await (const chunk of stream) {
if (chunk.type === 'TEXT_MESSAGE_CONTENT') {
process.stdout.write(chunk.delta)
}

if (chunk.type === 'CUSTOM' && chunk.name === 'file.changed') {
const value = chunk.value
if (value !== null && typeof value === 'object' && 'diff' in value) {
console.log('\n--- diff ---\n')
console.log(value.diff)
}
}
}

diff가 지점 B입니다. 에이전트가 리포지토리를 복제하고 버그를 찾아 파일을 수정했으며, 호스트 파일 시스템에 손대지 않고 에이전트가 만든 변경 사항을 출력했습니다.

Docker가 없나요? 호스트에서 실행

Docker를 완전히 건너뛰려면 프로바이더를 로컬 프로세스 프로바이더로 교체하세요. 호스트에서 에이전트를 직접 실행하므로(격리 없음) 가장 빠른 개발 루프를 구성할 수 있습니다.

npm i @tanstack/ai-sandbox-local-process
import { chat } from '@tanstack/ai'
import { grokBuildText } from '@tanstack/ai-grok-build'
import {
defineSandbox,
defineWorkspace,
githubRepo,
withSandbox,
} from '@tanstack/ai-sandbox'
import { localProcessSandbox } from '@tanstack/ai-sandbox-local-process'
import { messages } from './chat-context'

export const repoSandbox = defineSandbox({
id: 'bug-fixer',
provider: localProcessSandbox({
scrubEnv: ['XAI_API_KEY', 'GROK_API_KEY'],
}),
workspace: defineWorkspace({
source: githubRepo({ repo: 'owner/buggy-app' }),
setup: ['corepack enable', 'pnpm install'],
}),
lifecycle: { reuse: 'thread' },
})

const stream = chat({
adapter: grokBuildText('composer-2.5', { authMode: 'host' }),
messages,
middleware: [withSandbox(repoSandbox)],
})

어댑터가 grok login을 사용하도록 authMode: 'host'를 설정하세요. scrubEnv는 호스트 프로세스가 상속한 키를 제거합니다. 이러한 키가 로그인을 재정의할 수 있기 때문입니다.

로컬 프로세스 실행은 CI 러너일 수도 있습니다. 해당 시스템에는 브라우저 로그인이 없으므로 authMode: 'api-key'를 설정하세요. 그런 다음 XAI_API_KEY를 워크스페이스 시크릿으로 주입하세요. 샌드박스 유형은 이를 선택하지 않습니다. 하네스 인증을 참조하세요.

Docker Sandboxes 마이크로VM(sbx)

하이퍼바이저 마이크로VM이 필요하면 sbxSandbox()를 사용하세요. 이는 Docker 컨테이너가 아닙니다.

  1. sbxPATH에 있도록 Docker Sandboxes를 설치하세요.
    • macOS: brew trust docker/tap을 실행한 다음 brew install docker/tap/sbx를 실행합니다.
    • Windows: HypervisorPlatform을 활성화한 다음 winget install -h Docker.sbx를 실행합니다.
    • Debian 또는 Ubuntu: curl -fsSL https://get.docker.com | sudo REPO_ONLY=1 sh를 실행한 다음 apt-get install docker-sbx를 실행합니다. 사용자를 kvm 그룹에 추가하세요.
  2. sbx login을 실행하세요.
  3. 프로바이더를 교체하세요. pnpm install이 npm 레지스트리에 연결할 수 있도록 allowNetwork를 전달하세요. grok-build와 같은 알려진 어댑터는 모델 API 호스트도 추가합니다.
import {
createSecrets,
defineSandbox,
defineWorkspace,
githubRepo,
} from '@tanstack/ai-sandbox'
import { sbxSandbox } from '@tanstack/ai-sandbox-docker'

export const repoSandbox = defineSandbox({
id: 'bug-fixer',
provider: sbxSandbox({
allowNetwork: ['*.npmjs.org', 'registry.npmjs.org'],
}),
workspace: defineWorkspace({
source: githubRepo({ repo: 'owner/buggy-app' }),
setup: ['pnpm install'],
secrets: createSecrets({
XAI_API_KEY: process.env.XAI_API_KEY ?? '',
}),
}),
lifecycle: { reuse: 'thread' },
})

sbxSandbox()는 항상 Git 리포지토리를 VM에 복제합니다. 스냅샷을 생성하지 않습니다. 재개는 샌드박스 이름으로 수행됩니다.

작동하는 예제 실행

완전하게 실행할 수 있는 앱은 examples/sandbox-web. 포함되어 있습니다. 해당 앱은 새로고침 후에도 유지되는 실행을 지원하는 "앱을 만들어 주세요" 에이전트(Docker 샌드박스의 Claude Code)입니다. 샌드박스에서 앱의 기본 구조를 생성하고 개발 서버를 실행한 뒤 라이브 미리보기 URL을 다시 스트리밍합니다. UI에서 실행마다 하네스(Claude Code, Codex, Grok Build)를 선택하여 엣지에서 실행하는 코딩 에이전트에 대해서는 examples/sandbox-cloudflare.

다음 항목을 참조하세요.

  • 에이전트에 자체 서버 측 도구(DB 조회, 시크릿)를 제공하려면 도구를 참조하세요.
  • 에이전트가 실행할 수 있는 항목을 제한하려면 정책을 참조하세요.
  • 에이전트가 작업하면서 접근하는 모든 파일을 확인하려면 이벤트를 참조하세요.