feature_flags is doing its job; the same agent running a migration against orders at 2am is a conversation you want to have first. Until now the only answers were allow and refuse, so the choice was between granting a write you’d rather see and denying one the agent legitimately needs.
Ask is the third answer (0.16.0+). A write the policy already permits is held, a human decides, and the agent picks the result back up — no credential handed over, no policy loosened.
Reach for it when:
- An agent needs writes you don’t want unsupervised. Grant
read_writeonorders, then hold row changes so a person sees each one before it lands. - Schema changes need a second pair of eyes, but row writes don’t. Hold schema changes only; ordinary
UPDATEs keep running. - You’re loosening a policy and want a safety period. Turn a table writable and hold its writes for a week to see what the agent actually does.
The three write classes
Every write falls into one of three classes, and each carries its own independent rule (0.17.0+):
Each class takes exactly one of refuse, ask, or allow — values of a single rule, not gates stacked on each other, so the two can’t be configured to contradict one another.
Two consequences worth knowing before you configure this:
- Approvals sit under the policy, never over it. The hold runs only after the policy returns ALLOW, so a statement
table_accessor a guardrail already refused never reaches a reviewer — and no approval can buy a way past one. - A statement in more than one class is held if any of its classes is held.
WITH d AS (DELETE FROM audit_log) UPDATE orders SET … WHERE id = 1is both a whole-table write and a row change; running it because only one of the two was set to ask would be the worst available answer.
What happens to a held write
1
The agent's query is held
The engine files an approval request and holds the connection briefly. If a human answers within that window, the write runs inside the agent’s original tool call — the agent never sees a hold at all.
2
A slow decision becomes a ticket
Rather than block past an MCP client’s timeout, the engine hands the agent an
approval_id, a deadline, and a review URL. Nothing has run, and nothing has been denied.3
The agent polls
check_approval reports pending / approved / executed / consumed / denied / expired. Polling is cheap and never consumes the grant.4
The agent re-runs to collect
Once approved, the agent calls
query again with the identical sql and intent. That call is what executes the write.(database, sql, intent, token) and is single-use. An approval for DELETE FROM orders WHERE id < 100 cannot authorize … < 100000 — one character’s difference is a different request, needing its own approval. Two retries racing one approval yield exactly one execution.
An outage is never a refusal
If the approval service can’t be reached, the agent getsapproval_unavailable — explicitly retryable, and not a denial. Nothing is audited and no deny webhook fires, so an outage never leaves a refusal nobody made in your compliance record. Real decisions are audited like any other denial, as approval_denied or approval_expired. See denial reasons.
Reviewing a request
Held writes land in Approvals in the dashboard — a cross-project queue, alongside the audit log it mirrors. Anyone on the team can read the queue; approving and denying is owner and admin only. A request nobody answers expires after 30 minutes, and the agent is told to ask again.- A denial’s note reaches the agent. Say why you refused, and it can write a better statement instead of retrying the same one.
- Notifications are link-only. A held
DELETE’sWHEREclause routinely carries live values, so the statement is customer data — it renders in the dashboard, never in an email.
Turn it on
- Cloud (dashboard)
- Self-host (YAML)
In the project’s Database pane, set any row under What a write may do to Ask, then Save. The change hot-reloads the running engine — no restart, and no agent session dropped.
Related
Table access & guardrails
Which tables an agent may reach, and the writes refused outright.
`check_approval`
The tool an agent polls, and what each status tells it to do.
Policy schema
The
approvals and guardrails keys, with every default.Denial reasons
How a denied, expired, or held write reaches the agent and the audit log.