Scenario · Customer service · Verified live
A real durable approval, end to end
This is a live-verified walkthrough — not illustrative pseudocode. Every step below was actually run against a real model and a real signed webhook.
A message comes in, no human watching
A customer emails support asking for a refund on a broken order. The request hits POST /messages — not the streaming route, nobody's watching this exact response. The model looks up the order (auto-allowed) and calls issue_refund.
The gated call pauses instead of blocking
issue_refund matches an "ask" rule in production. Instead of holding the request open, the call returns instantly with stopReason: "pending_approval" and a pendingId. A signed webhook (HMAC-SHA256, X-Actauth-Signature) fires to the configured destination. The process is free to exit — nothing is held open.
A human resolves it, whenever they get to it
Minutes or days later: POST /pending-approvals/:id/resolve with { "decision": "approve" }. The turn resumes from a durable checkpoint, picks the conversation back up, and actually executes the refund.
Resuming can pause again
The model now drafts a refund-confirmation email. send_email's own intent field is "refund", not "tracking_info" — it falls through the content-conditional gate to its own ask rule. A second, independent pending approval opens, chained inside the resumed turn, with its own webhook.
Approve that too, and the turn actually finishes
Once every outstanding item in the batch is resolved, the turn finishes for real — the final customer-facing reply comes back from the resolve call itself, and a run_finish lifecycle webhook fires with the full text.
Cascade-skip, the other real case
If two calls in the same batch are both pending and one gets denied, the checkpoint closes immediately — the denial doesn't wait for its sibling. The still-outstanding item gets a synthesized skipped result instead of being left dangling, and the turn resumes with both outcomes accounted for in one message.
Same mechanism, a different domain: see the incident-triage scenario for on-call approvals gated through Slack's own interactive buttons, or the expense-approval scenario for a channel with no platform signature to lean on at all.