Skip to main content

Overview

defineTool creates a function tool that agents can call during execution. It uses an object-based API for clear, typed configuration.

Type Definition

Parameters

string
required
Human-readable description of what the tool does. This is sent to the LLM to help it decide when to use the tool.Good:
Avoid:
z.ZodObject
Zod object schema defining the tool’s parameters. Omit for tools with no arguments.Use .describe() on each field to help the LLM understand what to pass.
(state, args?) => Promise<ToolResult>
required
Async function that executes when the tool is called.
  • First parameter: ThreadState (execution context)
  • Second parameter: Validated arguments (only if args is defined)
z.ZodObject
Zod object schema for thread environment variables the tool requires.
Tenvs are validated at runtime. Missing required tenvs cause an error.
'local' | 'provider'
Where this tool is executed:
  • 'local' (default): Execute locally by the execution engine
  • 'provider': Executed by the LLM provider, results come in response
string
Which provider executes this tool (when executionMode='provider'). e.g., 'openai', 'anthropic'

Execute Parameters

ThreadState (first parameter)

The execution context providing access to thread data and environment:
See ThreadState for full documentation. state.envType(name) defaults to secret. Use state.setEnv(name, value, { type: 'text' }) only when the value is safe to show in tool output and errors; use { type: 'secret' } for redacted values. Use state.arguments for thread invocation data and resumable subagent creation arguments. Use state.context only for mutable scratch data during the current execution. CodeExecutionOptions.execute selects the export to run and optional args, defaulting to { fn: 'default', args: [] }. CodeExecutionOptions.modules can provide local relative ES modules to sandboxed code, such as { './helpers.js': 'export const ok = true' }.

Args (second parameter)

Validated arguments matching your Zod schema:

Return Value

Tools must return a ToolResult object:
'success' | 'error'
required
Whether the tool executed successfully.
string
The result to return to the LLM. For complex data, use JSON.stringify().
string
Error message (when status is 'error').
string
Stack trace for debugging (when status is 'error').
Array<ToolAttachment | AttachmentRef>
File attachments to include with the tool result. Attachments are stored in the thread’s file system and linked to the message.

Examples

Basic Tool

Tool Without Arguments

Using ThreadState

With Thread Environment Variables

Error Handling

Using Utilities

Returning File Attachments

Attachments are automatically stored in the thread’s /attachments/ directory and linked to the tool result message. Large files (>1.75MB) are automatically chunked.

Provider-Executed Tool

Complex Schema

File Location

Tools are auto-discovered from agents/tools/:
Requirements:
  • Use snake_case for file names
  • Tool name is derived from file name
  • One tool per file
  • Default export required

Supported Zod Types

Tool argument schemas support the following Zod types: Primitives:
  • z.string()
  • z.number()
  • z.boolean()
  • z.null()
  • z.literal(value)
Enums:
  • z.enum(['a', 'b', 'c'])
Wrappers:
  • z.optional(...)
  • z.nullable(...)
  • z.default(...)
Collections:
  • z.array(...)
  • z.object({ ... })
  • z.record(z.string(), ...)
Unions:
  • z.union([...])
Nested schemas are supported up to 7 levels deep.

Best Practices

The description helps the LLM decide when to use the tool:Good:
Avoid:
Use .describe() on every field:
Return JSON strings for complex data:
Always catch and return meaningful errors:
When queueing tools from sub-prompts, use state.rootState: