Common Patterns
List available tools with GET /api/tools to see both builtin and custom tools. Create custom tools with a clear description and input schema; agents use the description to decide when to call the tool. Assign tools to agents via the agent tools API (POST /api/agents/{id}/tools). Every route on this page requires the project’s service role key; an end user’s access token gets403. See Which key for which route.
GET /api/tools
List all tools (builtin: database_query, database_write, http_request, code_execute, storage_read, storage_write, web_search, web_scrape + custom).POST /api/tools
Create a custom tool. Required:name, description, type, input_schema. The route also accepts an optional config object. For HTTP-callable tools, the runtime reads config.endpoint, config.method (default POST), config.headers, and config.timeout_seconds when an agent invokes the tool.
string
required
Display name; agents see this when deciding to call the tool.
string
required
Free-text description; the LLM uses it to decide when to call the tool.
string
required
Free-form tag (≤50 chars). Stored verbatim; not used by runtime dispatch. Pick something descriptive (e.g.
http).object
required
JSON Schema for the tool’s arguments. Not validated at create-time; passed straight through.
object
Tool-specific config. For custom HTTP tools, set
{ endpoint, method?, headers?, timeout_seconds? } here; that’s where the runtime reads them.Top-level
endpoint_url / method / headers are silently dropped at create-time; only name, description, type, input_schema, and config are persisted. type is stored as a free-form String(50); the runtime does NOT switch on it. Agent-tool dispatch uses the assignment’s own tool_type (builtin vs custom), not the Tool’s type field.GET /api/tools/
Get a tool definition by ID.string
required
Tool ID
PUT /api/tools/
Update a custom tool.string
required
Tool ID
DELETE /api/tools/
Delete a custom tool.string
required
Tool ID
Data tool access and limits
The builtin data tools,database_query, database_write, storage_read and storage_write, act as whoever started the run, never with the API service’s own database privileges. A run started with an end user’s access token is held to that user’s grants, RLS policies and Storage policies; a run started with the service role key uses the agent’s own database login and the service role key for Storage. The side-by-side table is in What agent data tools act as. The limits below apply to both kinds of run.
Database tools
-
Configured tables are the whole reach. The table list in the tool assignment’s
config_override.schemas(set withPATCH /api/agents/{id}/tools/{assignment_id}; see Tool assignments) is everything the tool can read or write. An agent with no table list reaches nothing. -
Only tables and
security_invokerviews. You may configure plain tables, partitioned tables, and views createdWITH (security_invoker = true). Naming a view withoutsecurity_invoker, a materialized view, or a foreign table answers400when you assign or update the tool, and the check runs again at run time. A table that doesn’t exist yet may be configured. -
database_queryis parsed, not trusted. It accepts oneSELECTthat writes and locks nothing and references only the configured tables. It may call only a fixed allowlist of built-in functions, matched as Postgres resolves them (a quoted"Sum"is notsum), use only allowlisted operators, and cast only to built-in types. Functions that change or read settings or run a SQL string, your own functions, operators written in SQL or PL/pgSQL in your schemas, and casts to domains are rejected. An operator an installed extension defines is accepted when its symbol is on the list (pgvector’s distances<->,<=>,<#>and<+>, and symbols such as&&,@>or->) and the extension lives in one of the agent’s configured schemas; an extension installed in a schema the agent isn’t configured with, such as the defaultextensionsschema, isn’t visible to its queries. Functions that extensions add are rejected. The allowlists are fixed and can’t be configured. A rejected query returns an error to the agent naming what was refused: -
Timeouts. Every tool transaction has a 30-second statement timeout and a 5-second lock timeout, whatever timeout the
authenticatedrole has elsewhere. -
Logins. End-user runs use one shared login,
powabase_agent_user, which can only becomeauthenticatedand carries the user’s JWT claims. Each agent that has a database tool gets its own login,powabase_agent_<agent id without dashes>, which is a member of no other role; an agent without database tools gets none. None of these logins is a superuser, and deleting an agent drops its login. - Expired tokens. Tool calls on an end user’s run are refused once that user’s token has expired.
CHECK when a value is written, or the equality operator of a column’s type when a query groups or joins on it. Configure agents only with tables whose column types you trust.
Storage tools
- On an end user’s run, the tools call Storage with the user’s own token, so your Storage policies for that user apply. On a service-role run they use the service role key.
- Bucket names must match
^[A-Za-z0-9_-]+$, which is stricter than Storage itself: a bucket whose name contains a.or a space can’t be used from a tool. - Each
/-separated part of a path must be a name: not empty,.or.., and without%,\,?,#or control characters. - The internal
sourcesbucket, which holds the original files of ingested sources, is never reachable from a tool. - Errors come back to the agent as short messages: not found, access denied, or failed with a status.
Error Responses
Tool routes return{"error": "<message>"}.