본문으로 건너뛰기

빠른 시작

이미 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. sbx가 PATH에 있도록 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 조회, 시크릿)를 제공하려면 도구를 참조하세요.
  • 에이전트가 실행할 수 있는 항목을 제한하려면 정책을 참조하세요.
  • 에이전트가 작업하면서 접근하는 모든 파일을 확인하려면 이벤트를 참조하세요.