roowDocsSign in

Documentation

Agents, tools, and who decides

roow stands between an agent and your database. The agent gets one MCP endpoint and a handful of tools; every call it makes is classified, checked against the connection’s policy, bounded, and recorded as a run — refusals included. Nothing an agent sends can widen what it may do.

Connect an agent

  1. 1An owner or admin connects a database to the workspace and says what agents may read, and where they may write.
  2. 2In your AI tool, add roow as a connector with the endpoint https://api.roow.work/mcp.
  3. 3Your tool opens roow: sign in, choose the databases it may use, and for each whether it may only read. That’s it — no token to copy. Disconnect it any time from the connection’s page.
Claude Code
claude mcp add --transport http roow https://api.roow.work/mcp

For a tool that can’t sign in — a script, or a client without OAuth — make a token on the connection’s page instead. It starts gcx_, is shown once, and is stored only as a hash; send it as a bearer header.

With a token
claude mcp add --transport http roow https://api.roow.work/mcp \
  --header "Authorization: Bearer gcx_…"
Any MCP client that takes a JSON config
{
  "mcpServers": {
    "roow": {
      "type": "http",
      "url": "https://api.roow.work/mcp",
      "headers": {
        "Authorization": "Bearer gcx_…"
      }
    }
  }
}

A token reaches one database; a sign-in can reach several. With more than one, every tool takes a database argument (its name), and list_databases names them with what each may do. Each database keeps its own rules, read-only or not, and its own record of runs. The tools offered are the ones the chosen databases support, and a tool a database doesn’t take says so.

Tools

What each tool does, and which systems offer it. An owner or admin can switch any of them off for a connection under its Tools tab — that changes what the agent is offered, not what it is allowed: that is the policy’s answer, given per call. Tools marked off by default stay off until someone switches them on.

Look

Before asking for anything: what is there, and would this be allowed.

describe_schemaList the schemas, tables and columns, so an agent stops guessing names.
check_querySay what a statement would read and write, and whether it would be allowed.check_query(sql)

Read

Bounded by the connection's schemas and row limit, decided by its policy.

queryRun one read-only SQL statement.query(sql)
query_documentsRun one aggregation pipeline against one collection.query_documents(collection, pipeline)
exportRun one read-only query and keep the result as a CSV or JSON file in the workspace, under the same policy and row limit as `query`.export(sql, format, name)

Change

Refused until an owner or admin names where agents may write.

writeInsert, update or delete rows where this connection permits. A statement that would change more rows than the limit is rolled back.write(sql)
materializeCreate one table from a query, into a destination this connection permits.materialize(sql)

Files

The workspace's files this connection may see.

list_filesList the workspace files this connection may see: its exports, and uploads.
read_fileRead a text file from the workspace, a page at a time.read_file(file_id, offset)
upload_fileoff by defaultSave text the agent wrote — CSV, JSON, markdown — as a file in the workspace, seen by whoever may use this connection. Off until someone switches it on.upload_file(name, content)

Jobs

Start the jobs people made on this connection. Never make or change one.

list_jobsList the jobs on this connection: what each runs, when, and how it last went.
run_jobRun one of this connection's jobs now, as the job, and say how it went. A write the job asks about first waits for a person, as it always does.run_job(job_id)
job_statusLook up how a run of one of this connection's jobs went, and the file it kept.job_status(execution_id)

Follow up

How an agent learns a held run was answered.

run_statusLook up a run by id — how an agent learns a held run was approved.run_status(run_id)

Supabase Auth

Offered once Auth insights is switched on for a Supabase connection.

auth_usersLook up the project's Supabase Auth users: when they signed up and last signed in, by which provider, confirmed or not. Email and phone only if the connection allows.auth_users(since, provider, user_id, email_contains, limit)
auth_statsSignups and sign-ins per day, and users by provider, over the last N days.auth_stats(days)
auth_actionAsk for a change to a Supabase Auth user — ban, unban, sign out, confirm email or delete — from the actions this connection allows. Usually held for a person to approve.auth_action(action, user_id, hours)

Access

People and roles

RoleMay
OwnerEverything an admin may, and remove other admins. Made the workspace.
AdminConnect databases, set their bounds and policy, switch tools, invite people, choose where approvals are asked, and answer held runs.
MemberUse the connections they are given, make their own tokens, read runs, and make jobs — whose writes always ask first.

Owners and admins invite people by email or GitHub username. An email invitation is accepted by signing in with GitHub using an account that has that address verified, within 14 days; one to a username, by signing in as that account. Holding the invitation email is never enough on its own.

Connections

A connection belongs to the workspace, not to whoever pasted the credential, which is sealed and never shown to an agent. With no grants, every member may use it; once someone is granted it, only those people (and owners and admins) may. Each connection has its own bounds and its own policy — staging and production can differ completely.

BoundWhat it does
SchemasWhat may be read at all.
Denied tablesNever read or written, whatever a rule says.
Write destinationsWhere writes may land. None: the connection is read-only.
Row limitThe most rows a read returns.
Rows a write may changeA write that would change more is rolled back.
TimeoutHow long one statement may run.

Policy

Rules on each connection say what is allowed, refused, or allowed only after a person says yes — by operation, table, environment and actor. Every call is decided by them and recorded with the rule that decided it. Start from the presets on a connection’s Policy tab, and preview a statement against your rules before saving them.

Tokens

  • One person, one connection. Shown once, kept hashed.
  • An admin can narrow a token — fewer schemas, a lower row limit, read-only — but never widen it past its connection.
  • Removing someone from the workspace revokes their tokens; deleting a connection revokes all of its tokens. Its runs keep saying what they ran against.

Approvals

When a rule says to ask first, the run is held and the agent is told to wait; it can check with run_status. An owner or admin answers on the Approvals page, where they can count the rows it would change or preview them — run and rolled back, so nothing is changed.

A workspace can also be asked in Slack. The message shows what the run would do, with Approve, Decline and Preview rows on it, for people who linked their Slack account.

Runs

Every governed operation is a run, kept whether it ran or was refused: what was asked, by whom, what the policy decided and why, what it read and wrote, and how long it took. A run belongs to what started it — an agent’s tool call, or a job — and keeps naming its connection after the connection is deleted.

StatusMeans
AcceptedIt ran, within its bounds, and the result was checked.
Policy rejectedA rule or a bound refused it. Nothing reached the database.
Awaiting confirmationA rule asked for a person first. It waits on Approvals.
Confirmation declinedSomeone said no. Nothing changed.
Execution failedThe database refused or errored. A write that changed too many rows is rolled back.
Verification conflict, rejectedIt ran, and the result was not what was promised.
  • Runs lists the workspace’s runs newest first. Narrow it by what started them (agents, jobs, or one job), by status, by system, or by connection.
  • Each run opens to the full record: the statement, the rule that decided it, what it touched — or, if refused, what it asked to touch — and who answered it, where.
  • Agents read their own runs with run_status, scoped to their connection: a run id from elsewhere finds nothing.

Jobs

A job is one statement kept to run on demand or on a schedule: an export, kept as a CSV or JSON file, or a write. It runs as itself — service:job:<name>, so a rule can name it — on behalf of the person who made it, whose access is checked every time it runs. If they lose the connection or leave, the job fails and says why rather than running on.

Making one

  • On Jobs, choose the connection, export or change rows, and the statement. It is checked against the policy when you save, so a statement that would be refused is refused then.
  • A job’s writes ask a person first. Only an owner or admin can switch that off, and the policy still decides either way.
  • Run it when you press Run now, or on a schedule: five-field cron, read in the timezone you pick. A server that was down runs a missed job once, not once per missed time, and a job never runs twice at once — a write waiting on a person holds the next run back.
  • Choose when the channel hears how a run went: only when it fails (the default), every run, or never.

Dates by name

Filled in each run, in the schedule’s timezone (UTC for a job without one), as quoted values: {{today}}, {{yesterday}}, {{tomorrow}}, {{week_start}}, {{month_start}}, {{year_start}}, {{now}}, each with an offset like {{today-7}}. The run records the filled-in statement, so it says which day was read.

Yesterday's sign-ups, every morning
SELECT * FROM analytics.signups
WHERE created_at >= {{yesterday}} AND created_at < {{today}}

Starting one from outside

Make a trigger token on the job’s page. It can only start that job and read its runs; making a new one replaces it.

Start it, then ask how it went
curl -X POST https://api.roow.work/api/v1/jobs/trigger \
  -H "Authorization: Bearer gjt_…"
# → {"execution_id": "exe_…", "status": "running"}

curl https://api.roow.work/api/v1/jobs/trigger/exe_… \
  -H "Authorization: Bearer gjt_…"

Agents and jobs

An agent can list its connection’s jobs, run one, and ask how a run went — with list_jobs, run_job and job_status. It cannot make or change a job, so it cannot schedule its own unattended writes, and a read-only token cannot start a job that changes rows.

Files

KindComes fromWho sees it
ExportAn agent's export, or an export jobPeople and tokens that may use its connection.
PreviewPreview rows on a held writePeople and tokens that may use its connection.
AgentAn agent's upload_file, when switched onPeople and tokens that may use its connection.
UploadA person, on FilesEveryone in the workspace.
  • Kept encrypted, up to 25 MB. Upload by choosing a file or dropping it anywhere on Files.
  • Open one to see it: CSV and export-shaped JSON as a table, other JSON formatted, markdown rendered, other text as text. Large files show their start; download for the rest.
  • Agents read files with list_files and read_file, a page at a time.
  • If the workspace shares files, new ones go to its Slack channel too.
  • Whoever added a file, or an owner or admin, can delete it. Deleting a connection takes its exports and previews with it.