Skip to content

think, agents: work in a @cloudflare/computer Workspace - #2560

Open
mattzcarey wants to merge 1 commit into
deprecate-shell/1-pi-computer-0.5from
deprecate-shell/2-think-computer-workspace
Open

mattzcarey wants to merge 1 commit into
deprecate-shell/1-pi-computer-0.5from
deprecate-shell/2-think-computer-workspace

Conversation

@mattzcarey

@mattzcarey mattzcarey commented Oct 12, 2026 •

Copy link
Copy Markdown
Member

Think's workspace is now a Workspace from @cloudflare/computer. By default Think creates one on the agent's own storage, with no execution backends. Agent Skills take the same shape, and a new lazyWorkspace() covers a Workspace another Durable Object owns.

We want one way to give an agent a workspace:

  • Think's internals now go through one adapter over workspace.fs: media eviction, skills projection, fetch spill and the extension host functions. The writeFileBytes checks are gone, so media eviction and skills projection work with every workspace.
  • Think writes its own files under /workspace, Computer's working root.
  • @cloudflare/computer is a new peer dependency of Think. Workspace and WorkspaceLike are no longer exported, and createExecuteTool(this) no longer builds state.* from the workspace.
  • Agent Skills (agents) accept only the Computer shape, for both projection and skills.runner().
  • lazyWorkspace(resolve) turns an async resolver into a Workspace. It resolves on first use and keeps the client, and a failed resolution is retried on the next operation. agent-think disposes its client after each turn and assigns a fresh lazyWorkspace for the next one.
  • The assistant's file browser lists /workspace, and refreshes after each turn instead of on every write, because Computer has no change events. The examples that depend on Think add @cloudflare/computer.
  • docs/think/index.md gets an "Upgrading to a Computer workspace" section, which the changesets link to.

Tests ran: think workers suite, agents skills and skill runner, and the assistant example. Repo typecheck is clean.

Stacked on #2559.


Stack (merge in order, or merge the top to land them all together):

  1. examples(pi): move to @cloudflare/computer 0.5 #2559 examples(pi): move to @cloudflare/computer 0.5
  2. think, agents: work in a @cloudflare/computer Workspace #2560 (this PR) think, agents: work in a @cloudflare/computer Workspace
  3. think: use the @cloudflare/computer workspace tools #2561 think: use the @cloudflare/computer workspace tools
  4. think: drop @cloudflare/shell #2562 think: drop @cloudflare/shell
  5. examples, docs: move off @cloudflare/shell #2563 examples, docs: move off @cloudflare/shell
  6. shell: deprecate in favour of @cloudflare/computer #2564 shell: deprecate in favour of @cloudflare/computer
  7. think: deprecate createExecuteTool in favour of the Workspace exec tool #2565 think: deprecate createExecuteTool in favour of the Workspace exec tool

@changeset-bot

changeset-bot Bot commented Oct 12, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 0b4608a

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

This PR includes changesets to release 3 packages
Name Type
agents Minor
@cloudflare/think Minor
@cloudflare/agent-think Patch

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

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Note

Newer findings are available below. Devin Review posted a newer report on this PR, in addition to the findings presented here.

Devin Review found 7 potential issues.

Devin Review

Comment thread docs/think/index.md
Comment thread agent-think/src/agent.ts Outdated
bytes,
mediaType ?? "application/octet-stream"
);
await files.write(path, bytes);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔴 Evicted images lose their MIME type

When files.write stores an image outside the sniffed formats, its MIME type is discarded. The read tool then labels it unsupported binary, so the model cannot retrieve the evicted image.

Learn more

Media eviction replaces an old image part with a marker pointing to a workspace file. Previously the write carried mediaType, so detectWorkspaceMediaType could identify formats without a magic-byte detector. The new write only supplies bytes. Its detector recognizes PNG, JPEG, GIF, WebP, SVG, and PDF; other legitimate media types become application/octet-stream and createReadTool refuses to return them to the model.

Example: An aged image/avif file part is evicted. Its marker points to a saved AVIF file, but reading that file returns {kind: 'binary', unsupported: true} instead of an image.

Recommended fix: Preserve the original media type alongside the bytes or recover it when reading evicted media. Test a valid image type without an existing signature detector.

Devin Review


Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Not changing this. The next PR in the stack replaces Think's read tool with Computer's, which attaches PNG, JPEG, GIF, WebP and PDF, the formats model providers accept. The evicted file keeps its extension (.avif), so nothing is lost. Formats outside that list weren't reliably attachable before either.

Comment thread examples/assistant/agents/assistant/agents/my-assistant/agent.ts
Comment thread packages/think/src/workspace-files.ts Outdated
Comment thread .changeset/think-computer-workspace.md Outdated
Comment thread .changeset/skills-computer-workspace.md Outdated
@agent-think

agent-think Bot commented Oct 12, 2026 •

Copy link
Copy Markdown
Contributor

✅ agents import sizes: no significant changes (ea393e5f → 37ffb599, workflow run)

@mattzcarey
mattzcarey added this pull request to stack #2566 October 12, 2026 11:52
@pkg-pr-new

pkg-pr-new Bot commented Oct 12, 2026 •

Copy link
Copy Markdown

Open in StackBlitz

agents

npm i https://pkg.pr.new/agents@2560

@cloudflare/ai-chat

npm i https://pkg.pr.new/@cloudflare/ai-chat@2560

@cloudflare/codemode

npm i https://pkg.pr.new/@cloudflare/codemode@2560

hono-agents

npm i https://pkg.pr.new/hono-agents@2560

@cloudflare/shell

npm i https://pkg.pr.new/@cloudflare/shell@2560

@cloudflare/think

npm i https://pkg.pr.new/@cloudflare/think@2560

@cloudflare/voice

npm i https://pkg.pr.new/@cloudflare/voice@2560

@cloudflare/worker-bundler

npm i https://pkg.pr.new/@cloudflare/worker-bundler@2560

commit: 37ffb59

@mattzcarey
mattzcarey force-pushed the deprecate-shell/2-think-computer-workspace branch from f6b669d to 6d5042d Compare October 12, 2026 12:32
devin-ai-integration[bot]

This comment was marked as resolved.

@mattzcarey
mattzcarey force-pushed the deprecate-shell/2-think-computer-workspace branch from 6d5042d to 767f8ec Compare October 12, 2026 14:09
@mattzcarey
mattzcarey force-pushed the deprecate-shell/2-think-computer-workspace branch from 767f8ec to 37ffb59 Compare October 12, 2026 14:11
@mattzcarey
mattzcarey force-pushed the deprecate-shell/2-think-computer-workspace branch from 37ffb59 to 0b4608a Compare October 12, 2026 16:16

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Devin Review found 1 new potential issue.

Devin Review

Comment on lines +180 to +189
return Promise.all(
matches.map(async (match) =>
match.type === "dir"
? { path: match.path, type: "directory", size: 0 }
: {
path: match.path,
type: "file",
size: (await fs.stat(match.path)).size
}
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Concurrent deletion aborts skill glob

When a matching file disappears after fs.find, ctx.workspace.glob rejects instead of returning surviving matches. Promise.all propagates the missing file's fs.stat error to the entire skill script.

Learn more

The skill runner exposes ctx.workspace.glob to scripts through SkillScriptHostBridge. A shared workspace can change after fs.find lists its paths. If a matched file is removed before the new metadata lookup, fs.stat rejects with ENOENT and Promise.all discards every result. WorkspaceFiles.glob handles the same race by filtering missing entries after stat.

Example: fs.find returns /workspace/notes/a.md and /workspace/notes/b.md. Another client deletes b.md before its stat. The skill receives an error instead of the surviving a.md entry.

Recommended fix: Resolve each match through access.stat(match.path) and filter out null results. Preserve the existing result shape and let non-ENOENT errors propagate.

Devin Review


Was this helpful? React with 👍 or 👎 to provide feedback.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant