Agent tools
sandboxTools for the AI SDK, Mastra, and the OpenAI Agents SDK. Tool list, parameters, output format, and options.
Guide: Give your agent a sandbox.
sandboxTools(box, options?)
| Import | Returns |
|---|---|
@opencoredev/sandbox-sdk/ai |
AI SDK tool set |
@opencoredev/sandbox-sdk/mastra |
Mastra tool map |
@opencoredev/sandbox-sdk/openai |
OpenAI Agents SDK tool array |
import { createSandbox } from "@opencoredev/sandbox-sdk";
import { local } from "@opencoredev/sandbox-sdk/local";
import { sandboxTools } from "@opencoredev/sandbox-sdk/ai";
await using box = await createSandbox(local());
const tools = sandboxTools(box, { root: "/workspace/app", deny: ["stop_process"] });
console.log(Object.keys(tools));
Each adapter needs its framework and zod installed: AI SDK 7, Mastra 1.78, or OpenAI Agents 0.20, with Zod 4.6. They are optional peers and never load from the SDK root.
Options
root?: string: file paths and working directories the model passes must resolve inside this directory, with no symlink components. It is not an OS boundary: shell commands keep the sandbox’s full privileges and can use absolute paths.allow?: ToolName[]: only these tools. Also how you turn on optional tools.deny?: ToolName[]: every allowed tool except these.denywins overallow.beforeRun?: (command: string) => boolean | string | Promise<boolean | string>: called beforerunandstart_process. Returntrueto allow, a string to run instead, orfalseto refuse.limits?: Partial<Record<ToolName, ToolLimits>>: per-tool limits. See below.onEvent?: (event: ToolEvent) => void: receives redacted output as it streams, for your UI. Each event is{ tool, kind: "output", stream, text }. With the AI SDK, the same chunks also arrive as preliminary tool results.
Limits
| Field | Default | Applies to |
|---|---|---|
timeoutMs |
30_000 |
Commands. A timeoutMs the model passes can’t exceed it. |
maxOutputBytes |
16_384 |
Every result. At least 256. |
maxReadBytes |
1_048_576 |
read_file |
maxMatches |
100 |
search |
import { createSandbox } from "@opencoredev/sandbox-sdk";
import { local } from "@opencoredev/sandbox-sdk/local";
import { sandboxTools } from "@opencoredev/sandbox-sdk/ai";
await using box = await createSandbox(local());
const tools = sandboxTools(box, {
limits: { run: { timeoutMs: 120_000, maxOutputBytes: 8_192 } },
});
Other integrations
@opencoredev/sandbox-sdk/tools exports createSandboxTools and toolSchemas, the Zod schemas behind every tool. Convert them with z.toJSONSchema for a framework without an adapter.
Default tools
| Tool | Parameters | Notes |
|---|---|---|
run |
command, cwd?, timeoutMs? |
Waits for exit. Use start_process for servers. |
read_file |
path, offset?, limit? |
Numbered lines and a SHA-256. offset is a zero-based line index. Binary files return metadata only. |
write_file |
path, content |
Whole-file write |
edit_file |
path, find, replace |
find must match exactly once |
start_process |
name, command, cwd?, port? |
With port, waits for it and returns the URL. Without, confirms the launch only. |
process_logs |
name, cursor? |
Returns text and the next cursor |
stop_process |
name |
Optional tools
Turn these on with allow:
| Tool | Parameters | Notes |
|---|---|---|
search |
query, path?, glob? |
Literal text, not a regular expression |
list_files |
path?, glob? |
Recursive |
changes |
none | Files added, modified, or removed since the tools were created |
preview |
port, path? |
The URL only. Access headers stay on your server. |
Output format
Results open with one verdict line:
OK exit=0 1.2s cwd=/workspace
output:
added 214 packages in 9s
- Failures start with
FAILED exit=<code>. - Output is ANSI-stripped and capped at 16 KB as head plus tail, with a
[N bytes cut, use process_logs]marker. - Errors use the
SandboxErrormessage format. - Secrets passed to
createSandboxnever appear, including in file contents read byread_file. Rawbox.files.readis not redacted.