AbsoluteJS

AI Tools

Give AI models the ability to call functions in your application. Define tools with a description, JSON schema and a handler function. The plugin manages multi-turn tool execution automatically.

#Defining Tools

A tool has three parts: a description the model reads to decide when to use it, a JSON Schema describing the expected input, and a handler function that executes the tool and returns a string result.

TS
import type { AIToolMap } from '@absolutejs/absolute';

export const tools: AIToolMap = {
  search_products: {
    description: 'Search the product catalog by query, category, or price.',
    input: {
      type: 'object',
      properties: {
        query: {
          type: 'string',
          description: 'Search text to match against product names',
        },
        category: {
          type: 'string',
          description: 'Filter by category',
        },
        max_price: {
          type: 'number',
          description: 'Maximum price in dollars',
        },
      },
    },
    handler: (input) => {
      // Query your database, call an API, etc.
      const results = db
        .prepare('SELECT * FROM products WHERE name LIKE ?')
        .all(`%${input.query}%`);

      return JSON.stringify(results);
    },
  },

  get_weather: {
    description: 'Get current weather for a city.',
    input: {
      type: 'object',
      properties: {
        city: { type: 'string', description: 'City name' },
      },
      required: ['city'],
    },
    handler: async (input) => {
      const res = await fetch(`https://api.weather.com/${input.city}`);
      const data = await res.json();
      return JSON.stringify(data);
    },
  },
};

#Tool Types

TS
type AIToolDefinition = {
  description: string;
  input: Record<string, unknown>; // JSON Schema object
  handler: (input: unknown) => Promise<string> | string;
};

type AIToolMap = Record<string, AIToolDefinition>;

#Using Tools

Pass your tool map to the aiChat plugin. The plugin sends tool definitions to the model and executes handlers when the model calls them.

TS
import { aiChat } from '@absolutejs/ai';
import { anthropic } from '@absolutejs/ai/anthropic';
import { tools } from './tools';

new Elysia().use(
  aiChat({
    provider: () => anthropic({ apiKey: process.env.ANTHROPIC_API_KEY }),
    tools,
    systemPrompt: 'You have access to a product database. Use the tools to help users find products.',
    maxTurns: 5, // Stop after 5 tool-use rounds
  })
);

#Dynamic Tools

Not all models support tool calling. Pass a function instead of a static map to provide tools only when the model supports them.

TS
// Provide different tools based on provider or model
const getTools = (providerName: string, model: string) => {
  // Only give tools to models that support them
  const TOOL_CAPABLE = new Set([
    'claude-sonnet-4-6',
    'claude-opus-4-6',
    'gpt-4o',
    'gemini-3-pro',
  ]);

  return TOOL_CAPABLE.has(model) ? tools : undefined;
};

new Elysia().use(
  aiChat({
    provider: getProvider,
    tools: getTools,
  })
);

#Execution Flow

When a model decides to call a tool, the plugin handles the full execution loop:

1
Model returns a tool call with a name and input
2
Plugin sends tool_status: 'running' to the client
3
Handler executes and returns a string result
4
Plugin sends tool_status: 'complete' with the result
5
Tool result is fed back to the model for the next turn
6
Model calls more tools or generates a final text response

The maxTurns option (default: 10) prevents infinite loops. The plugin also detects repeated identical tool calls and stops early.