Human-in-the-Loop AI Purchases: Approval Workflows That Actually Work
June 11, 2026 · Victor Young
AI agents that buy things autonomously without any human checkpoint are a liability, not an asset. For most organizations, fully autonomous spending introduces too much financial and operational risk to be practical. The right model is human-in-the-loop: the agent does the research, surfaces options, and waits for a human to confirm before money moves. This post walks through the design patterns that make approval workflows fast enough to be useful and rigorous enough to be trustworthy.
Why Fully Autonomous Spending Is a Non-Starter
The appeal of a fully autonomous purchasing agent is obvious—no friction, no waiting. But the risks compound quickly. An agent optimizing for speed might pick the cheapest option without accounting for supplier reliability. One optimizing for quality might exceed a budget. Without a human checkpoint, there is no moment to catch a misunderstood intent before money leaves the account.
There is also an organizational reality: most companies have procurement policies, approval chains, and audit requirements that exist for legal and financial reasons. An agent that bypasses them does not eliminate those requirements—it just creates a compliance gap. For a deeper look at why agent accountability matters, see what a commerce execution API actually does and the Firestarter vs. Zip comparison on approval controls.
The practical middle ground is an agent that handles everything except the final authorization. It parses intent, searches suppliers, compares options, calculates total landed cost, and presents a clear summary—then stops and waits.
The Four-Stage Lifecycle
A well-designed approval workflow follows a consistent pattern:
1. Propose — The agent receives a request and translates it into a structured execution. It searches available suppliers, applies budget constraints, and ranks options by a combination of price, shipping time, and supplier score.
2. Review — The agent surfaces its top recommendations with enough information for a human to make a real decision. This is the gate. The execution sits in pending_approval status until someone acts.
3. Approve — A human reviewer confirms (or rejects) via an API call or a UI action backed by that call. Approval can be delegated—a manager approves large orders, a team lead approves small ones—based on amount thresholds configured at the API level.
4. Execute — Payment is authorized, a shipping label is generated, and tracking begins. From this point the agent monitors the order and handles exceptions (delays, damage, cancellations) without further human input.
This maps directly to Firestarter's lifecycle. When you POST to /v1/executions, the execution advances automatically through parse, search, and compare, then holds at pending_approval. From there, a human—or an automated policy engine—calls /v1/executions/:id/approve.
What a Human Needs at the Gate
An approval step is only useful if the reviewer has enough information to make a real decision quickly. The worst approval UIs show a request summary and ask "approve or reject?" without context. Reviewers either rubber-stamp or slow everything down asking clarifying questions.
A useful approval payload includes:
- The original request — what the agent was asked to find
- Top-ranked options — at minimum the recommended option plus one or two alternatives, with supplier name, unit price, and lead time
- Total landed cost — item cost plus shipping plus tax, not just unit price
- Estimated delivery date — specific, not "3–5 business days"
- Budget status — whether the order fits within the configured spend limit and what headroom remains
Here is what a Firestarter execution looks like when it reaches the approval gate:
{
"id": "exec_01HXYZ123",
"status": "pending_approval",
"request": "noise cancelling headphones under $80",
"budget": { "max_total": 80 },
"options": [
{
"rank": 1,
"supplier": "AudioSupplyCo",
"product": "SoundShield Pro 40",
"unit_price": 67.99,
"shipping": 5.99,
"tax": 3.40,
"total_landed": 77.38,
"estimated_delivery": "2026-06-14",
"in_budget": true
},
{
"rank": 2,
"supplier": "TechDirect",
"product": "QuietMate 200",
"unit_price": 71.50,
"shipping": 0,
"tax": 3.58,
"total_landed": 75.08,
"estimated_delivery": "2026-06-16",
"in_budget": true
}
],
"approve_url": "https://api.firestarter.network/v1/executions/exec_01HXYZ123/approve"
}
The reviewer sees real numbers for both options and can approve the recommendation or switch to an alternative in the same call.
Async Approval: Polling vs. Webhooks
Approval does not have to be synchronous. In most real deployments, the agent kicks off an execution, the request goes into a queue or notification channel, and a human reviews it when they next check their inbox or task list. Two patterns handle this well.
Status polling — The agent (or a calling system) periodically calls GET /v1/executions/:id and checks the status field. Once it transitions from pending_approval to approved or rejected, the agent either continues or surfaces the rejection for follow-up. Polling is simple to implement but wastes requests if the review cycle is long.
Webhooks — Firestarter posts a status-change event to a configured endpoint when an execution transitions state. Your system receives the event, routes it to the right handler (continue the agent workflow, notify the requester, log the outcome), and responds. Webhooks are more efficient for high-volume deployments and work well when approval is integrated into a Slack bot, email workflow, or internal dashboard.
See the full webhook and polling reference in the developer docs and the OpenAPI spec for the complete status transition model.
Calling the Approve Endpoint
Once a reviewer has seen the options and is ready to proceed, approval is a single POST:
curl -X POST https://api.firestarter.network/v1/executions/exec_01HXYZ123/approve \
-H "Authorization: Bearer fs_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"selected_option_rank": 1,
"approved_by": "user@example.com",
"note": "Approved for Q2 equipment budget"
}'
The approved_by field becomes part of the audit trail—recorded against the execution so there is always a human name attached to the authorization. The note field is optional but useful for procurement records.
After approval, the execution advances to payment_processing, then shipping, then in_transit. All transitions are queryable via GET /v1/executions/:id and appear in the step-by-step log.
Configuring Approval Thresholds
Not every purchase needs senior review. A good approval system is tiered: small purchases might auto-approve or require a quick confirmation, while large orders escalate. Firestarter supports per-execution spend limits and approval checkpoints configured when you create an execution:
{
"request": "office supplies for Q3",
"budget": {
"max_total": 500
},
"approval": {
"required": true,
"notify": ["ops@example.com"]
}
}
For orgs building agent workflows at scale, the MCP integration lets you expose firestarter_approve as a tool that an orchestrating agent can trigger after receiving confirmation from an authorized human in a conversation thread—useful for Slack-native or assistant-native approval flows.
What Happens on Rejection
Rejection should not be a dead end. When an approval call returns rejected, the agent has context about why—too expensive, wrong supplier, needs different specs—and can restart the search with refined parameters. The /v1/executions/:id/message endpoint lets a human send a correction mid-lifecycle:
curl -X POST https://api.firestarter.network/v1/executions/exec_01HXYZ123/message \
-H "Authorization: Bearer fs_live_YOUR_KEY" \
-d '{"message": "Prefer a supplier with 2-day delivery even if slightly more expensive"}'
The execution re-enters the search and comparison stages with updated preferences, then returns to pending_approval with a revised set of options. The full history of both rounds is preserved in the audit log.
For more on the end-to-end flow, see AI procurement automation and the kraft mailer scenario for a concrete B2B example.
FAQ
Can I turn off the approval checkpoint entirely?
Yes. Set "approval": {"required": false} in the execution request. Firestarter will advance automatically from options_ready to payment_processing without waiting for human input. This is appropriate for low-value, high-frequency purchases with tight budget constraints already enforced at the API level—but understand that you are shifting all review responsibility to the pre-purchase configuration.
How long does an execution stay in pending_approval before it expires?
Executions in pending_approval do not expire by default. Supplier quotes and inventory availability may change over time, so the execution surfaces a warning if a significant delay has elapsed since options were generated. You can also call /v1/executions/:id/cancel at any point to close the execution without proceeding.
Can different users have different approval authority levels?
Approval authority is enforced at the application layer—your system decides which users can call /approve for which executions. Firestarter records the approved_by identifier you supply; it does not maintain an internal user-role hierarchy. See the developer docs for patterns on building role-gated approval into your integration.
Does Firestarter support multi-step approval chains (e.g., manager + finance)?
The current model supports a single approval gate per execution. Multi-step chains—where the execution must be approved by two or more parties in sequence—are implemented by holding the execution in pending_approval until your application has collected all required sign-offs, then calling /approve once all conditions are satisfied. See /use-cases/agent-approval-audit-api for integration patterns.
What does it cost to run approval workflows through Firestarter?
Each execution consumes one token. Free tier: 100 tokens to start plus a 14-day Pro trial, no credit card required. Pro is $99/month with 10,000 tokens. Buyers pay no transaction fees.