The Narrated Gate
Agent Skills routinely include an instruction like this before a consequential write:
Show the user a review table and ask for confirmation before proceeding.
That instruction is unenforceable — not because agents ignore instructions, but because nothing in the system can tell the difference between the agent asking and the agent describing asking. Both produce text. The confirmation the skill author intended is a self-report, and self-reports are exactly the thing that fails.
The failure mode
Section titled “The failure mode”Picture a skill that logs a meeting to your CRM: resolve the account, build the records, show a review table, get a “yes”, then write. On a bad run, the agent goes straight from resolving the account to the write — twice — and then prints the review table:
| Field | Value |
|---|---|
| Subject | Acme Corp — Project Sync |
| Related To | Acme Corp — Platform Modernization (Opportunity) |
Every field correct. It may even close with “if you’d rather link this elsewhere, say so and I’ll re-point it” — offering a choice that has already been made and committed. That table is a receipt, not a gate: printed after the write, indistinguishable at a skim from the review the skill asked for. Detecting the difference means reading the raw transcript and correlating it against the tool-call log by hand.
This is not a hypothetical failure class. In Zapier’s AutomationBench, between 72% and 91% of failures across frontier models were the agent reporting success against a wrong world state. A skipped gate and an honored gate produce identical-looking output; the omission is invisible.
What a tool call changes
Section titled “What a tool call changes”Replace the prose instruction with a call to
elicit_confirm and three things become true
that no wording of the prose version can achieve:
-
It cannot be satisfied by narration. The agent can still neglect to call the tool — nothing prevents that — but it cannot manufacture a
"confirmed": true. The value comes from outside the model: a human pressed a button, or nobody did. This converts an invisible omission into an observable one, which is the entire gap. -
It is mechanically assertable. A tool call lands in the transcript, so an eval or CI check can assert, in code:
the
elicit_confirmcall precedes the first writeThat moves the gate out of the assertions that need a model grader (“did the agent show a review table and wait?”) and into the ones an exact check settles. A judgment call becomes a journal lookup.
-
It fails closed. In a headless or non-interactive run — the same environment where a prose gate is skipped silently —
elicit_confirmreturns promptly with{ "confirmed": null, "reason": "dismissed" }It does not hang, and it never returns
truewithout a human. A skill written to proceed only on"confirmed": truetherefore stops in exactly the situation where prose proceeded. If the skill is ever run unattended, that is the difference between a halted run and an unauthorized write.
Writing the gate
Section titled “Writing the gate”In the skill, replace the prose checkpoint with the call and a three-state rule:
Call
elicit_confirmwith a summary of the records about to be written. Proceed only ifconfirmedistrue. Treatfalseandnullas stop.
{ "message": "Create 2 Tasks on 'Acme Corp — Platform Modernization'?", "labels": { "ok": "Create records", "cancel": "Don't write" }}false is a human saying no; null means no answer was obtained. Neither is
permission. The full three-state contract is on the
elicit_confirm page.
For choosing among candidates (which account? which opportunity?), the same
argument applies to elicit_selection —
a native selector returning selectedIds beats rendering a markdown table
and hoping the reply parses.
What this does not solve
Section titled “What this does not solve”- Skipping the call is still possible. Elicitation makes the omission observable, not impossible. Pair the gate with the transcript assertion above in your evals, so a skipped gate fails the run instead of passing unnoticed.
- It does not verify the write landed. An elicitation gate runs before a write and answers “is this authorized?” — it says nothing about whether the write then succeeded. Post-action verification is a separate, complementary check.
- Host support varies. Run
elicit_doctorand consult the Support Matrix before depending on a mode — advertised is not the same as working. - Interactive confirm is bounded.
elicit_confirmwaits at most an hour. For scheduled or unattended runs where a human may be hours away, use the Pro Approval Flow —elicit_approval+elicit_awaithold the question open for up to 7 days, reach the reviewer on any device, and leave an audit trail.
Related
Section titled “Related”elicit_confirm— the gate, and its three-state resultelicit_selection— structured choice instead of parsed prose- Approval Flow — the durable gate for unattended runs
- Support Matrix — what hosts actually do when asked to elicit