tool

Define an app tool.

Input and output types are inferred from the schemas.

Import from @threads/core (TypeScript) or threads (Python).

function tool(options: {
  name: Name;
  description: string;
  input: z.ZodType<Input>;
  output?: z.ZodType<Output>;
  runs?: "host" | "sandbox";
  execute?: (input: Input, ctx: RunContext<Deps>) => Promise<Output>;
  effect?: EffectClass;
  dedupWindowMs?: PosInt;
  reconcile?: { lookup: (effectKey: string, ctx: RunContext<Deps>) => Promise<LookupResult<Output>>; finality: "final" | "nonfinal" };
  endsTurn?: boolean;
}): Tool<Input, Output, Deps>

Parameters

nameNamerequired

The name the model calls the tool by: lowercase letters, digits and underscores, starting with a letter, at most 64 characters. It must be unique within the agent.

descriptionstringrequired

What the tool does, shown to the model in its tool list. Write it for the model: when to call the tool and what it returns.

inputz.ZodType<Input>required

Tool arguments are parsed with it at the boundary; its JSON Schema is the pinned input_schema.

outputz.ZodType<Output>

TypeScript only. Pinned output_schema. A result that fails it is an error result; the effect still happened. Omitted: the result isn't checked; a string is shown as is and any other value as canonical JSON.

runs"host" | "sandbox"default host

Where execute runs. host (the default) runs it in the host process. sandbox is reserved and not supported in this release: a sandbox tool fails setup with ConfigError capability_missing (Python at tool(), TypeScript at agent check() or the first run) and never executes. Not pinned: host and an omitted runs give the same ToolSpec and config_hash. Only "host" is supported today; "sandbox" is a setup error.

execute(input: Input, ctx: RunContext<Deps>) => Promise<Output>

The tool body for runs host, the only kind built today. Its return value is the result; a thrown error becomes an error tool_result the model sees. Omitting it is a setup error capability_missing.

execute(input)Inputrequired

The model's arguments, already parsed by the tool's input schema: the parsed Zod value in TypeScript, an instance of the input model in Python.

execute(ctx)RunContext<Deps>required

The run this call belongs to: deps, thread_id, branch_id, principal, call_id and effect_key (send effect_key to providers that dedup). In TypeScript it also carries an abort signal.

effectEffectClassdefault unguarded

Undeclared tools are unguarded: uncertainty always parks.

dedupWindowMs / dedup_window_msPosInt

Milliseconds within which the provider dedups a repeated request that carries the same effect key. Required exactly when effect is idempotent; omit it for any other effect, where giving it is a setup error invalid_config.

reconcile{ lookup: (effectKey: string, ctx: RunContext<Deps>) => Promise<LookupResult<Output>>; finality: "final" | "nonfinal" }

Required exactly when effect is reconcilable; omit it for any other effect. finality is the tool's declared LookupCapability: the runtime accepts a not_found answer as final only when it is final; under nonfinal a not_found is treated as not_found_nonfinal and the call parks.

reconcile.lookup(effectKey: string, ctx: RunContext<Deps>) => Promise<LookupResult<Output>>required

Asks the provider whether the call with this effect key took effect, after a crash or lost response. Returns a LookupResult: found with the value, not_found, or unknown.

reconcile.lookup(effectKey) / reconcile.lookup(effect_key)stringrequired

The effect key of the call being checked, <branch_id>:<call_id>: the same key execute saw as ctx.effect_key.

reconcile.lookup(ctx)RunContext<Deps>required

The run the call belongs to: deps, thread_id, branch_id, principal and effect_key.

reconcile.finality"final" | "nonfinal"required

Whether a not_found from lookup is trustworthy. final: not_found means the effect never happened. nonfinal: not_found may just not be visible yet, so the call parks for a person to settle.

endsTurn / ends_turnbooleandefault false

true: a successful result from this tool ends the turn with no further model call; an error result doesn't. Default false.

Returns

Tool<Input, Output, Deps>

Edit on GitHub

On this page