Repository navigation
think: make createSandboxTools actually work #1319
Description
Parent roadmap: #1439
Summary
@cloudflare/think/tools/sandbox currently exports createSandboxTools(), but the implementation is intentionally a no-op: it logs a warning once and returns {}.
That means the blog/docs-level execution ladder says Think can wire in Cloudflare Sandbox as Tier 4, but the package export does not yet provide any usable tools.
This issue tracks turning createSandboxTools() into a real integration with the Cloudflare Sandbox SDK, or narrowing/removing the public promise until the integration exists.
Current behavior
Current implementation in packages/think/src/tools/sandbox.ts:
export function createSandboxTools(
_binding?: unknown,
_options?: CreateSandboxToolsOptions
): ToolSet {
if (!warned) {
warned = true;
console.warn(
"[@cloudflare/think] createSandboxTools is not yet implemented. " +
"No tools will be registered."
);
}
return {};
}The export exists in packages/think/package.json as @cloudflare/think/tools/sandbox, so users can import and spread it, but they get no tools.
Why this matters
Project Think's execution ladder is meant to be additive:
- Tier 0: Think Workspace /
@cloudflare/shell - Tier 1: Dynamic Worker / codemode execution
- Tier 2: npm/runtime dependency loading
- Tier 3: browser automation
- Tier 4: full Sandbox for OS-level toolchains, repos, test runners, compilers, and long-running processes
Tier 4 is the escape hatch for tasks that cannot fit in a Workers isolate: git clone, npm test, cargo build, real CLIs, shell scripts, code review bots, and heavyweight project work.
Right now Think has a named Sandbox tool export, but no actual Sandbox bridge. That creates a confusing gap for users and for the roadmap.
Sandbox SDK capabilities to target
The Sandbox SDK already exposes useful primitives:
getSandbox(env.Sandbox, id)to create/reuse a sandbox instanceexec()for command execution with complete stdout/stderr/exit codeexecStream()for long-running commands with streamed outputstartProcess()/ process log streaming for services- file operations:
readFile,writeFile,mkdir,exists, delete/move/rename - code interpreter contexts for Python/JavaScript/TypeScript
- preview URLs / port exposure for web servers
- terminal and WebSocket connections
- request-proxy patterns so real credentials stay in the Worker, not inside sandbox code
For Think v1, we should probably start with a small subset instead of exposing the whole SDK.
Proposed first milestone
Implement a minimal createSandboxTools(binding, options) that exposes a conservative tool set for Think agents:
-
sandbox_exec- Run a shell command in a named sandbox.
- Inputs:
command, optionalsandboxId, optionalcwd, optionaltimeout. - Output:
stdout,stderr,exitCode,success, maybe truncated output metadata.
-
sandbox_write_file- Write a file into
/workspaceor another allowlisted path. - Inputs:
path,content, optional encoding.
- Write a file into
-
sandbox_read_file- Read a file back from the sandbox.
- Inputs:
path, optional encoding / max bytes.
-
Optional later:
sandbox_exec_stream- Stream long-running output into Think chunks or a retained run/event model.
- This is probably not required for the first PR unless the API shape is obvious.
-
Optional later:
sandbox_expose_port/ preview URL helpers.
Keep the first implementation boring and testable: command execution + file transfer.
Workspace sync question
The important design question is how Think's DO-local Workspace interacts with the Sandbox filesystem.
Possible approaches:
A. Explicit file transfer tools
The model calls read / find / grep against Think Workspace, then calls sandbox_write_file for files it wants in the Sandbox. After commands run, it calls sandbox_read_file to pull results back.
Pros: simple, no hidden sync, minimal API.
Cons: tedious for whole repos / many files.
B. Helper methods for push/pull workspace snapshots
Expose tools like:
sandbox_push_workspace({ paths, sandboxPath })sandbox_pull_workspace({ sandboxPath, paths })
Pros: better UX for project work.
Cons: needs careful path filtering, binary handling, limits, and conflict behavior.
C. Git/Artifacts handoff
Use Git/Artifacts as the handoff boundary: Think commits workspace state to an Artifacts repo, Sandbox clones/mounts it, pushes results, and Think imports/reviews the diff.
Pros: clean versioned boundary, aligns with #1440.
Cons: larger integration; should not block the minimal createSandboxTools() milestone.
Recommendation: start with A, design B after using it, and keep C linked to #1440.
API shape questions
- Should
createSandboxTools()accept a Sandbox Durable Object namespace directly, or a factory function like(id) => getSandbox(binding, id)? - How should the sandbox id be chosen by default: Think agent name, chat/session id, caller-provided id, or a generated per-run id?
- Should tools reuse a long-lived sandbox per Think agent/session, or create per-run sandboxes?
- How should timeouts work, given Sandbox command timeout behavior does not necessarily kill the underlying process?
- Should path access be restricted to
/workspaceby default? - Should network/proxy setup be part of
createSandboxTools()or left to application code? - How do we surface preview URLs / running background processes without turning v1 into a full IDE API?
Security constraints
- Do not pass durable secrets directly into sandbox commands by default.
- Prefer Worker-side proxy patterns for external APIs so the sandbox gets short-lived scoped credentials, not real API keys.
- Require explicit opt-in for network credentials, repo write tokens, or access to user data.
- Default path access should be scoped, probably to
/workspace. - Tool outputs must be truncated/structured to avoid blowing up model context.
- Commands should have explicit timeouts and clear behavior for non-zero exit codes.
- Avoid logging secrets in command strings, outputs, or chat history.
Relationship to existing Think tools
createExecuteTool()remains the default for small JavaScript programs in Dynamic Worker isolates.createSandboxTools()is for full OS/toolchain work that cannot run in codemode: real shell commands, package managers, compilers, tests, CLI agents, and services.- Browser tools remain separate; Sandbox should not replace
createBrowserTools(). - Artifacts integration (Think + Artifacts: versioned workspaces, forks, and handoff #1440) may become the preferred handoff mechanism for large repo workflows, but this issue should make the Sandbox export useful on its own first.
Acceptance criteria
createSandboxTools()returns at least one real AI SDK tool instead of{}when passed a valid Sandbox binding/factory.- The minimal tools can run a command in a sandbox and return structured result data.
- The minimal tools can write a file into the sandbox and read it back.
- Tool outputs are bounded/truncated and include enough metadata for the model to continue.
- Timeouts and non-zero exit codes have documented behavior.
- The implementation has worker tests or a focused example covering command execution and file round trip.
- Docs explain when to use
createExecuteTool()versuscreateSandboxTools(). - Docs show the required Wrangler binding/configuration.
- The no-op warning is removed, or retained only when the function is called without a usable binding.
Nice-to-have follow-ups
- Streaming command output into Think events.
- Background process and preview URL tools.
- Workspace push/pull helpers.
- Artifacts-backed clone/push handoff with Think + Artifacts: versioned workspaces, forks, and handoff #1440.
- Sandbox request proxy helpers for GitHub, package registries, model providers, or R2.
- A Think example that runs tests/builds in Sandbox and reports results back into chat.
Useful files
packages/think/src/tools/sandbox.tspackages/think/src/tools/execute.tsdocs/think/tools.mdexamples/assistant/src/server.tsexperimental/gadgets-sandbox/README.md
References
- Roadmap umbrella: Project Think roadmap: durable agent platform preview to stable developer experience #1439
- Artifacts handoff issue: Think + Artifacts: versioned workspaces, forks, and handoff #1440
- Sandbox SDK overview: https://developers.cloudflare.com/sandbox/
- Sandbox command execution: https://developers.cloudflare.com/sandbox/guides/execute-commands/
- Sandbox file operations: https://developers.cloudflare.com/sandbox/guides/manage-files/
- Sandbox streaming output: https://developers.cloudflare.com/sandbox/guides/streaming-output/
- Sandbox request proxy pattern: https://developers.cloudflare.com/sandbox/guides/proxy-requests/
- Claude Code on Sandbox tutorial: https://developers.cloudflare.com/sandbox/tutorials/claude-code/
Activity
threepointone commentedon Jun 17, 2026
this is probably going to be
@cloudflare/workspace