File system·续2
List the waiting calls with workspace.runtime.pending(), and answer one with respond():
for (const call of await this.workspace.runtime.pending()) {
await this.workspace.runtime.respond(call.id, call.callId, {
approved: true,
});
}
for (const call of await this.workspace.runtime.pending()) {
await this.workspace.runtime.respond(call.id, call.callId, {
approved: true,
});
}
Once none of its calls are waiting, the run replays to the call, and the function runs again with the same callId. This time, ctx.interrupt() returns the answer straight away. To notify someone when a call starts waiting, pass an onWait function to the backend. It receives the same fields as pending(), at most once per wait. killExec() ends a waiting run.
- A call can interrupt once. A second
ctx.interrupt()in the same call throws. - Only a run with
onInterrupt: "replay"can wait. In any other run,ctx.interrupt()throws. respond()throws anENOTWAITINGerror for a call that is not waiting, such as one already answered.
Current limitations
These limitations apply to the experimental release and may change in future releases.
- A replay must take the same path as the first attempt. A run fails if it calls or prints something different. Keys from
crypto.subtle.generateKey(),node:cryptorandomness,node:timers, andcloudflare:socketsare not replayed. - A replayable run buffers
fetchresponses instead of streaming them, and each body must fit in 1 MiB by default. Requests go through the Durable Object, so they are slower than in other runs. A request in flight at the restart is sent again. - A host module function runs again once its answer arrives, so any work before
ctx.interrupt()must be safe to repeat. Every answer replays the run from the beginning. - A run gets three attempts, counted again each time it journals a call. It must finish within its original timeout, counted from when it first started.
- A run resumes only on the same runtime. A new compatibility date or flags, new size limits on the backend, or a package upgrade that changes how runs replay fails the runs it interrupted.
- Interrupted runs restart four at a time, because a Durable Object can run up to ten Dynamic Workers at once.
- Until a run finishes, its journal uses Durable Object storage of roughly the size of every response, plus the code of the run.
Limits
- Each workspace shares the storage of its Durable Object. For storage limits, refer to Durable Objects limits. Size workspaces for an agent's working files, not for full monorepos or large dependency trees.
- The JavaScript backend runs ECMAScript modules, not shell commands or native binaries. When an agent needs a Linux environment, use a sandbox.
- Each JavaScript run is bounded in CPU time, wall-clock time, output size, and the number and size of file operations. Completed runs are kept for 60 minutes by default.
Security considerations
The model reads everything that the file tools and exec return. A file can contain text written to steer the model, such as an instruction to delete other files. Check tool results before the agent acts on them outside the workspace, and require approval for tools with side effects.
Code that the JavaScript backend runs cannot read the environment variables, bindings, or storage of the agent. It reaches only the files under root, the modules you configure, and the network when you pass a globalOutbound. Host modules run with the full access of the agent, so expose only the functions that model-written code needs.
Every user who talks to the same agent instance shares its workspace. Give each user their own agent instance when their files must stay apart.
API reference
Workspace
new Workspace(options) from @cloudflare/computer creates a workspace. It accepts the following options:
| Option | Description |
|---|---|
storage |
Required. The storage of the Durable Object, this.ctx.storage. |
backends |
Execution backends, such as WorkerJavaScriptBackend. The first backend is the default. |
mounts |
Read-only content mounted at a path, from an R2 bucket (R2Bucket()) or the Worker bundle (WorkerBundle()). |
git |
A Git client from createGitClient() in @cloudflare/computer/git, which turns on workspace.git. |
defaultGitIdentity |
The { name, email } that Git commits use. |
artifacts |
An Artifacts binding, as { binding }. |
output |
Where long command output is saved, and how much result() keeps. |
workspace.fs
Every path is absolute. Every method returns a promise.
| Method | Description |
|---|---|
readFile(path, encoding?) |
Reads a file. Returns a string with "utf8", or a ReadableStream without an encoding. Accepts { byteOffset, byteLength } to read part of a file. |
writeFile(path, content, options?) |
Writes a string, Uint8Array, or ReadableStream. Set options.mode for permissions. |
mkdir(path, options?) |
Creates a directory. Set recursive: true to create parents. |
readdir(path) |
Lists a directory as entries with name, parentPath, isFile, and isDirectory. |
stat(path) |
Returns name, mode, mtime, size, isFile, and isDirectory, following symbolic links. |
lstat(path) |
Like stat, but reports a symbolic link itself, with isSymbolicLink. |
rm(path, options?) |
Removes a file or directory. Set recursive: true for a non-empty directory, and force: true to ignore a missing path. |
rename(oldPath, newPath) |
Moves a file, directory, or symbolic link in one transaction. |
symlink(target, path) |
Creates a symbolic link at path that points to target. |
readlink(path) |
Returns the target of a symbolic link. |
chmod(path, mode) |
Changes the permission bits of a path. |
find(directory, pattern?, options?) |
Finds paths that match a glob, relative to directory. Accepts exclude, limit, and offset. |
ls(prefix) |
Lists every file at or under prefix. |
grep(pattern, path, options?) |
Searches file contents. Accepts regex, ignoreCase, context, include, exclude, limit, and offset. |
Failed operations reject with an error whose code is a POSIX error code, such as ENOENT for a missing path.
workspace.runtime
| Method | Description |
|---|---|
exec(source, options?) |
Runs source on a backend and returns a handle. Call result() on the handle for the final result. |
getExec(id, options?) |
Reattaches to a run by ID. |
killExec(id, options?) |
Stops a run. |
disposeExec(id, options?) |
Discards a completed run. |
backends() |
Lists the backends and the description that each gives to the model. |
recover() |
Resumes interrupted runs. Call it from an alarm. Experimental. |
pending() |
Lists the host module calls that are waiting for an answer. Experimental. |
respond(id, callId, answer, options?) |
Answers a waiting call. Experimental. |
exec() accepts the following options:
| Option | Description |
|---|---|
backend |
The backend ID to run on. Defaults to the first backend. |
input |
JSON-compatible data passed to the default export of a JavaScript module. |
encoding |
Set to "utf8" to receive stdout and stderr as strings instead of bytes. |
cwd |
The working directory, and the base for relative imports. |
env |
Environment variables for this run, available to JavaScript as process.env. |
stdin |
Standard input, as a string or Uint8Array. |
timeoutMs |
How long the run can take, up to the backend's maxTimeoutMs. |
onInterrupt |
What happens to this run if a restart interrupts it. Overrides the backend's default. |
The result contains status ("completed", "failed", or "cancelled"), exitCode, stdout, stderr, and value, the return value of a JavaScript module. When output is too long, truncated names the workspace file that holds all of it.
Declare handles from exec() with using so they are disposed when they go out of scope.
Tool functions
| Function | Entry point | Returns |
|---|---|---|
createAITools() |
@cloudflare/computer/tools/ai-sdk |
An AI SDK ToolSet. |
createPiTools() |
@cloudflare/computer/tools/pi-ai |
Pi AI tool declarations and an execute function. |
createTanStackTools() |
@cloudflare/computer/tools/tanstack-ai |
A list of TanStack AI ↗︎ tools. |
Host modules
Pass these to the modules option of WorkerJavaScriptBackend:
| Function | Entry point | Module | Description |
|---|---|---|---|
createGitModule() |
@cloudflare/computer/modules/git |
ws:git |
Git operations on the workspace. Requires the git workspace option. Pass { allowNetwork: true } to clone, fetch, and push. |
createArtifactsModule() |
@cloudflare/computer/modules/artifacts |
ws:artifacts |
Artifacts repositories. Requires the artifacts workspace option. |
createToolBindings() |
@cloudflare/computer/modules/tools |
ws:tools |
The agent's own tools, callable from code. Build the bindings with forAISDKTools() or forPiTools(). |
For the full interfaces, refer to the Computer design documentation ↗︎.
Related resources
Cloudflare Computer
Source code, examples, and design documentation for @cloudflare/computer.
Sandbox
Give an agent a Linux sandbox to run shell commands, scripts, and tests.
Think tools
Built-in workspace tools, custom tools, and approvals for Think agents.
Dynamic Workers
Load and run Workers on demand from another Worker.
Was this helpful?
YesNo
On this page
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/agents/tools/filesystem/#page","headline":"File system","description":"Give an agent a virtual file system stored in its Durable Object, with file tools for the model and an optional JavaScript runtime.","url":"https://developers.cloudflare.com/agents/tools/filesystem/","inLanguage":"en","image":"https://developers.cloudflare.com/agents/tools/filesystem/og.png?v=d015b763134c08dd","dateModified":"2026-10-23","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
description: Connect agents to external Model Context Protocol servers and use their tools in model calls. title: MCP image: https://developers.cloudflare.com/agents/tools/mcp/og.png?v=45c87f178d28710a
Documentation Index
Fetch the complete documentation index at: https://developers.cloudflare.com/agents/llms.txt
Use this file to discover all available pages before exploring further.
Docs