From f7030f840dc42ff045a951d20a2a7ff78d56d84d Mon Sep 17 00:00:00 2001 From: Matt Carey Date: Wed, 14 Oct 2026 15:10:15 +0200 Subject: [PATCH 1/5] [Agents] Think works in a @cloudflare/computer Workspace --- .../2026-10-14-think-computer-workspace.mdx | 43 +++ .../agents/harnesses/think/configuration.mdx | 38 ++- .../harnesses/think/getting-started.mdx | 8 +- .../docs/agents/harnesses/think/index.mdx | 2 +- .../docs/agents/harnesses/think/tools.mdx | 247 ++++++++++-------- .../agents/runtime/execution/agent-skills.mdx | 2 + src/content/docs/agents/tools/browser.mdx | 2 +- .../docs/agents/tools/codemode/ai-sdk.mdx | 20 +- 8 files changed, 220 insertions(+), 142 deletions(-) create mode 100644 src/content/changelog/agents/2026-10-14-think-computer-workspace.mdx diff --git a/src/content/changelog/agents/2026-10-14-think-computer-workspace.mdx b/src/content/changelog/agents/2026-10-14-think-computer-workspace.mdx new file mode 100644 index 00000000000..44aab711972 --- /dev/null +++ b/src/content/changelog/agents/2026-10-14-think-computer-workspace.mdx @@ -0,0 +1,43 @@ +--- +title: Think agents now use a @cloudflare/computer Workspace +description: Think and Agent Skills now work in a Workspace from @cloudflare/computer. @cloudflare/shell is deprecated. +products: + - agents + - workers +date: 2026-10-14 +--- + +import { TypeScriptExample } from "~/components"; + +[Think](/agents/harnesses/think/) and [Agent Skills](/agents/runtime/execution/agent-skills/) now work in a `Workspace` from [`@cloudflare/computer`](https://github.com/cloudflare/computer). Think's built-in workspace tools are now Computer's tools, and you configure them with `workspaceTools`. Add an execution backend to the Workspace to give the model an `exec` tool. + +`@cloudflare/shell` is deprecated, and so is Think's `createExecuteTool`. + + + +```ts +import { Think } from "@cloudflare/think"; +import { Workspace } from "@cloudflare/computer"; +import { WorkerJavaScriptBackend } from "@cloudflare/computer/backends/worker-javascript"; + +export class MyAgent extends Think { + override workspace = new Workspace({ + storage: this.ctx.storage, + backends: [ + new WorkerJavaScriptBackend({ id: "js", loader: this.env.LOADER }), + ], + }); + + override workspaceTools = { + exec: { js: { description: "Run JavaScript against workspace files." } }, + }; +} +``` + + + +## Migrate your workspace data + +This is a breaking change. Computer stores files in different tables from Shell, and nothing moves your data automatically. To keep an existing workspace, copy its files with the script in [Migrating from `@cloudflare/shell` to `@cloudflare/computer`](https://github.com/cloudflare/agents/blob/main/docs/shell/migrating-to-computer.md). If you do not, your agent starts with an empty workspace. + +For more information, refer to [Think tools](/agents/harnesses/think/tools/#built-in-workspace-tools). diff --git a/src/content/docs/agents/harnesses/think/configuration.mdx b/src/content/docs/agents/harnesses/think/configuration.mdx index 70ffc0fe9f6..6a24e598f3c 100644 --- a/src/content/docs/agents/harnesses/think/configuration.mdx +++ b/src/content/docs/agents/harnesses/think/configuration.mdx @@ -27,12 +27,12 @@ Think is configured by overriding methods and properties on your `Think` subclas | `configureSession()` | identity | Add context blocks, compaction, search, skills — refer to [Sessions](/agents/runtime/lifecycle/sessions/) | | `getSkills()` | `[]` | Return Agent Skills sources for on-demand skill activation — refer to [Agent Skills](/agents/runtime/execution/agent-skills/) | | `getSkillScriptRunner()` | `null` | Enable the optional `run_skill_script` tool | -| `workspaceBash` | `true` | Include or configure the default workspace `bash` tool — refer to [Tools](/agents/harnesses/think/tools/) | +| `workspaceTools` | `{}` | Options for the `@cloudflare/computer` workspace tools (`exec` backends and descriptions, read limits, `readonly`). `false` omits them. Refer to [Tools](/agents/harnesses/think/tools/#configure-the-tools) | | `messageConcurrency` | `"queue"` | How overlapping submits behave — refer to [Client tools](/agents/harnesses/think/client-tools/#message-concurrency) | -| `includeMcpTools` | `true` | Convert connected MCP tools to AI SDK tools and add them to model turns. Refer to [MCP tools](/agents/harnesses/think/tools/#mcp-tools) | +| `includeMcpTools` | `true` | Convert connected MCP tools to AI SDK tools and add them to model turns. Refer to [MCP tools](/agents/harnesses/think/tools/#mcp-tools) | | `waitForMcpConnections` | `false` | Wait for MCP servers before inference | -| `chatRecovery` | Always on | Durable recovery configuration. Refer to [Durable recovery](/agents/harnesses/think/recovery/) for all options and defaults | -| `chatStreamStallTimeoutMs` | `0` (off) | Opt-in inactivity watchdog: abort a turn whose model stream produces no chunk for this long (measures the gap between chunks, including tool execution). A stall routes into bounded recovery | +| `chatRecovery` | Always on | Durable recovery configuration. Refer to [Durable recovery](/agents/harnesses/think/recovery/) for all options and defaults | +| `chatStreamStallTimeoutMs` | `0` (off) | Opt-in inactivity watchdog: abort a turn whose model stream produces no chunk for this long (measures the gap between chunks, including tool execution). A stall routes into bounded recovery | | `contextOverflow` | `undefined` | Opt-in mid-turn context-overflow handling with `reactive`, `maxRetries`, and `proactive` options. Requires `classifyChatError` plus a session compaction function — refer to [Context-window overflow recovery](/agents/harnesses/think/recovery/#context-window-overflow-recovery) | For `chatRecovery` and `chatStreamStallTimeoutMs` behavior, refer to [Durable recovery](/agents/harnesses/think/recovery/). @@ -122,17 +122,16 @@ For the full Session API — context blocks, compaction, search, skills, and mul ## Package exports -| Export | Description | -| --------------------------------------- | ------------------------------------------------------------- | -| `@cloudflare/think` | `Think`, `Session`, `Workspace`, `skills` namespace | -| `@cloudflare/think/messengers` | Messenger contracts, Chat SDK bridge, state agent, delivery | -| `@cloudflare/think/messengers/telegram` | Telegram messenger provider and delivery helpers | -| `@cloudflare/think/workflows` | `ThinkWorkflow`, `step.prompt()` — Workflow prompts | -| `@cloudflare/think/tools/workspace` | `createWorkspaceTools()` — for custom storage backends | -| `@cloudflare/think/tools/execute` | `createExecuteTool()` — sandboxed code execution via Code Mode | -| `@cloudflare/think/tools/browser` | `createBrowserTools()` — Chrome DevTools Protocol tools | -| `@cloudflare/think/tools/extensions` | `createExtensionTools()` — LLM-driven extension loading | -| `@cloudflare/think/extensions` | `ExtensionManager`, `HostBridgeLoopback` — extension runtime | +| Export | Description | +| --------------------------------------- | ------------------------------------------------------------ | +| `@cloudflare/think` | `Think`, `Session`, `lazyWorkspace`, `skills` namespace | +| `@cloudflare/think/messengers` | Messenger contracts, Chat SDK bridge, state agent, delivery | +| `@cloudflare/think/messengers/telegram` | Telegram messenger provider and delivery helpers | +| `@cloudflare/think/workflows` | `ThinkWorkflow`, `step.prompt()` — Workflow prompts | +| `@cloudflare/think/tools/execute` | `createExecuteTool()` — deprecated Code Mode execution tool | +| `@cloudflare/think/tools/browser` | `createBrowserTools()` — Chrome DevTools Protocol tools | +| `@cloudflare/think/tools/extensions` | `createExtensionTools()` — LLM-driven extension loading | +| `@cloudflare/think/extensions` | `ExtensionManager`, `HostBridgeLoopback` — extension runtime | ## Dependencies @@ -143,14 +142,13 @@ Peer dependencies you provide: | `agents` | yes | Cloudflare Agents SDK | | `ai` | yes | AI SDK v6 | | `zod` | yes | Schema validation (v4) | +| `@cloudflare/computer` | yes | Workspace and workspace tools | | `@chat-adapter/telegram` | optional | Required for Telegram messengers | Bundled with `@cloudflare/think`: -| Package | Notes | -| ---------------------- | ----------------------------------------------------- | -| `@cloudflare/shell` | `Workspace` filesystem | -| `@cloudflare/codemode` | Code execution for `createExecuteTool()` | -| `just-bash` | Sandboxed shell for the default workspace `bash` tool | +| Package | Notes | +| ---------------------- | ---------------------------------------- | +| `@cloudflare/codemode` | Code execution for `createExecuteTool()` | The Agent Skills engine and its script runner live in [`agents/skills`](/agents/runtime/execution/agent-skills/), so skill scripts pull `@cloudflare/worker-bundler` and `just-bash` through `agents`, not Think. diff --git a/src/content/docs/agents/harnesses/think/getting-started.mdx b/src/content/docs/agents/harnesses/think/getting-started.mdx index 74b36c7dc6b..d5770f64d3c 100644 --- a/src/content/docs/agents/harnesses/think/getting-started.mdx +++ b/src/content/docs/agents/harnesses/think/getting-started.mdx @@ -18,7 +18,7 @@ By the end of this tutorial you will have a Think agent that: - Streams responses to a React chat UI - Has persistent memory the model can read and write -- Includes workspace file tools (read, write, edit, find, grep, delete) +- Includes workspace file tools (read, ls, find, grep, write, edit, delete) - Supports custom server-side tools ## Prerequisites @@ -37,7 +37,7 @@ npm init -y Install dependencies: ```sh -npm install @cloudflare/think @cloudflare/ai-chat agents ai @cloudflare/shell zod workers-ai-provider react react-dom +npm install @cloudflare/think @cloudflare/computer @cloudflare/ai-chat agents ai zod workers-ai-provider react react-dom npm install -D wrangler @cloudflare/vite-plugin @cloudflare/workers-types @vitejs/plugin-react @tailwindcss/vite tailwindcss typescript vite ``` @@ -133,7 +133,7 @@ This is a working agent. Think automatically provides: - WebSocket chat protocol (compatible with `useAgentChat`) - Message persistence in SQLite - Resumable streaming (page refresh replays buffered chunks) -- Workspace file tools (read, write, edit, list, find, grep, delete) +- Workspace file tools (read, ls, find, grep, write, edit, delete) - Abort/cancel support - Error handling with partial message persistence @@ -297,7 +297,7 @@ export class MyAgent extends Think { Think merges tools from multiple sources automatically. On every turn, the model has access to: -1. **Workspace tools** — read, write, edit, list, find, grep, delete, bash (built-in) +1. **Workspace tools** — read, ls, find, grep, write, edit, delete, plus exec when the Workspace has a backend (built-in) 2. **Your tools** — from `getTools()` 3. **Extension tools** — from loaded extensions 4. **Session tools** — set_context, load_context, search_context (from `configureSession`) diff --git a/src/content/docs/agents/harnesses/think/index.mdx b/src/content/docs/agents/harnesses/think/index.mdx index 429d443b4bf..e11a8dbfe35 100644 --- a/src/content/docs/agents/harnesses/think/index.mdx +++ b/src/content/docs/agents/harnesses/think/index.mdx @@ -32,7 +32,7 @@ If this is your first agent, start with the [Getting started tutorial](/agents/h ### Install - + Think supports AI SDK v6 and v7. Use `ai@^6` with `@ai-sdk/react@^3`, or use `ai@^7` with `@ai-sdk/react@^4`. Keep the AI SDK packages on matching major versions throughout your project. diff --git a/src/content/docs/agents/harnesses/think/tools.mdx b/src/content/docs/agents/harnesses/think/tools.mdx index dea6092a761..b2f51838895 100644 --- a/src/content/docs/agents/harnesses/think/tools.mdx +++ b/src/content/docs/agents/harnesses/think/tools.mdx @@ -1,7 +1,7 @@ --- title: Tools pcx_content_type: reference -description: Built-in workspace tools (including bash), custom tools, approvals, MCP tools, code execution, browser tools, and extensions for Think agents. +description: Built-in workspace tools, custom tools, approvals, MCP tools, code execution, browser tools, and extensions for Think agents. sidebar: order: 4 products: @@ -16,7 +16,7 @@ Think provides built-in workspace file tools on every turn, plus integration poi On every turn, Think merges tools from multiple sources. Later sources override earlier ones if names collide: -1. **Workspace tools** — `read`, `write`, `edit`, `list`, `find`, `grep`, `delete`, `bash` (built-in) +1. **Workspace tools** — `read`, `ls`, `find`, `grep`, `write`, `edit`, `delete`, plus `exec` and `publish` when configured (built-in) 2. **`getTools()`** — your custom server-side tools 3. **Extension tools** — tools from loaded extensions (prefixed by extension name) 4. **Session tools** — `set_context`, `load_context`, `search_context` (from `configureSession`) @@ -28,30 +28,54 @@ Tools belong to the agent running the turn. For parent-child orchestration, use ## Built-in workspace tools -Every Think agent gets `this.workspace` — a virtual filesystem backed by Durable Object SQLite. Workspace tools are automatically available to the model with no configuration. +Every Think agent gets `this.workspace`, a `Workspace` from [`@cloudflare/computer`](https://github.com/cloudflare/computer) stored in the Durable Object's SQLite. Think adds Computer's AI SDK tools to every turn with no configuration. -| Tool | Description | -| -------- | --------------------------------------------------------------------------- | -| `read` | Read text with line numbers; pass images and PDFs to multimodal models | -| `write` | Write content to a file (creates parent directories) | -| `edit` | Apply a find-and-replace edit to an existing file (supports fuzzy matching) | -| `list` | List files and directories in a path | -| `find` | Find files matching a glob pattern | -| `grep` | Search file contents by regex or fixed string | -| `delete` | Delete a file or directory | -| `bash` | Run a sandboxed Bash script against workspace files | +| Tool | Description | +| --------- | ----------------------------------------------------------------------------------- | +| `read` | Read text with line and byte paging; pass images and PDFs to multimodal models | +| `ls` | List files and directories in a path, with pagination | +| `find` | Find files matching a glob pattern | +| `grep` | Search file contents by regex or fixed string | +| `write` | Write content to a file (creates parent directories) | +| `edit` | Apply exact text replacements to a file, falling back to whitespace-tolerant search | +| `delete` | Delete a file or directory | +| `exec` | Run a command or module on one of the Workspace's execution backends | +| `publish` | Share a workspace file through a presigned URL, when the Workspace has assets | -The `bash` tool is enabled by default. It mounts workspace files into a `just-bash` virtual filesystem, runs with network access disabled, and writes created, updated, and deleted files and empty directories back to the workspace. Use it for shell-style workflows that combine multiple file operations; use the narrower tools for simple reads, writes, and edits. +Paths are absolute. Computer's tools and backends treat `/workspace` as the working root, and Think writes its own files there too. -To keep tool calls bounded, the Bash tool snapshots up to 1,000 workspace files by default and skips files larger than 1 MB. Skipped files are reported in the tool result and are treated as protected during write-back so the script cannot accidentally overwrite or delete content that was not mounted. You can tune `maxWorkspaceFiles`, `maxWorkspaceFileBytes`, `maxOutputBytes`, `timeout`, and `network` through `workspaceBash`. +`@cloudflare/computer` is a peer dependency of Think: -Disable the default Bash tool for conservative deployments: +```sh +npm install @cloudflare/computer +``` + +### Run code with `exec` + +The default Workspace has no execution backends, so there is no `exec` tool until you add one. Configure the backends, and the modules they offer, on the Workspace: ```ts +import { Think } from "@cloudflare/think"; +import { Workspace } from "@cloudflare/computer"; +import { WorkerJavaScriptBackend } from "@cloudflare/computer/backends/worker-javascript"; +import { createGitClient } from "@cloudflare/computer/git"; +import { createGitModule } from "@cloudflare/computer/modules/git"; + export class MyAgent extends Think { - workspaceBash = false; + override workspace = new Workspace({ + storage: this.ctx.storage, + git: createGitClient(), + backends: [ + new WorkerJavaScriptBackend({ + id: "js", + loader: this.env.LOADER, + access: "read-write", + modules: { "ws:git": createGitModule() }, + }), + ], + }); getModel() { /* ... */ @@ -61,42 +85,107 @@ export class MyAgent extends Think { -### R2 spillover +The JavaScript backend runs code in a [Dynamic Worker](/dynamic-workers/), so it needs a Worker Loader binding: + + + +```toml +[[worker_loaders]] +binding = "LOADER" +``` + + + +Computer also ships a `just-bash` shell backend that runs in Dynamic Workers, and a container backend with a full Linux userland. Refer to the [Computer README](https://github.com/cloudflare/computer/tree/main/packages/computer#choosing-a-backend) for each backend's bindings. -By default, the workspace stores everything in SQLite. For large files, override `workspace` to add R2 spillover: +### Call the agent's tools from code + +Give a JavaScript backend a `ws:tools` module, and code the model runs with `exec` can import the agent's tools. Code reads files through `node:fs/promises`, so serve `getTools()` rather than the workspace tools: ```ts -import { Think } from "@cloudflare/think"; -import { Workspace } from "@cloudflare/shell"; +import { createToolBindings } from "@cloudflare/computer/modules/tools"; +import { forAISDKTools } from "@cloudflare/computer/tools/ai-sdk"; -export class MyAgent extends Think { - override workspace = new Workspace({ - sql: this.ctx.storage.sql, - r2: this.env.R2, - name: () => this.name, - }); +new WorkerJavaScriptBackend({ + id: "js", + loader: this.env.LOADER, + modules: { + "ws:tools": createToolBindings(forAISDKTools(() => this.getTools())), + }, +}); +``` - getModel() { - /* ... */ - } + + +Code the model runs with `exec`: + +```js +import { readFile } from "node:fs/promises"; +import { getWeather } from "ws:tools"; + +export default async function () { + const cities = JSON.parse(await readFile("/workspace/cities.json", "utf8")); + const reports = []; + for (const city of cities) reports.push((await getWeather({ city })).text); + return reports; +} +``` + +`ws:tools` does not export tools that need approval or tools that run in the browser, because nothing can approve or run them from code. Calls from code do not go through `beforeToolCall`. Refer to [`ws:tools`](https://github.com/cloudflare/computer/blob/main/docs/17_isolate_javascript.md#wstools) for how calls and results work. + +### Configure the tools + +`workspaceTools` takes the options of `createAITools` from `@cloudflare/computer/tools/ai-sdk`. Use `exec` to choose which backends the model can run on and to describe them. Your text comes before each backend's own description: + + + +```ts +export class MyAgent extends Think { + override workspaceTools = { + exec: { js: { description: "Use for multi-file edits and git." } }, + read: { maxBytes: 32 * 1024, maxLines: 800 }, + }; } ``` -This requires an R2 bucket binding: +Set `readonly: true` to keep only `read`, `ls`, `find`, and `grep`. Set `workspaceTools = false` to omit the workspace tools entirely. - +### Share a workspace -```toml -[[r2_buckets]] -binding = "R2" -bucket_name = "agent-files" +To work in a Workspace another Durable Object owns, wrap `getWorkspace` in `lazyWorkspace`. Think contacts the owner only when a turn first touches a file: + + + +```ts +import { getWorkspace } from "@cloudflare/computer"; +import { Think, lazyWorkspace } from "@cloudflare/think"; + +export class Chat extends Think { + override workspace = lazyWorkspace(async () => + getWorkspace(await this.parentAgent(Directory)), + ); +} ``` - + + +Every Think agent can hand out its Workspace this way. `getWorkspace(stub)` calls the agent's `__getWorkspaceStub()` method over RPC. A lazy Workspace gets the file tools but no `exec`. + +### Upgrade from `@cloudflare/shell` + +Earlier versions of Think used a `Workspace` from `@cloudflare/shell`, which is now deprecated. Computer stores files in different tables, and Think does not move your data. To keep an existing workspace, copy its files with the script in [Migrating from `@cloudflare/shell` to `@cloudflare/computer`](https://github.com/cloudflare/agents/blob/main/docs/shell/migrating-to-computer.md). + +The upgrade also changes the tools: + +- `list` is now `ls`. +- The in-process `bash` tool is gone. Add a backend to the Workspace to get `exec`. +- `workspaceBash`, `createWorkspaceTools`, and `@cloudflare/think/tools/workspace` are removed. + +Refer to [Upgrading to a Computer workspace](https://github.com/cloudflare/agents/blob/main/docs/think/index.md#upgrading-to-a-computer-workspace) for the full list. ## Custom tools @@ -150,7 +239,7 @@ getTools(): ToolSet { inputSchema: z.object({ path: z.string() }), needsApproval: async ({ path }) => path.startsWith("/important/"), execute: async ({ path }) => { - await this.workspace.rm(path); + await this.workspace.fs.rm(path); return { deleted: path }; }, }), @@ -249,18 +338,23 @@ export class MyAgent extends Think { ## Code execution tool +:::caution[Deprecated] +`createExecuteTool` and `createExecuteRuntime` are deprecated. Use `exec` on a JavaScript backend with a `ws:tools` module instead. Refer to [Call the agent's tools from code](#call-the-agents-tools-from-code). The execute tool keeps working until it is removed along with `@cloudflare/codemode`. +::: + Let the LLM write and run JavaScript in a sandboxed Worker, recorded on a durable Code Mode runtime (abort-and-replay, human approvals, audit trail, reusable snippets). Requires `@cloudflare/codemode` and a `worker_loaders` binding. ```sh npm install @cloudflare/codemode ``` -The one-liner infers everything from the agent — `state.*` from `this.workspace`, the executor from `env.LOADER`, and a live browser (`cdp.*`) from `env.BROWSER` if bound: +The one-liner infers the executor from `env.LOADER` and a live browser (`cdp.*`) from `env.BROWSER` if bound. Pass tools for `tools.*`, including the workspace tools if the sandbox should reach the workspace: ```ts import { Think } from "@cloudflare/think"; +import { createAITools } from "@cloudflare/computer/tools/ai-sdk"; import { createExecuteTool } from "@cloudflare/think/tools/execute"; export class MyAgent extends Think { @@ -270,7 +364,9 @@ export class MyAgent extends Think { getTools() { return { - execute: createExecuteTool(this), + execute: createExecuteTool(this, { + tools: createAITools({ workspace: this.workspace }), + }), }; } } @@ -308,31 +404,17 @@ Each missing piece fails with an error naming the step. Inside the sandbox the model sees typed namespaces plus the platform SDK: - `tools.*` — your AI SDK tools (object args, validated against their schemas). Only tools with an `execute` function are exposed — client-side tools cannot run in the sandbox. -- `state.*` — the workspace filesystem (`state.readFile({ path })`, `state.glob({ pattern })`, `state.planEdits(...)`, and so on). - `cdp.*` — the browser, when a Browser Run binding is configured. The execute tool defaults to `session: { mode: "dynamic" }`: sessions are per-execution unless the model promotes one with `cdp.startSession()`. - `codemode.search` / `codemode.describe` / `codemode.step` / `codemode.run` — discovery, side-effect boundaries, and saved snippets. -Pass overrides for anything beyond the defaults — for example, custom `tools.*` alongside the agent-derived state: +Or pass fully explicit options (no agent inference): ```ts -execute: createExecuteTool(this, { tools: myDomainTools }); -``` - - - -Or fully explicit options (no agent inference): - - - -```ts -import { createWorkspaceStateBackend } from "@cloudflare/shell"; - createExecuteTool({ ctx: this.ctx, tools: myDomainTools, - state: createWorkspaceStateBackend(this.workspace), browser: this.env.BROWSER, loader: this.env.LOADER, }); @@ -429,7 +511,7 @@ The tool is backed by a Code Mode runtime with the `cdp` connector: the model wr By default each execution gets a fresh browser session (`one-shot`), torn down when the run ends. Pass `session: { mode: "dynamic" }` to let the model promote a session with `cdp.startSession()` so later executions continue in the same browser, or `session: { mode: "reuse", key }` for a named long-lived session. Stale sessions are reclaimed by the connector's `sweep()` — call it from a scheduled task. :::note -The simplest setup is the unified execute tool in [Code execution tool](#code-execution-tool): `createExecuteTool(this)` already includes `cdp.*` alongside `state.*` and `tools.*` when `env.BROWSER` is bound — one tool, one durable history. Use `createBrowserTools` when you want a separate, browser-only tool. +The simplest setup is the unified execute tool in [Code execution tool](#code-execution-tool): `createExecuteTool(this)` already includes `cdp.*` alongside `tools.*` when `env.BROWSER` is bound — one tool, one durable history. Use `createBrowserTools` when you want a separate, browser-only tool. ::: For a custom Chrome endpoint, pass `cdpUrl` instead of `browser`: @@ -564,56 +646,3 @@ getExtensions() { ``` The context block is registered as `notes_scratchpad` (namespaced by extension name). - -## Custom workspace backends - -The individual tool factories are exported for use with custom storage backends: - - - -```ts -import { - createReadTool, - createWriteTool, - createEditTool, - createListTool, - createFindTool, - createGrepTool, - createDeleteTool, - createWorkspaceTools, -} from "@cloudflare/think/tools/workspace"; -``` - - - -Implement the operations interface for your storage backend: - - - -```ts -import type { ReadOperations } from "@cloudflare/think/tools/workspace"; - -const myReadOps: ReadOperations = { - readFile: async (path) => fetchFromMyStorage(path), - stat: async (path) => getFileInfo(path), -}; - -const readTool = createReadTool({ ops: myReadOps }); -``` - - - -Or create the full set from a `Workspace`, optionally disabling the Bash tool: - - - -```ts -import { createWorkspaceTools } from "@cloudflare/think/tools/workspace"; - -const tools = createWorkspaceTools(myCustomWorkspace); -const toolsWithoutBash = createWorkspaceTools(myCustomWorkspace, { - bash: false, -}); -``` - - diff --git a/src/content/docs/agents/runtime/execution/agent-skills.mdx b/src/content/docs/agents/runtime/execution/agent-skills.mdx index 133da646ae1..580acff3445 100644 --- a/src/content/docs/agents/runtime/execution/agent-skills.mdx +++ b/src/content/docs/agents/runtime/execution/agent-skills.mdx @@ -113,6 +113,8 @@ export default async function run(input: unknown, ctx: SkillRunContext) { `ctx` is `{ skill, files, workspace, tools, output }`. `ctx.files` holds bundled text resources by relative path, `ctx.workspace` is gated by the workspace permission, `ctx.tools` only exposes tools the runner was given, and `ctx.output.writeFile(name, content)` returns scratch artifacts to the model (it does not mutate the workspace). Python and Bash use the path-based contract instead: `/input.json`, `/context.json`, bundled resources under `/skill`, and `/output` for artifacts. +`workspaceInstance` must be a `Workspace` from [`@cloudflare/computer`](https://github.com/cloudflare/computer). In Think, `this.workspace` already is one. Relative paths in skill scripts resolve against `/workspace`. + Passing `workspaceInstance` gives scripts read-only workspace access by default. Network access, tools, and workspace writes are opt-in. The default timeout is 30 seconds. ## Example diff --git a/src/content/docs/agents/tools/browser.mdx b/src/content/docs/agents/tools/browser.mdx index a1d70c1e4ff..571297e4de8 100644 --- a/src/content/docs/agents/tools/browser.mdx +++ b/src/content/docs/agents/tools/browser.mdx @@ -581,7 +581,7 @@ The browser agent example uses the legacy tools. It covers Browser Run setup, to ### Think execute tool -Think's unified execute tool, `createExecuteTool(this)`, includes `cdp.*` alongside `state.*` and `tools.*` when `env.BROWSER` is bound. It uses the legacy browser connector. Refer to [Think tools](/agents/harnesses/think/tools/). +Think's unified execute tool, `createExecuteTool(this)`, includes `cdp.*` alongside `tools.*` when `env.BROWSER` is bound. It uses the legacy browser connector. The execute tool is deprecated in favour of the Workspace `exec` tool. Refer to [Think tools](/agents/harnesses/think/tools/). ## Related resources diff --git a/src/content/docs/agents/tools/codemode/ai-sdk.mdx b/src/content/docs/agents/tools/codemode/ai-sdk.mdx index 2087c51bdbf..62c521e80bd 100644 --- a/src/content/docs/agents/tools/codemode/ai-sdk.mdx +++ b/src/content/docs/agents/tools/codemode/ai-sdk.mdx @@ -125,9 +125,9 @@ The default namespace is `codemode`. `createCodeTool()` also accepts a custom `d A tool provider groups tools under one sandbox namespace. Pass the tool set directly when every tool belongs under `codemode.*`. -Use `aiTools()` when combining AI SDK tools with providers from other packages. The following optional workspace example also requires `@cloudflare/shell`: +Use `aiTools()` when combining AI SDK tools with providers from other packages. The following optional workspace example also requires [`@cloudflare/computer`](https://github.com/cloudflare/computer): - + @@ -135,16 +135,22 @@ Use `aiTools()` when combining AI SDK tools with providers from other packages. import { AIChatAgent } from "@cloudflare/ai-chat"; import { DynamicWorkerExecutor } from "@cloudflare/codemode"; import { aiTools, createCodeTool } from "@cloudflare/codemode/ai"; -import { Workspace } from "@cloudflare/shell"; -import { stateTools } from "@cloudflare/shell/workers"; +import { Workspace } from "@cloudflare/computer"; +import { createAITools } from "@cloudflare/computer/tools/ai-sdk"; import { weatherTools } from "./tools"; export class Chat extends AIChatAgent { - workspace = new Workspace({ sql: this.ctx.storage.sql }); + workspace = new Workspace({ storage: this.ctx.storage }); codemodeTool() { return createCodeTool({ - tools: [aiTools(weatherTools), stateTools(this.workspace)], + tools: [ + aiTools(weatherTools), + { + name: "workspace", + tools: createAITools({ workspace: this.workspace }), + }, + ], executor: new DynamicWorkerExecutor({ loader: this.env.LOADER }), }); } @@ -153,7 +159,7 @@ export class Chat extends AIChatAgent { -This example exposes AI SDK tools as `codemode.*` and workspace tools as `state.*`. +This example exposes AI SDK tools as `codemode.*` and workspace tools as `workspace.*`, for example `workspace.read({ path })`. To assign custom namespaces, pass provider objects instead: From f782612e16c3a23acf571c0fc95afd67828386d2 Mon Sep 17 00:00:00 2001 From: Matt Carey Date: Wed, 14 Oct 2026 15:23:02 +0200 Subject: [PATCH 2/5] [Agents] Drop workspaceTools from Think docs --- .../2026-10-14-think-computer-workspace.mdx | 6 +----- .../agents/harnesses/think/configuration.mdx | 1 - .../docs/agents/harnesses/think/tools.mdx | 17 +++++++++-------- 3 files changed, 10 insertions(+), 14 deletions(-) diff --git a/src/content/changelog/agents/2026-10-14-think-computer-workspace.mdx b/src/content/changelog/agents/2026-10-14-think-computer-workspace.mdx index 44aab711972..ecb1c4ec6ac 100644 --- a/src/content/changelog/agents/2026-10-14-think-computer-workspace.mdx +++ b/src/content/changelog/agents/2026-10-14-think-computer-workspace.mdx @@ -9,7 +9,7 @@ date: 2026-10-14 import { TypeScriptExample } from "~/components"; -[Think](/agents/harnesses/think/) and [Agent Skills](/agents/runtime/execution/agent-skills/) now work in a `Workspace` from [`@cloudflare/computer`](https://github.com/cloudflare/computer). Think's built-in workspace tools are now Computer's tools, and you configure them with `workspaceTools`. Add an execution backend to the Workspace to give the model an `exec` tool. +[Think](/agents/harnesses/think/) and [Agent Skills](/agents/runtime/execution/agent-skills/) now work in a `Workspace` from [`@cloudflare/computer`](https://github.com/cloudflare/computer). Think's built-in workspace tools are now Computer's tools. Add an execution backend to the Workspace and the model gets an `exec` tool. `@cloudflare/shell` is deprecated, and so is Think's `createExecuteTool`. @@ -27,10 +27,6 @@ export class MyAgent extends Think { new WorkerJavaScriptBackend({ id: "js", loader: this.env.LOADER }), ], }); - - override workspaceTools = { - exec: { js: { description: "Run JavaScript against workspace files." } }, - }; } ``` diff --git a/src/content/docs/agents/harnesses/think/configuration.mdx b/src/content/docs/agents/harnesses/think/configuration.mdx index 6a24e598f3c..8a31ca3f254 100644 --- a/src/content/docs/agents/harnesses/think/configuration.mdx +++ b/src/content/docs/agents/harnesses/think/configuration.mdx @@ -27,7 +27,6 @@ Think is configured by overriding methods and properties on your `Think` subclas | `configureSession()` | identity | Add context blocks, compaction, search, skills — refer to [Sessions](/agents/runtime/lifecycle/sessions/) | | `getSkills()` | `[]` | Return Agent Skills sources for on-demand skill activation — refer to [Agent Skills](/agents/runtime/execution/agent-skills/) | | `getSkillScriptRunner()` | `null` | Enable the optional `run_skill_script` tool | -| `workspaceTools` | `{}` | Options for the `@cloudflare/computer` workspace tools (`exec` backends and descriptions, read limits, `readonly`). `false` omits them. Refer to [Tools](/agents/harnesses/think/tools/#configure-the-tools) | | `messageConcurrency` | `"queue"` | How overlapping submits behave — refer to [Client tools](/agents/harnesses/think/client-tools/#message-concurrency) | | `includeMcpTools` | `true` | Convert connected MCP tools to AI SDK tools and add them to model turns. Refer to [MCP tools](/agents/harnesses/think/tools/#mcp-tools) | | `waitForMcpConnections` | `false` | Wait for MCP servers before inference | diff --git a/src/content/docs/agents/harnesses/think/tools.mdx b/src/content/docs/agents/harnesses/think/tools.mdx index b2f51838895..d2d3bd92255 100644 --- a/src/content/docs/agents/harnesses/think/tools.mdx +++ b/src/content/docs/agents/harnesses/think/tools.mdx @@ -135,24 +135,25 @@ export default async function () { `ws:tools` does not export tools that need approval or tools that run in the browser, because nothing can approve or run them from code. Calls from code do not go through `beforeToolCall`. Refer to [`ws:tools`](https://github.com/cloudflare/computer/blob/main/docs/17_isolate_javascript.md#wstools) for how calls and results work. -### Configure the tools +### Limit the tools -`workspaceTools` takes the options of `createAITools` from `@cloudflare/computer/tools/ai-sdk`. Use `exec` to choose which backends the model can run on and to describe them. Your text comes before each backend's own description: +The model gets `exec` for every backend on the Workspace. Each backend describes itself to the model, so there is nothing to configure in Think. + +To narrow the tools for a turn, return `activeTools` from `beforeTurn`. This turn only reads files: ```ts export class MyAgent extends Think { - override workspaceTools = { - exec: { js: { description: "Use for multi-file edits and git." } }, - read: { maxBytes: 32 * 1024, maxLines: 800 }, - }; + beforeTurn() { + return { activeTools: ["read", "ls", "find", "grep"] }; + } } ``` -Set `readonly: true` to keep only `read`, `ls`, `find`, and `grep`. Set `workspaceTools = false` to omit the workspace tools entirely. +To replace a workspace tool, return a tool with the same name from `getTools()`. Refer to [Tool merge order](#tool-merge-order). ### Share a workspace @@ -183,7 +184,7 @@ The upgrade also changes the tools: - `list` is now `ls`. - The in-process `bash` tool is gone. Add a backend to the Workspace to get `exec`. -- `workspaceBash`, `createWorkspaceTools`, and `@cloudflare/think/tools/workspace` are removed. +- `workspaceBash`, `createWorkspaceTools`, and `@cloudflare/think/tools/workspace` are removed. Use `activeTools` in `beforeTurn` to limit the tools. Refer to [Upgrading to a Computer workspace](https://github.com/cloudflare/agents/blob/main/docs/think/index.md#upgrading-to-a-computer-workspace) for the full list. From 5d5b44113d7eead3de60e1a6124c7670257e151f Mon Sep 17 00:00:00 2001 From: Matt Carey Date: Wed, 14 Oct 2026 15:29:43 +0200 Subject: [PATCH 3/5] [Agents] Address review comments --- .../changelog/agents/2026-10-14-think-computer-workspace.mdx | 2 +- src/content/docs/agents/harnesses/think/getting-started.mdx | 2 +- src/content/docs/agents/tools/browser.mdx | 4 ---- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/content/changelog/agents/2026-10-14-think-computer-workspace.mdx b/src/content/changelog/agents/2026-10-14-think-computer-workspace.mdx index ecb1c4ec6ac..6c5c88fd2d5 100644 --- a/src/content/changelog/agents/2026-10-14-think-computer-workspace.mdx +++ b/src/content/changelog/agents/2026-10-14-think-computer-workspace.mdx @@ -34,6 +34,6 @@ export class MyAgent extends Think { ## Migrate your workspace data -This is a breaking change. Computer stores files in different tables from Shell, and nothing moves your data automatically. To keep an existing workspace, copy its files with the script in [Migrating from `@cloudflare/shell` to `@cloudflare/computer`](https://github.com/cloudflare/agents/blob/main/docs/shell/migrating-to-computer.md). If you do not, your agent starts with an empty workspace. +This is a breaking change. Computer stores files in different tables from Shell, and there is no automatic data migration between workspace formats. To keep an existing workspace, copy its files with the script in [Migrating from `@cloudflare/shell` to `@cloudflare/computer`](https://github.com/cloudflare/agents/blob/main/docs/shell/migrating-to-computer.md). If you do not, your agent starts with an empty workspace. For more information, refer to [Think tools](/agents/harnesses/think/tools/#built-in-workspace-tools). diff --git a/src/content/docs/agents/harnesses/think/getting-started.mdx b/src/content/docs/agents/harnesses/think/getting-started.mdx index d5770f64d3c..428046a1c87 100644 --- a/src/content/docs/agents/harnesses/think/getting-started.mdx +++ b/src/content/docs/agents/harnesses/think/getting-started.mdx @@ -18,7 +18,7 @@ By the end of this tutorial you will have a Think agent that: - Streams responses to a React chat UI - Has persistent memory the model can read and write -- Includes workspace file tools (read, ls, find, grep, write, edit, delete) +- Includes workspace file tools (read, ls, find, grep, write, edit, delete) from @cloudflare/computer - Supports custom server-side tools ## Prerequisites diff --git a/src/content/docs/agents/tools/browser.mdx b/src/content/docs/agents/tools/browser.mdx index 571297e4de8..8bc6f0d7305 100644 --- a/src/content/docs/agents/tools/browser.mdx +++ b/src/content/docs/agents/tools/browser.mdx @@ -579,10 +579,6 @@ The browser agent example uses the legacy tools. It covers Browser Run setup, to description="Build an agent that can browse the web, inspect pages, capture screenshots, and debug frontend issues." /> -### Think execute tool - -Think's unified execute tool, `createExecuteTool(this)`, includes `cdp.*` alongside `tools.*` when `env.BROWSER` is bound. It uses the legacy browser connector. The execute tool is deprecated in favour of the Workspace `exec` tool. Refer to [Think tools](/agents/harnesses/think/tools/). - ## Related resources Date: Wed, 14 Oct 2026 15:34:22 +0200 Subject: [PATCH 4/5] [Agents] Mirror 'Changing the tools' from the agents docs --- .../docs/agents/harnesses/think/tools.mdx | 22 +++---------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/src/content/docs/agents/harnesses/think/tools.mdx b/src/content/docs/agents/harnesses/think/tools.mdx index d2d3bd92255..b22e9354da5 100644 --- a/src/content/docs/agents/harnesses/think/tools.mdx +++ b/src/content/docs/agents/harnesses/think/tools.mdx @@ -135,25 +135,9 @@ export default async function () { `ws:tools` does not export tools that need approval or tools that run in the browser, because nothing can approve or run them from code. Calls from code do not go through `beforeToolCall`. Refer to [`ws:tools`](https://github.com/cloudflare/computer/blob/main/docs/17_isolate_javascript.md#wstools) for how calls and results work. -### Limit the tools +### Change the tools -The model gets `exec` for every backend on the Workspace. Each backend describes itself to the model, so there is nothing to configure in Think. - -To narrow the tools for a turn, return `activeTools` from `beforeTurn`. This turn only reads files: - - - -```ts -export class MyAgent extends Think { - beforeTurn() { - return { activeTools: ["read", "ls", "find", "grep"] }; - } -} -``` - - - -To replace a workspace tool, return a tool with the same name from `getTools()`. Refer to [Tool merge order](#tool-merge-order). +`exec` offers every backend the Workspace has, and each backend describes itself to the model. To change a built-in tool, return a tool with the same name from `getTools()`. It replaces the built-in. To hide tools for a turn, return `activeTools` from `beforeTurn`. ### Share a workspace @@ -184,7 +168,7 @@ The upgrade also changes the tools: - `list` is now `ls`. - The in-process `bash` tool is gone. Add a backend to the Workspace to get `exec`. -- `workspaceBash`, `createWorkspaceTools`, and `@cloudflare/think/tools/workspace` are removed. Use `activeTools` in `beforeTurn` to limit the tools. +- `workspaceBash`, `createWorkspaceTools`, and `@cloudflare/think/tools/workspace` are removed, with no replacement. To change a built-in tool, return a tool with the same name from `getTools()`. To hide tools for a turn, return `activeTools` from `beforeTurn`. Refer to [Upgrading to a Computer workspace](https://github.com/cloudflare/agents/blob/main/docs/think/index.md#upgrading-to-a-computer-workspace) for the full list. From fa33b00e00d59d184f819b0c7680b5c75e959adf Mon Sep 17 00:00:00 2001 From: vance Date: Fri, 16 Oct 2026 16:25:47 -0500 Subject: [PATCH 5/5] Empty commit to trigger worker preview