Skip to main content
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 for a single result and stream for token-by-token events. Under the hood, agents run on TanStack 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 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

BlockWhat it isPage
AgentA typed Chat subclass describing the model, system prompts, tools, and middleware.Defining an Agent
Runningrun for one result, stream for live events, with per-request input.Running an Agent
ToolsFunction-calling classes the model invokes, with validated typed input.Tools
MiddlewareLifecycle hooks that observe or transform a run.Middleware
Structured OutputA schema that turns the final answer into a typed object.Structured Output
Built-in ToolsWeb, Wikipedia, PubMed, and Linear tools ready to drop in.Built-in Tools

Installation

bun add @ooneex/ai
Models are reached through OpenRouter, so set your key in the environment:
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:
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 so it can search the web or act on your system.
  • Add middleware to audit, trace, or transform runs.
  • Ask for structured output when you need a typed object.
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.