--- title: "Tools" description: "Define typed actions the agent can call, and gate sensitive ones on human approval." url: /tools --- A tool is a typed action the agent can call, such as hitting an API, running a query, or writing a file. The action stays in code you control. Tools run in your app runtime with full access to `process.env`, not in the [sandbox](/docs/sandbox). ## Define a tool The filename is the tool name the model sees. A file at `agent/tools/get_weather.ts` is exposed as `get_weather`. ```ts title="agent/tools/get_weather.ts" import { defineTool } from "eve/tools"; import { z } from "zod"; export default defineTool({ description: "Get the current weather for a city.", inputSchema: z.object({ city: z.string().min(1) }), async execute({ city }, ctx) { return { city, condition: "Sunny", temperatureF: 72 }; }, }); ``` A tool definition needs: - a filename slug under `agent/tools/`, the model-facing name. - a `description`: what the tool does, written for the model. - an `inputSchema`: a Zod schema (or any Standard Schema, or a plain JSON Schema object). Required. For no input, pass `z.object({})`. Zod and Standard Schema infer the `input` type in `execute`. Plain JSON Schema types it as `Record`. - an `execute(input, ctx)`: the implementation. May be sync or async. When a tool returns structured data, add an optional `outputSchema`. With Zod or Standard Schema it also types the `execute` return. ### The `ctx` parameter `execute` gets a `ctx` carrying the runtime accessors: - `ctx.session`: session metadata, turn, auth, parent lineage. - `ctx.getSandbox()`: the live [sandbox](/docs/sandbox) handle. - `ctx.getSkill(id)`: read a packaged [skill](/docs/skills)'s metadata and files. Running in the app runtime is what lets a tool import shared code from `lib/`, read `process.env`, and take part in eve’s durable pause/resume model. eve never runs authored tools during discovery. The model sees descriptors first, and only what it actually calls gets executed. Completed steps never re-run; eve replays the recorded result. A step interrupted mid-execution re-runs, so make non-idempotent side effects like charges or emails idempotent, or gate them with approval. ## Gate a tool on human approval A tool can require a person to sign off before it runs. Set `needsApproval` with the helpers from `eve/tools/approval`: ```ts title="agent/tools/refund_charge.ts" import { defineTool } from "eve/tools"; import { always } from "eve/tools/approval"; import { z } from "zod"; export default defineTool({ description: "Refund a charge.", inputSchema: z.object({ chargeId: z.string(), amount: z.number() }), needsApproval: always(), // or once() / never() / a predicate async execute(input) { return refund(input); }, }); ``` Approval is one half of eve's [human-in-the-loop](./human-in-the-loop) model — the page covers the `always/once/never` helpers, input-dependent predicates, and how a gated call pauses and resumes durably. ## Shape what the model sees with `toModelOutput` By default the model sees the full `execute` return. When a tool returns rich data a channel needs for rendering but the model only needs the gist, project it down with `toModelOutput`: ```ts toModelOutput(output) { return { type: "text", value: `Report for ${output.domain}: score ${output.score}.` }; }, ``` `toModelOutput` receives the full, typed `execute` return and only affects the model. Channel event handlers and hooks still get the full output on `action.result`, so a channel can render rich platform output (Slack Block Kit, say) the model never sees. Return `{ type: "text", value }` for a summary, or `{ type: "json", value }` for a smaller object. Do not return secrets, credentials, unnecessary personal data, or unbounded sensitive content from tools. Filter, minimize, and redact tool outputs before returning them. ## What to read next - [Human-in-the-loop](./human-in-the-loop): gate a tool on approval, or have the agent ask a question - [Skills](/docs/skills): on-demand procedures the model loads when relevant - [Default harness](/docs/concepts/default-harness): the built-in tools and how to override or disable them - [Dynamic capabilities](/docs/guides/dynamic-capabilities): tools whose set is resolved per session with `defineDynamic` - [Auth & route protection](/docs/guides/auth-and-route-protection): authenticate a tool to an external service