Pause a run for a human. In one call.
An agent calls sb.approval.request(). The run suspends. The request lands in the Studio HITL inbox, an approver decides, and the run resumes with their decision — no queue to poll, no webhook delivery to stand up. It is in the platform and the SDK.
- one call
- built-in inbox
- resumes with the decision
const res = await sb.approval.request({ topic: 'refund.over_limit', payload: { orderId, amount, currency }, onDecide: '/hooks/refund-decided',})// → Result<ApprovalRequest>// { approvalId, status: 'pending', callbackUrl, expiresAt }One run, five stops. The rail and the inbox below are the same run — step the rail and the inbox row moves with it.
- 01requested
- 02suspended
- 03awaiting
- 04decided
- 05resumed
The request is in the Studio HITL inbox; an approver must decide. The run stays suspended.
Pending approvals land here as job rows. The real screen is live — it syncs via SSE; this is a seeded still of it, not a live feed.
- Run
- 7f3a…
- Age
- 2m
- Timeout
- in 23h
- Fallback
- reject
{
"orderId": "ord_9f3",
"amount": 420,
"currency": "usd"
}
- tool·lookup_order done
- approval·refund.over_limit awaiting
No prior decisions.
The live screen decides here. Decide in Studio.
When an approver decides, the control plane comes back to your agent — you read the decision and resume.
The control plane POSTs the decision to it, resolved against the agent’s public URL server-side.
onDecide: '/hooks/refund-decided'On the callback you verify it before trusting it.
approved · rejected · timed_out · cancelledonTimeout decides for you when nobody does.
onTimeout: reject | approve | ignoreconst decision = await sb.approval.verify(request)// → Promise<Result<Decision>>Same topic + idempotencyKey returns the same approvalId — never a duplicate. payload is required by the type
A dedicated approver role exists for compliance and stakeholders — read-only plus the HITL decision (approve / reject / edit payload). It does not run /invoke, edit config, or touch secrets. Roles are mutually exclusive.
one call out. one decision back.
The verbs exist so the surface tree is stable — but they are not live yet.
Scaffolded so the surface tree is stable; every verb returns not_implemented until the runtime ships. The inbox and the SDK call are live today — decide in Studio while the CLI lands.
Wire a human into the loop.