AI agents

Your agent doesn't need your database. It needs an answer.

AccessFlow gives an AI agent a governed shape of database access: it can ask, and the query goes through the same parse, AI risk analysis, human approval, and audit trail as one a person submitted. Point an agent at a database over MCP without that and it inherits whatever the connection string can do — every table, every row, every DELETE.

What a direct database connection actually hands over

The usual way to give an agent data access is a database MCP server holding a connection string. That server is not a permission boundary — it is a pipe. Whatever the credential can do, the agent can do, and three properties follow from that:

  • The blast radius is the credential, not the task. An agent asked to summarise last week's signups holds the same access as one asked to drop a table. Scope lives in the prompt, which is not a security control.
  • Prompt injection becomes database access. Untrusted text in a support ticket or a web page the agent reads can redirect what it decides to run. The pipe faithfully executes the redirected intent.
  • The audit trail loses the human. The database sees one service account. Which person's agent ran what, and why, is not recoverable from the logs afterwards.
This is the emerging consensus, not a novel claim. Vendor guidance through 2026 converges on the same conclusion — MCP servers reaching production data need a governance layer in front of them. Most of the available answers are proprietary. AccessFlow is an open-source one.

The agent joins the queue, like everyone else

AccessFlow exposes a Model Context Protocol server. An agent connects with an API key and sees twelve tools; a service account's key can be limited to the subset an admin allow-lists. Submitting a query does not execute it — it enters the same state machine a query from the web editor enters.

01

Discover, then draft

The agent calls get_datasource_schema to see what exists, and validate_sql to parse-check a draft. Validation never executes and never calls the AI — the agent can iterate for free.

02

Submit for review

submit_query returns PENDING_AI. Nothing has touched the database yet. Permission and parse failures come back as structured errors, not executions.

03

AI risk analysis

The query is scored 0–100, checked for missing indexes and anti-patterns, and given a pre-flight cost estimate — the same analysis a human submission gets.

04

Human approval

The datasource's review plan decides who signs off. Reviewers see the agent's SQL, its risk score, and its justification, and approve or reject from the web UI, Slack, or a mobile push.

05

Execute, under the same guards

On approval the proxy runs it with the schema allow-list, column masking, row-level security, and row caps applied — then get_query_result returns the rows to the agent.

The property that matters. Agents cannot bypass AI analysis, multi-stage approvals, or column-level restrictions. There is no agent fast-path, because the tools call the same services the web UI calls — the guards live in the service layer, below both.

What holds, specifically

Governance claims are worth only as much as their enforcement point. All but the last are enforced in the service layer, not in the tool wrapper; the tool allow-list is the one check that runs in the wrapper itself, ahead of the service:

Keys carry their owner's access, nothing more

An API key carries exactly the role and datasource permissions of the identity it belongs to — a person for a personal key, or the service account an admin set up for the agent. A reviewer's key can review; an analyst's key cannot. An agent never gets more access than the identity its key belongs to.

Masking survives sampling

get_column_samples runs the governed read path — row-level security predicates and column masks apply, so a masked column returns the masked value to the agent, never the raw one.

Audit is caller-scoped

get_audit_log forces the actor to the calling user and their organisation. An agent cannot read another user's activity — not even with an admin key.

No self-approval

review_query blocks approving your own submission at the service layer, and list_pending_reviews excludes the caller's own queries. An agent cannot approve what it submitted.

Every action is attributed

MCP submissions and decisions write the same audit rows as the web UI, recording the user id, the API key used and the action — the tool layer does not capture the caller's IP or user-agent. There is no separate agent audit path.

Keys are hashed and revocable

The plaintext key is shown exactly once; only a SHA-256 hash is stored, so neither admins nor the system can recover it. Revocation takes effect on the next request.

Scoped to the tools it needs

An admin can restrict a service account to an explicit tool allow-list — a checkbox list on the account's MCP tools tab under Service accounts. Every tool is still listed to every caller, but a call outside the list returns a structured permission_denied before the service runs — the list can only narrow what the account's role already permits, never widen it.

Bounded by a per-identity rate limit

An agent in a runaway loop is capped, not just logged. Every call an API key makes counts against the identity behind it — 120 requests a minute by default, with an optional daily ceiling, and a per-account override an admin can set on the account's Limits tab. Over the cap the server answers HTTP 429 with a Retry-After header so a well-behaved client backs off; a person signed in through the browser is never limited.

Acting for a named person

An agent can say whom it is working for by adding an X-AccessFlow-On-Behalf-Of header naming that person, once they have consented (through their own delegation endpoint, or an admin on the account's On-behalf-of principals tab). Naming someone changes nothing about what the agent may do — its permissions stay its own. The person is recorded on the submission and on every audit entry written while that call is handled, inside the tamper-evident chain, and can no longer approve that submission themselves, or sign off the review of an emergency run made for them. A name the agent may not use, or the header on a review action, gets HTTP 403 from the same filter that rate-limits, before anything runs — never a quiet ignore.

Connecting an agent

Give the agent a key, then point the client at your AccessFlow instance. For an agent that runs on its own — a chat bot, a scheduled assistant, a shared team agent — ask an admin for a service account with a narrow role and only the tools it needs, and use a key issued on its API keys tab. For trying an agent on your own machine, a personal key from Profile → API keys works too, with exactly your own permissions. The server speaks stateless Streamable HTTP at /mcp.

claude_desktop_config.json
{
  "mcpServers": {
    "accessflow": {
      "type": "http",
      "url": "https://accessflow.example.com/mcp",
      "headers": {
        "X-API-Key": "af_kQ7…"
      }
    }
  }
}
Claude Code
claude mcp add accessflow --transport http \
  --url https://accessflow.example.com/mcp \
  --header "X-API-Key: af_kQ7…"

Any MCP-compatible client works the same way — Claude Desktop, Claude Code, or a custom pipeline. Full tool reference and error codes are in the MCP documentation →

What this does not solve

A governance layer that claims to solve everything is not one worth trusting. The boundaries are worth stating plainly:

  • It does not stop an agent submitting a bad query. A compromised or confused agent can still submit anything its key permits. What it cannot do is get that query executed without passing the review plan. The control is on execution, not on intent.
  • Auto-approval is a policy you choose. Routing policies can auto-approve low-risk reads, and a review plan can be configured not to require human approval. Those are deliberate settings — if you grant an agent a path that skips review, it skips review. The default is that it does not.
  • It governs AccessFlow, not your agent. This is a control on one path — the database. An agent with other tools, other credentials, or a shell is outside its scope entirely.

Run it yourself

AccessFlow is Apache 2.0 and self-hosted — it runs inside your own infrastructure, and no query text or row data leaves it. One docker compose up gets a working instance; the install guide covers Helm and from-source too.