Operating system set to macOS
Documentation jurisdiction set to United States
Sign inConnect Claude

Confirmation Contract

A Write Stops for a Human

Archie does the work, but he never posts an irreversible entry on his own. When a write crosses a risk threshold he pauses and hands you a structured prompt. Every framework (REST, MCP, LangGraph, the agent SDKs) gets human-in-the-loop for free.

When a Confirmation Fires

Confirmation fires when a tool would take an action above a risk threshold. The current triggers are:

  • Journal entries above the auto-approval monetary limit for the key.
  • Any write tool on a key carrying the write:confirm scope.
  • Bulk modifications, and irreversibly, bulk deletions.

Read-only tools never trigger confirmation. Test keys use lower thresholds, so you can exercise the flow without posting real data.

The Confirmation Object

When a tool defers, Archie creates a confirmation record and returns its confirmation_id. Fetch the full record at any time with GET /api/v1/confirmations/{confirmation_id}.

confirmation recordjson
{
  "confirmation_id": "conf_01ABC...",
  "status": "pending",
  "action_type": "journal_entry",
  "action_name": "Post journal entry",
  "action_description": "Dr Plant & Equipment USD 12,500 / Cr Bank USD 12,500 (Q1 forklift)",
  "affected_count": 1,
  "risk_level": "medium",
  "reversible": true,
  "created_at": "2026-04-29T10:00:00Z",
  "expires_at": "2026-04-29T10:05:00Z",
  "prompt_markdown": "**Approve journal entry?**\n\nDr Plant & Equipment  $12,500  \n  Cr Bank             $12,500  \n\nMemo: Q1 forklift"
}

Render prompt_markdown directly to the user. It is the canonical, human-readable description of what will happen. Surface action_name and risk_level alongside it if your UI needs structure.

Approve or Deny

decisionbash
# Approve, which executes the action
POST /api/v1/confirmations/{confirmation_id}/approve
{ "reason": "Verified against PO 4421" }      # body optional

# Deny, which cancels the action
POST /api/v1/confirmations/{confirmation_id}/deny
{ "reason": "Wrong client account" }          # body optional

Records are single-use, scoped to the caller that issued the original tool call, and expire after five minutes by default. A denied confirmation cannot be re-approved; call the original tool again to retry.

Lifecycle

Poll GET /api/v1/confirmations/{confirmation_id} to check status. The status field moves through:

  • pending: awaiting a decision.
  • approved: the caller approved, so the action executes.
  • denied: the caller denied, so the action is cancelled.
  • expired: the five-minute window elapsed.

To cancel a pending confirmation outright, use DELETE /api/v1/confirmations/{confirmation_id}.

Framework Adapters Handle This for You

With the Python or TypeScript SDK and a framework adapter, the confirmation surfaces natively.

LangGraph

The adapter raises a NodeInterrupt carrying prompt_markdown and pauses the graph. Resume with graph.ainvoke(None, config) once the user approves.

OpenAI Agents SDK

The tool raises a ConfirmationRequiredError. Catch it, surface err.prompt_markdown, then call tool.approve(err.confirmation_id).

Vercel AI SDK

The tool returns a confirmation result type that triggers the SDK's native confirmation UI.

Calling REST directly
Render prompt_markdown to the user before you decide whether to call /approve or /deny. The human sees what posts before it posts.

Security

  • Records are single-use, so replay is bounded to the five-minute window.
  • Records are scoped to the user or key that issued the original call.
  • The audit log records both the original call and the approve or deny decision.
  • The correlation_id on the original response links the full audit trail.
Confirmation Contract · Archie Developers · Archie for developers