Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/exec-tool-single-backend.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@cloudflare/computer": minor
---

The `exec` tool has no `backend` argument when only one backend is configured. It always runs there, its description no longer talks about choosing a backend, and `defaultBackend` becomes optional. A single shell backend also drops the `input` argument it could never accept, and a single callable backend describes `command` as ES module source. With more than one backend, nothing changes and `defaultBackend` is still required.
11 changes: 11 additions & 0 deletions .changeset/unified-modules.md

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@agent-think can you split this changeset into one per change, use one sentence for the summary and link to the relevant docs.

Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
"@cloudflare/computer": minor
---

`WorkerJavaScriptBackend` takes a single `modules` option. A string is bundled source, as before. An object of functions is a host module that runs in the Durable Object under a `ws:*` specifier, and each function becomes a named export: `modules: { "ws:weather": { forecast } }` lets code write `import { forecast } from "ws:weather"`. A factory, `(host) => ({ ... })`, builds a host module from the Workspace's Git client, Artifacts client, or runtime. Each function receives `(args, { signal, deadline, access, resolvePath })` and may return any JSON-compatible value.

`ws:git` and `ws:artifacts` are no longer installed automatically. Add `createGitModule()` from `@cloudflare/computer/modules/git` and `createArtifactsModule()` from `@cloudflare/computer/modules/artifacts`. `createContainerModule()` from `@cloudflare/computer/modules/container` runs shell commands in the Workspace's container backend. The container shares the Workspace's files, a canceled execution kills the command, and it refuses to run on a read-only backend. `node:fs` and `node:fs/promises` stay built in.

The backend now describes its source language and every module for a model, and the `exec` tool shows that text. A backend's `description` in the tool options becomes optional when the backend describes itself, so the module list the model reads always matches what is installed. The tool also stops offering `input` when no configured backend accepts it.

To migrate, move `trustedModules` entries into `modules`, replacing any `call(method, args)` handler with one function per method. Replace `allowGitNetwork: true` with `createGitModule({ allowNetwork: true })` and `allowArtifactNetwork: true` with `createArtifactsModule({ allowNetwork: true })`.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ SQLite and exposes one pluggable execution surface through
Workers RPC, so there is no second store or sync round trip.
- **Isolate JavaScript** runs an ECMAScript module in a fresh Dynamic
Worker with structured input/results, durable relative imports,
configured libraries, Workspace-backed `node:fs/promises`, and trusted `ws:git` and
`ws:artifacts` modules.
configured libraries, Workspace-backed `node:fs/promises`, and host modules such as
`ws:git`, `ws:artifacts`, and `ws:container`.

A Workspace may register multiple backends under stable IDs.
`workspace.runtime.exec(source, { backend })` is the single execution
Expand Down
25 changes: 23 additions & 2 deletions docs/09_tool_interface.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,16 @@ export class Agent {

Pass the returned AI SDK `ToolSet` to `generateText`, `streamText`, or an agent framework hook such as `getTools()`.

Pass `shell` only when the Workspace has matching backend ids:
Pass `shell` only when the Workspace has matching backend ids. With one backend, `exec` has no `backend` argument and always runs there:

```ts
const tools = createAITools({
workspace,
shell: { backends: { "worker-javascript": {} } },
});
```

With more than one, pass `defaultBackend` and the model picks a backend per call:

```ts
const tools = createAITools({
Expand Down Expand Up @@ -244,7 +253,19 @@ The tool uses forced removal, so deleting a missing path succeeds. Set `recursiv

## `exec`

`exec` is opt-in. It calls `workspace.runtime.exec` with the configured backend and streams bounded output. Backend descriptions are included in the model-facing tool description, so describe capabilities and startup cost in plain language.
`exec` is opt-in. It calls `workspace.runtime.exec` with the configured backend and streams bounded output.

Each backend's entry in the tool description joins two parts: the `description` you pass, and what the backend says about itself (`backend.description`, read through `workspace.runtime.describe(id)`). `WorkerJavaScriptBackend` describes its source language and every module code can import, so `{ "worker-javascript": {} }` is enough and the list stays in step with `modules`. A backend that does not describe itself needs a `description`. Describe capabilities and startup cost in plain language.

The tool offers only the arguments that can work:

| Backends | Arguments |
| --- | --- |
| One shell backend | `command`, `cwd`, `env` |
| One callable backend | `command`, `cwd`, `env`, `input` |
| More than one | `command`, `cwd`, `backend`, `env`, plus `input` when any is callable. `defaultBackend` is required. |

A `backend` value the model sends anyway is dropped when only one backend is configured. The output still names the backend that ran.

Wire this tool carefully: it executes arbitrary shell commands inside the configured backend. Treat its output as untrusted text when including it in later model input. Omit `shell` or use `readonly: true` when command execution is not part of the agent's job.

Expand Down
4 changes: 2 additions & 2 deletions docs/16_code_execution.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ The selected backend defines how it interprets `source`.
| --- | --- | --- |
| `container-shell` | shell command | Full Linux, native binaries, installed packages, processes |
| `worker-shell` | just-bash command | Fast text tools and Workspace Git without a Container |
| `worker-javascript` | ECMAScript module | Isolated structured JavaScript with trusted Workspace modules |
| `worker-javascript` | ECMAScript module | Isolated structured JavaScript with Workspace host modules |

Applications may register additional command or module backends under their own IDs. Backend IDs are part of the execution contract: changing the backend may change the source language.

Expand Down Expand Up @@ -85,4 +85,4 @@ new WorkerJavaScriptBackend({

The backend argument is never itself authorization.

See [17. Isolate JavaScript](./17_isolate_javascript.md) for module and trusted-package behavior.
See [17. Isolate JavaScript](./17_isolate_javascript.md) for module behavior.
Loading
Loading