Skip to main content
For every box, you can configure a built-in agent like Claude Code or Codex. It has access to the filesystem, git, and shell commands and should simulate running an Agent on your own computer. You can choose between:
  • run() when you want to wait for completion and then read the final typed result.
  • stream() when you want real-time output while the agent is running.

Configure an Agent

Get your Claude API key from the Claude Console.
.env
UPSTASH_BOX_API_KEY=abx_xxxxxxxxxxxxxxxxxxxxxxxx
ANTHROPIC_API_KEY=sk-ant-xxxxxxxxxxxxxxxx
import { Box, Runtime, ClaudeCode } from "@upstash/box"

const box = await Box.create({
  runtime: "node",
  agent: {
    model: ClaudeCode.Sonnet_4_5,
    apiKey: process.env.ANTHROPIC_API_KEY!,
  },
})

Quickstart

Run an agent

Use run() when you only need the final result.
const run = await box.agent.run({
  prompt: "Analyze /work/report.csv and return top 10 customers by revenue",
})

console.log(run.status)
console.log(run.result)
console.log(run.cost.totalUsd)

Stream an agent

Use stream() when you want to display progress in real time.
const stream = await box.agent.stream({
  prompt: "Refactor the payment module",
})

for await (const chunk of stream) {
  process.stdout.write(chunk)
}

console.log(stream.status)
console.log(stream.result)
console.log(stream.cost.totalUsd)

Prompt options

Prompt (required)

Type: string
Supported on: box.agent.run() and box.agent.stream()
The task instruction sent to the agent.

Timeout

Type: number
Supported on: box.agent.run() and box.agent.stream()
Default: no execution timeout
Execution timeout in milliseconds. When reached, the run is aborted.

onToolUse

Type: { name: string; input: Record<string, unknown> }
Supported on: box.agent.run() and box.agent.stream()
Called whenever the agent invokes a tool (for example file, shell, or git tools).

responseSchema

Type: Zod Schema
Supported on: box.agent.run()
Attach a Zod schema to get typed output.
import { z } from "zod"

const responseSchema = z.object({
  customers: z.array(
    z.object({
      name: z.string(),
      revenue: z.number(),
    }),
  ),
})

const analysis = await box.agent.run({
  prompt: "Analyze /work/report.csv and return top customers by revenue",
  responseSchema,
})

console.log(analysis.result.customers)

maxRetries

Type: number
Supported on: box.agent.run()
Default: 0
Retry count to compensate temporary provider outages or similar transient errors. Retries use exponential backoff (1s, 2s, 4s, …) capped at 30s.

Webhook

Type: WebhookConfig
Supported on: box.agent.run()
Useful for fire-and-forget mode. The SDK returns immediately and sends the completion payload to your webhook URL when the run succeeds or fails.

Examples

Minimal example

Clone a repository, run the agent, and open a pull request.
import { Box, Runtime, ClaudeCode } from "@upstash/box"

const box = await Box.create({
  runtime: "node",
  agent: {
    model: ClaudeCode.Opus_4_5,
    apiKey: process.env.ANTHROPIC_API_KEY,
  },
  git: {
    token: process.env.GITHUB_TOKEN,
  },
})

await box.git.clone({ repo: "github.com/your-org/your-repo" })

const stream = await box.agent.stream({
  prompt: "Fix the null token bug in src/auth.ts and add tests",
})

for await (const chunk of stream) {
  process.stdout.write(chunk)
}

await box.git.createPR({
  title: "Fix null token bug",
  base: "main",
})

Document processing agent

Run one box per file, process in parallel, and return ranked structured results.
import { Box, Runtime, ClaudeCode } from "@upstash/box"
import { readdir } from "fs/promises"
import { z } from "zod"

const responseSchema = z.object({
  name: z.string(),
  email: z.string(),
  yearsOfExperience: z.number(),
  skills: z.array(z.string()),
  score: z.number().min(0).max(100),
  summary: z.string(),
})

const job = "Senior Backend Engineer (Node.js, PostgreSQL)."

const files = await readdir("./resumes")
const resumes = files.filter((file) => file.endsWith(".pdf"))

const results = await Promise.all(
  resumes.map(async (file) => {
    const box = await Box.create({
      runtime: "node",
      agent: {
        model: ClaudeCode.Opus_4_5,
        apiKey: process.env.ANTHROPIC_API_KEY,
      },
    })

    await box.files.upload([
      { path: `./resumes/${file}`, destination: "/work/resume.pdf" },
    ])

    const run = await box.agent.run({
      prompt: `Read /work/resume.pdf. Extract candidate data and score 0-100 for: ${job}`,
      responseSchema,
    })

    await box.delete()

    return { file, ...run.result, cost: run.cost.totalUsd }
  }),
)

const ranked = results.sort((a, b) => b.score - a.score)