Start Here
Quick Start
Create your first sandbox, wait for readiness, send work to the AI agent, watch the browser, and get outputs back through the SDK.
This page shows the fastest complete integration path.
By the end of it, you will know how to:
- create a client
- launch a sandbox
- wait for it to be usable
- send work to the AI agent
- watch the browser
- collect files or artifacts
- clean up when the job is done
1. Install the SDK
npm install @banata-boxes/sdk2. Create a client
import { BanataSandbox } from "@banata-boxes/sdk";
const banata = new BanataSandbox({
apiKey: process.env.BANATA_API_KEY!,
baseUrl: "https://api.boxes.banata.dev",
});This client is your entry point for:
- sandbox lifecycle
- agent tasks
- browser preview links
- file access
- artifacts
- webhooks
- billing and usage reads
3. Launch a sandbox
For a first integration, use launch().
launch() is the easiest starting point because it:
- creates the sandbox
- waits for readiness
- returns a session object that already targets that sandbox
If you want to use the AI agent, you should pass model provider settings in env when you create the sandbox.
Use:
OPENROUTER_API_KEYOPENROUTER_MODEL
Recommended:
OPENROUTER_SMALL_MODEL
Without those values, the sandbox can still be created, but AI agent prompts may not do useful work.
const sandbox = await banata.launch({
env: {
OPENROUTER_API_KEY: process.env.OPENROUTER_API_KEY!,
OPENROUTER_MODEL: "openai/gpt-5.3-codex",
OPENROUTER_SMALL_MODEL: "openai/gpt-5.3-codex",
},
capabilities: {
agent: { enabled: true, defaultAgent: "build" },
browser: {
viewport: { width: 1440, height: 900 },
},
documents: { libreofficeHeadless: true },
},
});
console.log("sandbox:", sandbox.sessionId);What these values do:
OPENROUTER_API_KEYgives the agent access to the model providerOPENROUTER_MODELchooses the main model for the runOPENROUTER_SMALL_MODELgives the agent a lighter model for smaller decisions
Use launch() when:
- you want to get productive quickly
- your app does not need custom readiness orchestration
- you want one method that returns a usable sandbox
Use create() when:
- your own backend already has a job queue
- you want to create first and wait later
- you want more control over when the caller blocks
4. Check the browser preview
const previewUrl = await sandbox.getPreviewViewerUrl();
console.log(previewUrl);Use the preview when you want to:
- watch the AI agent work
- inspect browser state during debugging
- let a person take over later
5. Run one direct command
Before sending an agent task, verify the sandbox itself is healthy.
const result = await sandbox.exec("sh", ["-lc", "echo hello from banata"]);
console.log(result.stdout);This is the fastest way to confirm:
- the sandbox is live
- commands run successfully
- your client is authenticated correctly
6. Send a real AI agent task
For meaningful work, prefer promptAsync().
const queued = await sandbox.promptAsync(
"Open https://example.com, confirm the title, write TITLE:<title> to /workspace/result.txt, and reply briefly when done.",
{
metadata: {
userId: "user_123",
jobId: "job_456",
source: "my-app",
},
},
);
console.log("task:", queued.taskId);Why promptAsync() is the better default:
- it returns quickly
- it works well for long-running jobs
- it gives you a
taskId - it lets you attach your own metadata
- it works naturally with webhooks
Use prompt() only when you truly want a short convenience call and you expect a quick reply.
7. Check task status
const task = await sandbox.getAgentTask(queued.taskId!);
console.log(task?.status);Task states you should expect:
queuedrunningcompletedfailed
8. Use webhooks for production completion handling
Polling can work during development, but it is not the best pattern for production.
The better production flow is:
- call
promptAsync() - pass metadata that identifies the job in your system
- store
taskId - receive a webhook when the task finishes
- fetch files or artifacts afterward
That way:
- your app does not hold one request open
- you do not need constant polling
- your webhook payload already tells you which job finished
9. Read files from /workspace
Small outputs are easiest to read directly.
const text = await sandbox.fs.read("/workspace/result.txt");
console.log(text);Use direct file reads when:
- the file is small
- you want the contents immediately
- the file is mainly a working output, not a durable customer download
10. Use artifacts for durable outputs
const artifactState = await sandbox.getArtifacts();
console.log(artifactState.artifacts);Then, if you need a download URL:
const item = artifactState.artifacts?.items?.[0];
if (item?.key) {
const download = await sandbox.getArtifactDownloadUrl(item.key);
console.log(download.url);
}Artifacts are the better choice when:
- the output is large
- another system needs a stable file handoff
- the output should remain associated with the sandbox as a durable result
11. End the sandbox
await sandbox.kill();End the sandbox when:
- the job is complete
- you already collected the outputs you need
- you do not plan to resume later
Use pause() instead when the work should continue later and you want to keep the workspace around.
Recommended first production pattern
If you are integrating Banata into another product, this is the cleanest first design:
- create or launch a sandbox
- queue work with
promptAsync() - attach your own metadata
- let the agent save its outputs to
/workspace - receive completion through a webhook
- download final outputs through artifacts or direct file reads
- end the sandbox
That gives you:
- stable async behavior
- clean job tracking
- clear ownership of outputs
- a straightforward operational model