> ## 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.

# Overview

> Build tool-using AI agents on a typed Chat class — model, system prompts, tools, and middleware in one place

The `@ooneex/ai` package lets you build **agents**: a model, a set of system prompts, the tools it can call, and the middleware that observes or shapes each run — all described by a small typed class. The base `Chat` class owns the agent loop (call the model, run the tools it asks for, feed the results back, repeat until done) and exposes two surfaces: [`run`](/ai/agents/running) for a single result and [`stream`](/ai/agents/running#streaming) for token-by-token events.

Under the hood, agents run on [TanStack AI](https://tanstack.com/ai) with the OpenRouter adapter, so any `provider/model` available on OpenRouter is a one-line change.

## Why this package

* **Declarative agents.** Subclass `Chat` and implement four getters — the base class wires them into the agent loop.
* **Container-managed.** Agents, tools, and middleware are registered with a decorator and resolved from the DI container, so dependencies inject cleanly.
* **Typed tools.** A tool's input schema is an [ArkType](https://arktype.io) assertion; arguments are validated before your handler runs.
* **Composable middleware.** Observe or transform every stage of a run — config, chunks, tool calls, usage, and the terminal outcome.
* **Structured output.** Pass an output schema and get a validated, typed object back instead of free text.
* **Batteries included.** Ready-made web, encyclopedia, biomedical, and Linear tools ship in the box.

## The building blocks

| Block                 | What it is                                                                           | Page                                              |
| --------------------- | ------------------------------------------------------------------------------------ | ------------------------------------------------- |
| **Agent**             | A typed `Chat` subclass describing the model, system prompts, tools, and middleware. | [Defining an Agent](/ai/agents/defining)          |
| **Running**           | `run` for one result, `stream` for live events, with per-request input.              | [Running an Agent](/ai/agents/running)            |
| **Tools**             | Function-calling classes the model invokes, with validated typed input.              | [Tools](/ai/agents/tools)                         |
| **Middleware**        | Lifecycle hooks that observe or transform a run.                                     | [Middleware](/ai/agents/middleware)               |
| **Structured Output** | A schema that turns the final answer into a typed object.                            | [Structured Output](/ai/agents/structured-output) |
| **Built-in Tools**    | Web, Wikipedia, PubMed, and Linear tools ready to drop in.                           | [Built-in Tools](/ai/agents/built-in-tools)       |

## Installation

```bash theme={null}
bun add @ooneex/ai
```

Models are reached through OpenRouter, so set your key in the environment:

```bash theme={null}
OPENROUTER_API_KEY=sk-or-...
```

## Quick example

Describe the agent as a class, register it with the `decorator.chat()` decorator, then resolve and run it from the container:

```typescript theme={null}
import { container } from "@ooneex/container";
import { Chat, decorator } from "@ooneex/ai";
import type { AiMiddlewareClassType, AiToolClassType } from "@ooneex/ai";

@decorator.chat()
class SupportChat extends Chat {
  public getModel = (): string => "anthropic/claude-sonnet-4.5";
  public getSystemPrompts = (): string[] => ["You are a concise support agent."];
  public getTools = (): AiToolClassType[] => [];
  public getMiddlewares = (): AiMiddlewareClassType[] => [];
}

const reply = await container.get(SupportChat).run<string>({ prompt: "Hi!" });
```

That is a complete agent. From here:

* Give it [tools](/ai/agents/tools) so it can search the web or act on your system.
* Add [middleware](/ai/agents/middleware) to audit, trace, or transform runs.
* Ask for [structured output](/ai/agents/structured-output) when you need a typed object.

<Note>
  The model identifier is an OpenRouter `provider/model` string — e.g. `anthropic/claude-sonnet-4.5`, `openai/gpt-5`, or `google/gemini-2.5-pro`. Switch providers by changing that one line.
</Note>
