Documentation menu

Documentation

Code Mode

drive_code runs an async JavaScript function that the agent writes. The function calls the drive directly, so work over hundreds of files takes one tool call instead of hundreds.

When to use it

Use Code Mode when the next step depends on what the agent finds: filtering files by content, renaming by a rule, rewriting JSON, collecting a report. The function's intermediate results stay in the sandbox, and only its return value and logs come back to the conversation.

For one read or one edit, the direct tools are simpler. For commands an agent already knows, such as grep -r or cp -r, the shell is shorter. A program can also call the shell with sh().

Example

async () => {
  // Rename every report to include its date, then summarize what changed.
  const files = await find("/r2-media/reports", { name: "*.md" });
  const renamed = [];
  for (const file of files) {
    const text = await cat(file.path);
    const date = text.match(/^date: (\d{4}-\d{2}-\d{2})/m)?.[1];
    if (!date || file.name.startsWith(date)) continue;
    await mv(file.path, `/r2-media/reports/${date}-${file.name}`);
    renamed.push(file.name);
  }
  console.log(`checked ${files.length} files`);
  return { renamed };
}

The agent sends the function as the code argument of drive_code. The result is the returned value as JSON, the console.log lines, the number of drive calls and the run time.

API

This is the interface the function receives, exactly as the tool describes it to the agent. Every method is also a global function, so cat(path) and drive.read(path) are the same call.

type Entry = { name: string; path: string; type: "file" | "directory"; size?: number; modified?: string; etag?: string };
type Stat = { type: "file" | "directory"; path: string; size?: number; modified?: string; etag?: string; contentType?: string };
type Tree = { target?: string; objects: number; bytes: number; skipped: number; failed: { path: string; message: string }[]; job?: string };
declare const drive: {
  ls(path?: string, options?: { recursive?: boolean; limit?: number }): Promise<Entry[]>;
  stat(path: string): Promise<Stat>;
  exists(path: string): Promise<boolean>;
  read(path: string, options?: { offset?: number; length?: number }): Promise<string>; // UTF-8 text; offset/length in bytes
  readJson(path: string): Promise<any>;
  readBytes(path: string, options?: { offset?: number; length?: number }): Promise<Uint8Array>;
  write(path: string, data: string | Uint8Array | object, options?: { ifMatch?: string; createOnly?: boolean; contentType?: string }): Promise<{ path: string; etag: string; size: number }>; // objects are saved as JSON
  append(path: string, text: string): Promise<{ path: string; etag: string; size: number }>;
  edit(path: string, oldText: string, newText: string, options?: { replaceAll?: boolean; ifMatch?: string }): Promise<{ path: string; etag: string; replacements: number }>;
  mkdir(path: string): Promise<{ path: string; created: boolean }>;
  rm(path: string, options?: { recursive?: boolean }): Promise<Tree>;
  cp(src: string, dst: string, options?: { recursive?: boolean; overwrite?: boolean }): Promise<Tree>; // like cp: into dst when dst is a folder or ends with "/"
  mv(src: string, dst: string, options?: { overwrite?: boolean }): Promise<Tree>;
  find(path: string, filters?: { name?: string; iname?: string; type?: "file" | "directory"; minSize?: number; maxSize?: number; modifiedAfter?: string; modifiedBefore?: string; limit?: number }): Promise<Entry[]>;
  grep(pattern: string, path: string, options?: { ignoreCase?: boolean; fixed?: boolean; include?: string; maxMatches?: number }): Promise<{ path: string; line: number; text: string }[]>;
  du(path: string): Promise<{ bytes: number; files: number; truncated: boolean }>;
  url(path: string, options?: { expiresIn?: number; inline?: boolean }): Promise<{ url: string; expiresAt: string }>; // download link
  uploadUrl(path: string, options?: { expiresIn?: number }): Promise<{ url: string; method: "PUT"; headers: Record<string, string>; expiresAt: string }>;
  sh(command: string, options?: { cwd?: string }): Promise<{ stdout: string; stderr: string; exitCode: number }>; // the same bash as drive_sh
  mounts(): Promise<{ path: string; provider: string; access: string; label?: string }[]>;
};
// Every drive method is also a global: ls, stat, exists, read (alias cat), readJson, readBytes, write, append, edit, mkdir, rm, cp, mv, find, grep, du, url, uploadUrl, sh, mounts.

Methods run with the connection's access. A refused call throws an error whose message starts with its code, such as PERMISSION_DENIED:, so the function can catch it and continue.

Sandbox and limits

  • Each run starts a fresh isolate with no network, no bindings and no credentials. fetch fails. The only capability is the drive API above.
  • A run lasts up to 45 seconds and makes up to 1,000 drive calls. The time limit ends before the 60-second request timeout that many MCP clients apply.
  • The return value can be up to 64,000 characters of JSON.
  • A copy, move or delete that needs longer than the run has left continues as a background job, and the method returns its job ID.
  • Code Mode can be turned off per drive in its settings. Each account can start 1,000 runs per day.