Skip to content

computer: Offer only exec arguments that can work - #171

Open
mattzcarey wants to merge 1 commit into
feat/named-trusted-module-functionsfrom
feat/exec-tool-single-backend
Open

mattzcarey wants to merge 1 commit into
feat/named-trusted-module-functionsfrom
feat/exec-tool-single-backend

Conversation

@mattzcarey

@mattzcarey mattzcarey commented Sep 30, 2026 •

Copy link
Copy Markdown
Member

Stacked on #170.

The exec tool always offered a backend argument, even with one backend, and always offered input, even when nothing accepted it. Callers also described each backend by hand, so a JavaScript backend's modules had to be listed twice:

createAITools({
  workspace,
  shell: {
    defaultBackend: "js",
    backends: { js: { description: "JavaScript. ws:git exports clone, status, ..." } },
  },
});

The tool now offers only arguments that can work, and each backend's entry adds what the backend says about itself through workspace.runtime.describe(id) (added in #170):

createAITools({ workspace, shell: { backends: { "worker-javascript": {} } } });
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 required

With one backend, the description covers what it does instead of how to choose. For WorkerJavaScriptBackend that includes its module list:

Run code in the workspace.

`command` is ECMAScript module source, run in an isolated JavaScript runtime. ...
Code has no direct network access.

Modules code can import:
- `node:fs/promises` (also `node:fs`): the workspace's files. ...
- `ws:git`: The workspace's Git repository tools: `status({ dir })`, ...
- `ws:weather`: exports `forecast`.

A caller's description still comes first and is required only for a backend that does not describe itself. A backend value the model sends anyway is stripped by the schema, and the output still names the backend that ran. Internally, the tool builds one input schema instead of a single-backend and a multi-backend variant, and its output truncation moves to a shared UTF-8 helper.

The tests read the generated JSON Schema to check which arguments the model sees, parse a call that includes backend against a single-backend tool, and check the description against a real WorkerJavaScriptBackend. docs/09_tool_interface.md covers both configurations.

@changeset-bot

changeset-bot Bot commented Sep 30, 2026 •

Copy link
Copy Markdown

馃 Changeset detected

Latest commit: 6f7e54d

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 4 packages
Name Type
@cloudflare/computer Minor
@cloudflare/dofs Minor
@cloudflare/computer-rpc Minor
@cloudflare/computerd Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions

Copy link
Copy Markdown
Contributor

Thanks for your interest in Cloudflare Computer.

This repository does not accept unsolicited pull requests. Please use one of the accepted contribution paths instead:

If a maintainer asked you to open this pull request, they can add the allow-pr label and reopen it.

@github-actions github-actions Bot closed this Sep 30, 2026

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Devin Review found 1 potential issue.

Devin Review

inputSchema,
execute: async function* ({ command, cwd, backend, env, input }, { abortSignal }) {
const selectedBackend = backend ?? options.defaultBackend;
const selectedBackend = backend ?? defaultBackend;

@devin-ai-integration devin-ai-integration Bot Sep 30, 2026 •

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

馃敶 Single-backend calls can run elsewhere

When a caller passes backend directly to execute, selectedBackend overrides the sole configured backend. On a Workspace with another registered backend, the command runs there despite the single-backend configuration.

Learn more

The tool exposes an inputSchema and an execute function. AI SDK model calls parse through the schema, which removes backend for a single-backend tool. Direct consumers can call execute without parsing; createExecutorTool demonstrates wrapping that function. The execution path still accepts the supplied backend and forwards it to WorkspaceRuntime.exec. If the Workspace registers more backends than the tool exposes, this runs on an unadvertised backend.

Example: A Workspace registers shell and container, while the tool configures only shell. Calling execute({ command: "echo hello", backend: "container" }, options) runs in container; the single-backend tool was expected to run in shell.

Recommended fix: Select onlyBackend whenever single is true, regardless of the direct call's backend field. Retain the existing default and override behavior for multiple-backend tools.

Devin Review


Was this helpful? React with 馃憤 or 馃憥 to provide feedback.

@pkg-pr-new

pkg-pr-new Bot commented Sep 30, 2026 •

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@cloudflare/computer@171

commit: 6f7e54d

@aron-cf
aron-cf added this pull request to stack #178 September 30, 2026 21:17
@mattzcarey
mattzcarey force-pushed the feat/exec-tool-single-backend branch from f945040 to 4b6db8c Compare October 1, 2026 09:27
@mattzcarey mattzcarey changed the title computer: Drop the exec backend argument for one backend computer: Offer only exec arguments that can work Oct 1, 2026
The exec tool always offered a backend argument, even with one backend
configured, and always offered input, even when no backend accepted
it. With one backend the model saw an enum of one value and a
description written for choosing between backends. Callers also had
to describe each backend by hand, so the modules a JavaScript backend
installs had to be listed twice and kept in step.

With one backend the tool now has no backend argument and always runs
there, defaultBackend becomes optional, and the description talks
about what that backend does. input appears only when some backend
accepts it. A backend value sent anyway is removed by the schema.

Each backend's entry adds what the backend says about itself, read
through workspace.runtime.describe(id), after the caller's own
description, which becomes optional for a backend that describes
itself. The tool builds one input schema instead of a single-backend
and a multi-backend variant, and its output truncation moves to a
shared UTF-8 helper.
@mattzcarey
mattzcarey force-pushed the feat/exec-tool-single-backend branch from 4b6db8c to 6f7e54d Compare October 1, 2026 11:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

allow-pr Allow a PR to remain open.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants