Designed for agents
Built for the code
that asks before it acts.
Most approval tools were designed for humans filling in forms. FinalApproval was designed for agents — long-running processes that need to pause, wait for a decision, and resume with the right branch running.
The problem
An agent is trusted up to the point it isn't.
The agents you build are powerful up to a line — the line where a mistake costs real money, breaks a customer relationship, or can't be undone. Send the email to every subscriber. Issue the refund. Push to production. Delete the row.
The conventional answer is a confirmation prompt in the terminal, or worse, a Slack message and prayer. Neither is a real gate — terminals time out, Slack messages get lost, and both rely on whoever happens to be watching.
FinalApproval is the gate — a queue a human reviews, a decision that fires back, and a branch of your own code that runs on the right answer.
What makes it agent-native
Three things generic approval tools miss.
Skill-first setup
The agent itself runs the install. You describe what needs approval in plain English; the skill provisions the review UI, the signed webhook, and the continuation handler directly in your codebase.
The alternative
Most tools ask you to click through a form wizard and paste configuration into your code yourself.
Continuation-native
The decision doesn't come back as an email or a row in a database — it comes back as a function call in your agent's own runtime. Approve → executeBranch(). Deny → cancelBranch(). No polling, no state reconstruction.
The alternative
Most tools hand you a row in a database and expect you to figure out how to resume the agent that was waiting on it.
Built for many calls, not many configs
Your agent might ask for 500 refund approvals this week. Each one is a single API call with a unique HTML body; the channel, webhook, and API key are configured once and never touched.
The alternative
Most tools scale badly past one-off workflows — every new approval type is a new board, a new form, a new config.
Integration patterns
Three ways your agent waits.
Agents live with different runtime assumptions. FinalApproval supports all three waiting patterns with the same API surface — pick the one that fits your orchestrator.
Stay in the function until the decision arrives.
Simplest pattern. Your code calls POST /api/v1/approvals and awaits a short-poll helper that returns when resolution lands. Fine for agents with long-lived runtimes and short approval SLAs.
const decision = await fa.awaitDecision({
title: 'Refund $1,248 to Acme, Inc.',
body: '<p>Invoice #INV-9831…</p>',
data: { invoice_id: 'INV-9831' },
timeoutMs: 120_000,
});
if (decision.status === 'approved') await issueRefund();Yield. The webhook resumes the workflow.
Right pattern for agents that check-point to disk or to a durable queue. Submit the approval, save the agent's state keyed by the returned request id, and let the webhook handler rehydrate and resume.
const { id } = await fa.submit({ title, body, data });
await queue.parkState({ runId, waitingOn: id });
// — later, in /hooks/refunds —
const run = await queue.resume({ waitingOn: decision.id });
run.continue({ decision: decision.status });Keep producing — resolve this branch asynchronously.
For agents that fan out work. Submit the approval, keep doing other things, and let the webhook fire a single branch resolver that doesn't block the parent trace.
agent.branch('refund', async () => {
const { id } = await fa.submit({ title, body, data });
return fa.resolveOn(id); // resolves when webhook arrives
});
// agent continues other branches in parallelRuntime-agnostic
Works with every agent framework.
FinalApproval is a plain HTTP API. If your agent can make a network request, it can ask for approval. The skills library adds idiomatic bindings for the frameworks you're most likely to reach for.
Claude Agent SDK
SkillTool call that waits for a human
LangChain / LangGraph
SkillCheckpoint node with decision routing
CrewAI
SkillHumanGate tool + resolver callback
Vercel AI SDK
SkillgenerateText tool definition
OpenAI Agents SDK
SkillFunctionTool with parked state
Anything else
HTTPPlain HTTP. Any language. Any runtime.
Let your agent ask before it acts.
Install the skill, describe what you want approved, and ship.