Skip to main content
A tool is an AI SDK tool an agent may call. defineTool wraps one with Smithers runtime context: a deterministic idempotency key, side-effect metadata, and the side-effect snapshot hook. The five built-in tools (read, write, edit, grep, bash) are themselves defineTool results, run inside the task’s sandbox.

defineTool

Wrap a Zod-validated execute function into a durable AI SDK tool, passed to an agent’s tools or a <Task>’s tools prop.
string
required
Tool name surfaced to the agent and stamped onto ctx.toolName. Also the default description.
string
Human-readable description the agent sees. Defaults to name.
ZodType
required
Zod schema for the tool’s input, validated by the AI SDK before execute runs with the parsed args.
boolean
default:"false"
Marks the tool as mutating external state: opts it into Smithers side-effect tracking and runs the durability snapshot hook after execute.
boolean
default:"!sideEffect"
Whether re-running with the same input is safe; defaults to true when sideEffect is false. With sideEffect: true, idempotent: false, retries inject a warning that the tool was already called, so the agent can verify external state first.
(args, ctx) => Promise<unknown>
required
Runs the tool: args is the parsed input, ctx is the tool context. If sideEffect: true, idempotent: false and execute omits ctx, Smithers logs a startup warning, since ctx.idempotencyKey is needed to handle retries safely.
object
An AI SDK tool with attached Smithers metadata. Read the metadata with getDefinedToolMetadata.
The sideEffect / idempotent pair drives retry behavior: The rule: if you cannot undo it with git reset, mark it sideEffect: true. Source defineTool.js · context.js · Tests tools-unit.test.js, define-tool-durability.test.js · See also Built-in Tools, SDK agents

getDefinedToolMetadata

Read the Smithers metadata attached by defineTool. Returns null for plain AI SDK tools or non-objects.
unknown
required
A tool (or any value). Inspected for the Symbol.for("smithers.tool.metadata") property.
object | null
Source defineTool.js · Tests tools-unit.test.js · See also defineTool

Built-in tools

Five defineTool results, all sandboxed to ctx.rootDir (the workflow directory by default): paths resolve against the root, symlink escapes are rejected, and output truncates to ctx.maxOutputBytes (200KB). Import them individually or as the tools bundle:

read

Read a UTF-8 file from the sandbox.
string
required
File path, relative to rootDir or absolute within it.
Returns the file contents, throwing if it exceeds maxOutputBytes.

write

Write content to a file, creating parent directories as needed.
string
required
Destination path, relative to rootDir or absolute within it.
string
required
File contents.
Returns "ok". Throws TOOL_CONTENT_TOO_LARGE if content exceeds maxOutputBytes; only the content’s byte size and SHA-256 hash are logged, never the content itself.

edit

Apply a unified-diff patch to an existing file.
string
required
File to patch. Must already exist.
string
required
A unified diff. Applied against the current contents.
Returns "ok". Throws TOOL_PATCH_TOO_LARGE (patch over maxOutputBytes) or TOOL_PATCH_FAILED (the patch context does not match the file).

grep

Search for a pattern with ripgrep (rg -n). Requires rg on PATH.
string
required
Regex to search for.
string
default:"."
Directory or file to search, relative to rootDir.
Returns matching lines as file:line:text. No matches returns an empty string; an rg error (exit code 2) throws TOOL_GREP_FAILED.

bash

Run an executable with arguments. There is no shell parsing: pass arguments via args, and for pipes or redirects invoke a shell explicitly, e.g. { cmd: "sh", args: ["-lc", "..."] }.
string
required
Executable name or path. Up to 8,192 characters.
string[]
Arguments. Up to 128 entries, each up to 8,192 characters.
{ cwd?: string }
cwd sets the working directory (sandboxed under rootDir). Defaults to rootDir.
Returns combined stdout and stderr, truncated to maxOutputBytes. A non-zero exit code throws TOOL_COMMAND_FAILED; the process is killed with SIGKILL after ctx.timeoutMs (default 60s, hard cap one hour).
Network is blocked unless allowNetwork is enabled (RunOptions, --allow-network, or server config): Smithers then rejects commands whose executable basename is curl, wget, npm, bun, or pip, any argument that is itself a http:// or https:// URL (whole argument or --flag=<url> value), and git whose subcommand is push, pull, fetch, clone, or remote (throwing TOOL_NETWORK_DISABLED or TOOL_GIT_REMOTE_DISABLED). Only the invoked executable and real URL arguments are matched, so local commands such as git status or git commit -m "fetch upstream changes" are allowed. A shell -c payload (sh -c "curl https://x") is matched in command position, so it is blocked too.
This denylist is not isolation on Linux. True OS-level network isolation exists only on macOS, where a blocked bash runs under sandbox-exec with a network-deny profile (if available). Elsewhere, including Smithers’ CI, cloud, and production environments, allowNetwork:false cannot enforce a kernel sandbox and falls back to the denylist above: best-effort defense-in-depth, not a security boundary, trivially bypassed by a shell, an interpreter (python -c assembling a URL from parts, bash /dev/tcp), or a renamed binary. When isolation is unenforced, Smithers logs a TOOL_NETWORK_ISOLATION_UNENFORCED observability warning. Do not rely on allowNetwork:false to sandbox untrusted code; run it under a real <Sandbox> provider with egress controls instead.
Source tools/index.js · bash.js, read.js, write.js, edit.js, grep.js · Tests tools-unit.test.js · See also Built-in Tools, Common External Tools, SDK agents