> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ooneex.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Tools

> Give an agent function-calling tools with validated, typed input and optional call hooks

A tool is a function the model can call during a run. You describe it as a class implementing `ITool`: a name, a description, an optional input schema, and a handler. The agent loop exposes the tool to the model, validates the arguments the model supplies against your schema, runs your handler, and feeds the result back into the conversation.

## Defining a tool

Implement `ITool<P, R>`, where `P` is the validated input and `R` is the handler's return type. Register the class with `decorator.tool()`:

```typescript theme={null}
import { inject } from "@ooneex/container";
import { Assert, type AssertType } from "@ooneex/validation";
import { decorator } from "@ooneex/ai";
import type { ITool } from "@ooneex/ai";

type WeatherInput = { city: string; units?: "metric" | "imperial" };

@decorator.tool()
class WeatherTool implements ITool<WeatherInput, Promise<string>> {
  public constructor(@inject(WeatherClient) private readonly client: WeatherClient) {}

  public getName = (): string => "get_weather";

  public getDescription = (): string =>
    "Get the current weather for a city. Returns a short human-readable summary.";

  public getInputSchema = (): AssertType =>
    Assert({
      city: "string > 0",
      "units?": "'metric' | 'imperial'",
    });

  public handler = async (param: WeatherInput): Promise<string> => {
    const report = await this.client.current(param.city, param.units ?? "metric");
    return `${report.summary}, ${report.temperature}°`;
  };
}
```

Add it to any agent's `getTools`, or pass it per request:

```typescript theme={null}
public getTools = (): AiToolClassType[] => [WeatherTool];

// or, for a single call:
await chat.run<string>({ prompt: "Weather in Paris?", tools: [WeatherTool] });
```

## The `ITool` contract

| Member           | Required | Purpose                                                                      |
| ---------------- | -------- | ---------------------------------------------------------------------------- |
| `getName`        | ✅        | Unique tool name the model uses to call it.                                  |
| `getDescription` | ✅        | Plain-language description of when and how to use it — the model reads this. |
| `handler`        | ✅        | Runs the tool. Receives the validated input, returns the result.             |
| `getInputSchema` | —        | ArkType assertion validating the model's arguments before `handler` runs.    |
| `onBeforeCall`   | —        | Hook that runs before the tool is invoked; can short-circuit the call.       |
| `onAfterCall`    | —        | Hook that runs after the tool returns.                                       |

<Note>
  A clear `getDescription` and a precise `getInputSchema` are what make a tool reliable — the model decides whether and how to call the tool entirely from those two. Describe the input fields in the schema and the tool's purpose in the description.
</Note>

## Validated input

When `getInputSchema` is present, the agent loop validates the model's arguments against it before your handler runs. Inside `handler`, the input already matches the schema — no manual checks needed. The schema is an [ArkType](https://arktype.io) assertion built with `Assert` from `@ooneex/validation`:

```typescript theme={null}
public getInputSchema = (): AssertType =>
  Assert({
    query: "string > 0",
    "limit?": "number > 0",
    "tags?": "string[]",
  });
```

Omit `getInputSchema` for a tool that takes no arguments.

## Call hooks

A tool can observe or gate its own invocation with two optional hooks. When any tool on a run declares either hook, the agent loop bridges them onto the run automatically.

### `onBeforeCall`

Runs before the handler. Return a decision to allow, modify, or block the call — useful for permission checks or argument rewriting:

```typescript theme={null}
public onBeforeCall = (ctx, hookCtx) => {
  if (!ctx.context?.currentUser) {
    return { action: "deny", reason: "Authentication required" };
  }
  return { action: "allow" };
};
```

### `onAfterCall`

Runs after the handler returns — for logging, metrics, or auditing:

```typescript theme={null}
public onAfterCall = async (ctx, info) => {
  await ctx.context.audit.write({ tool: this.getName(), result: info.result });
};
```

Both hooks receive the run's `ChatMiddlewareContext` as their first argument, so they can read `ctx.context` — the [runtime context](/ai/agents/running#metadata-vs-context) passed to the call.

## Built-in tools

The package ships ready-made tools for web search, Wikipedia, PubMed, and Linear. See [Built-in Tools](/ai/agents/built-in-tools) for the full catalog and the keys they need.
