arcie.
++

Tools

defineTool — give your agent capabilities. Each file in tools/ is a callable tool.

Tools are what an agent can do. Each file in agent/tools/ default-exports a tool built with defineTool; the file name becomes the tool name. No registry, no wiring.

// agent/tools/get_weather.ts
import { defineTool } from "arcie/tools";
import { z } from "zod";
 
export default defineTool({
  description: "Get the current weather for a city.",
  inputSchema: z.object({ city: z.string() }),
  async execute({ city }) {
    return { city, condition: "Sunny", temperatureF: 72 };
  },
});

defineTool requires a description and an execute function — omitting either throws at definition time (Tool must have a description / Tool must have an execute function).

ToolConfig

interface ToolConfig<TInput = unknown, TOutput = unknown> {
  name?: string;                     // defaults to the file name
  description: string;               // required — shown to the model
  inputSchema?: z.ZodType<TInput>;   // validates + types the input
  outputSchema?: z.ZodType<TOutput>; // optional structured output
  sandbox?: boolean;                 // run in an isolated sandbox
  execute: (input: TInput) => TOutput | Promise<TOutput>;
}
FieldPurpose
descriptionHow the model decides when to call the tool. Write it for an LLM reader.
inputSchemaA Zod schema. execute's argument is typed and validated against it.
outputSchemaOptional schema describing the result — useful for structured tool output.
sandboxWhen true, marks the tool to run in an isolated execution sandbox.
executeThe implementation. Sync or async; receives the parsed input.

Typing

defineTool is generic, so inputSchema flows into execute's parameter type:

export default defineTool({
  description: "Add two numbers.",
  inputSchema: z.object({ a: z.number(), b: z.number() }),
  // input is { a: number; b: number }
  execute: ({ a, b }) => ({ sum: a + b }),
});

Keep one tool per file and name the file after the action (send_email.ts, search_docs.ts). That file name is the tool name the model calls.

defineTool is also re-exported from the package root, so import { defineTool } from "arcie" works too.