Custom SQL tools#

A SQL tool is a stored, parameterized query that an agent can invoke by name. Use it to give an agent access to your own tables and business logic, without writing any Rust or exposing a native AIDB function:

SELECT aidb.create_sql_tool(
    name             => orders_by_customer,
    description      => Look up recent orders for a customer by id.,
    sql_statement    => SELECT id, status, total FROM orders WHERE customer_id = ${customer_id} ORDER BY created_at DESC LIMIT ${limit},
    params           => aidb.tool_params(
        aidb.tool_param(customer_id, INT, The customers id.),
        aidb.tool_param(limit, INT, Maximum number of orders to return.)
    ),
    read_only        => true,  -- optional; enforced, not just descriptive (see below). Default: true
    return_type_hint => NULL   -- optional; documents the returned row shape, same aidb.tool_params() shape as `params`. Default: NULL
);

Parameter

Type

Default

Description

name

TEXT

Required

Unique name for the tool.

description

TEXT

Required

Shown to the model as part of the tool's definition.

sql_statement

TEXT

Required

The query to run, with ${name} placeholders for each declared parameter.

params

JSONB

Required

The tool's parameters, built with aidb.tool_params().

read_only

BOOLEAN

true

If true, reject the statement at registration time unless it's provably read-only.

return_type_hint

JSONB

NULL

Documents the query's return shape, in the same aidb.tool_params() shape. Not currently surfaced to the model.

aidb.tool_param(name, type, description) builds one parameter; aidb.tool_params(...) combines several; aidb.tool_params() with no arguments declares a tool that takes no parameters.

Register the tool on an agent the same way as any other:

SELECT aidb.create_agent(sales_helper, Answer questions about customer orders., my_gpt,
    tools => ARRAY[orders_by_customer]);

Naming#

A tool’s name must be unique across every tool type — it can’t collide with a built-in Native tools or a tool already imported from an MCP tools . aidb.create_sql_tool() rejects the call up front if it does.

Parameter placeholders#

Reference each declared parameter in sql_statement as ${name} — AIDB substitutes each with the value the model supplied for that call, bound as a real query parameter (not string-interpolated). A parameter used more than once in the statement only needs to be declared once. params is required; pass aidb.tool_params() with no arguments for a tool that takes no parameters.

Read-only tools#

read_only defaults to true . Pass read_only => false for a tool that needs to write — and that’s enforced, not just descriptive, in both directions: left at the default true , registration fails immediately if sql_statement matches a recognized write pattern (INSERT , UPDATE , DELETE , and so on), rather than letting a mislabeled tool through. A tool left at the default read_only => true is also usable by an agent running in Read-only mode ; a tool explicitly marked read_only => false is excluded from a read-only run, the same as an unclassified native or MCP tool.

sql_statement must be a single statement, and can’t be a utility statement like EXPLAIN or COPY . Trailing whitespace and a trailing ; are stripped automatically when you register it.

!!!note create_sql_tool also accepts a return_type_hint argument, in the same aidb.tool_params() shape as params , describing the shape of the rows the query returns. It’s stored alongside the tool but isn’t currently surfaced to the model or to aidb.tools . For now, its only use is as documentation for anyone inspecting aidb.sql_tool_registry directly.

Removing a tool#

SELECT aidb.delete_tool(orders_by_customer);

aidb.delete_tool() also removes an MCP tools if the name you pass belongs to one instead of a SQL tool, but built-in native tools can’t be deleted.