---
title: Tools
description: Define typed actions the agent can call, and gate sensitive ones on human approval.
---

# 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](../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<string, unknown>`.
* 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](../sandbox) handle.
* `ctx.getSkill(id)`: read a packaged [skill](../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](../skills): on-demand procedures the model loads when relevant
* [Default harness](../concepts/default-harness): the built-in tools and how to override or disable them
* [Dynamic capabilities](../guides/dynamic-capabilities): tools whose set is resolved per session with `defineDynamic`
* [Auth & route protection](../guides/auth-and-route-protection): authenticate a tool to an external service


---

For a semantic overview of all documentation, see [/sitemap.md](/sitemap.md)

For an index of all available documentation, see [/llms.txt](/llms.txt)

For agent-facing discovery, including API and MCP surfaces, see [/agents.md](/agents.md)