// connections

Bring your own database

Point an agent at a Postgres you already run, or at your own Supabase account. You write the GRANTs, so the ceiling on what an agent can do is a thing you can read before you run it, and revoke in one statement afterwards.

01// postgres

You create the role, you grant the access

Any reachable Postgres works: Supabase, RDS, a self-hosted instance. We provision nothing and hold no admin credential. You run a copy-paste preset against your own database, then paste the resulting DSN. Whatever the GRANTs allow is exactly what an agent can do, and nothing enforces a narrower rule on top.

PresetRoleWhat it grants
readagntdata_roSELECT on every table in public, now and in future. Analytics and read-only assistants.
read_writeagntdata_rwSELECT, INSERT, UPDATE, DELETE in public. No schema changes.
fullagntdata_fullAdds CREATE, ALTER and DROP, via membership in the project's postgres role.
customagntdata_customYou pick the schemas, the tables and the operations. Nothing else is granted.

The snippet names the Supabase SQL editor because that is the common case; the statements are plain Postgres and run anywhere.

as the dashboard renders itsql
-- 1) Replace <PASSWORD> with a strong password before running.
--    e.g. openssl rand -base64 24
-- 2) Paste this into your Supabase project's SQL editor and run it.
-- 3) Then copy the Transaction-pooler connection string from
--    Project Settings → Database, swap the username/password, and
--    paste the resulting DSN into agntdata's 'Self-provision' tab.

do $$
begin
  if not exists (select 1 from pg_roles where rolname = 'agntdata_ro') then
    execute format('create role %I login password %L', 'agntdata_ro', '<PASSWORD>');
  else
    execute format('alter role %I with login password %L', 'agntdata_ro', '<PASSWORD>');
  end if;
end $$;
alter role "agntdata_ro" bypassrls;
grant usage on schema public to "agntdata_ro";
grant select on all tables in schema public to "agntdata_ro";
grant select on all sequences in schema public to "agntdata_ro";
alter default privileges in schema public grant select on tables to "agntdata_ro";
alter default privileges in schema public grant select on sequences to "agntdata_ro";

-- Bypass RLS so agent queries are not silently filtered. To enforce
-- RLS, change `bypassrls` above to `nobypassrls`.

-- Role created: agntdata_ro. Uninstall snippet is included in the dashboard.

rls

The presets create the role with bypassrls on, so policies written for browser sessions do not silently filter an agent's reads. Change it to nobypassrls in the snippet if you want RLS enforced against the role.
  1. 01

    Preview the SQL

    The dashboard renders the exact statements for the preset you picked, with the password left as <PASSWORD> for you to fill in. The Custom editor re-renders it as you change schemas, tables and operations, so you see the grants before you give them.

  2. 02

    Run it, then test the DSN

    Run the snippet yourself, build the DSN for the new role, and use the dashboard's test action before saving. It opens a real connection so a bad DSN fails then and there, not on the first agent call.

  3. 03

    Save

    The DSN is encrypted at rest. From then on the connection answers on the REST routes below and on the connection_postgres_* tools.

02// querying postgres

One statement per call

POST /v1/connections/postgres/query runs a single SQL statement. Multi-statement scripts have to come in as separate calls. Use $1, $2 placeholders and pass the values in params.

NameInTypeRequiredDescription
sqlbodystringrequiredA single SQL statement.
paramsbodyarrayoptionalBind values, matched positionally to $1, $2, …
row_capbodyintegeroptionalMaximum rows returned. Defaults to 1000, capped at 5000.
statement_timeout_msbodyintegeroptionalPer-statement timeout. Defaults to 30000, capped at 60000, floor 1000.
querybash
curl -s -X POST "https://api.superagnt.com/v1/connections/postgres/query" \
  -H "Authorization: Bearer $AGNTDATA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "sql": "select id, email from customers where created_at > $1 order by created_at desc",
    "params": ["2026-01-01"],
    "row_cap": 500
  }'

The result reports row_count and a truncated flag, so a caller can tell a short answer from a clipped one. Column types come back as raw Postgres OIDs in data_type_id.

Introspection

GET /v1/connections/postgres/schema returns the tables, columns, types and RLS status the role can see. Pass a comma-separated schemas query param to look beyond public. Prefer it over hand-rolled information_schema queries.

schemabash
curl -s "https://api.superagnt.com/v1/connections/postgres/schema?schemas=public,billing" \
  -H "Authorization: Bearer $AGNTDATA_API_KEY"
03// supabase

Connecting an account grants access to nothing

Supabase projects are deny-by-default. Connecting the account lets you allowlist projects; it does not expose any of them. You add projects one at a time in the dashboard.

  • A Management API call addressed at a project ref that is not on the allowlist returns a 403 naming the allowlist as the fix.
  • The project list endpoint is filtered server-side, so an agent enumerating projects sees only the allowlisted ones. There is nothing to leak by asking.
04// sql on supabase

Not through the Management API

hard-blocked

The Supabase Management API SQL endpoint returns a 403 here, always, regardless of the allowlist. It executes as the privileged postgres role, which makes every per-table grant you set meaningless. It is not a data plane an agent gets.

SQL goes through connection_supabase_query and connection_supabase_schema instead. Those connect over a scoped Postgres role provisioned per project from the per-table grants you pick in the dashboard, so a statement touching a table you did not grant fails at the database, not at a filter we wrote.

project_ref is optional on both tools. With one provisioned project it resolves on its own, and with several the error lists them, which is also how an agent discovers what it can reach.

05// auditing

Every query leaves a record

Each query and schema call writes an audit event carrying the actor, the surface it came from, the tool name and a truncated SQL preview. Bind values are deliberately not stored, because they routinely carry whatever the agent had in its prompt.

A usage row is written alongside it at zero cost. Your database is your database, so there is nothing to meter, but the call still shows up in usage so you can see the volume an agent is generating.

06// from an agent

Two families, one per vendor

The database tools sit in their own families, vendor-db:postgres and vendor-db:supabase, separate from the HTTP connection:supabase family. They are gated on the connection existing, so a workspace never sees a database tool it has no database for, and picking one does not drag in the other.

ToolDoes
connection_postgres_queryOne statement against the connected DSN.
connection_postgres_schemaIntrospect that database.
connection_supabase_queryOne statement against an allowlisted project, through its scoped role.
connection_supabase_schemaIntrospect that project. Only tables the role can reach are visible.