Blog · · 11 min read
AI agent pricing without double-charging for retries

AI agent pricing breaks when a SaaS product sends raw model tokens or tool calls straight to the customer invoice. One user action can branch into several model turns, tools, retries, and a human review. The customer did not choose that execution plan, and a retry should not create a second charge. Meanwhile, a flat feature fee can hide expensive workflows until margins disappear. The fix is to keep two linked ledgers: one for the real cost of each agent run and another for customer-visible billable outcomes. This guide shows how to choose the unit, meter it once, handle failures and reversals, enforce plan limits, and verify margin before launch.
Separate cost attribution from customer billing
The run-cost ledger answers internal questions. Which tenant, workflow, model, tool, agent release, and review step created cost? The OpenAI Usage API and Costs API cookbook shows provider usage and cost data grouped by fields such as model and project. That data is useful for reconciliation and routing decisions. It is not automatically a good customer unit.
The billing ledger answers a customer contract question. What understandable unit did the product deliver, under which price and entitlement rules, and has that unit already been charged or reversed?
Keep both ledgers immutable. Corrections should append adjustment events instead of rewriting prior events. Link them with run_id, tenant_id, workflow_id, and agent_release_id, but never require one cost event to equal one billable event. A successful outcome may use several providers and tools. A failed run may create cost without creating anything billable.
This separation closes the main forecasting problem in a direct Hacker News practitioner question: one SaaS action can generate an unpredictable number of LLM requests and tokens. Your product should absorb that execution variability inside a defined unit, then manage it through internal budgets and routing.
Choose the right AI agent pricing unit
Current AI agent pricing pages already describe many models. Sierra compares traditional, consumption, and outcome-based pricing, while a Forbes contributor catalogs conversation, labor-replacement, outcome, blended, and agentic-seat approaches. The product decision is which unit your workflow can accept or reject consistently.
| Unit | Use it when | Main risk |
|---|---|---|
| Seat | Agent value is broadly available to each licensed user | Heavy users can make the plan unprofitable |
| Request | One request has a stable scope and cost envelope | Retries and multi-step requests make the unit ambiguous |
| Provider token | Customers explicitly buy raw inference capacity | Bills expose implementation detail and become hard to predict |
| Conversation | A conversation has a clear start, end, and service boundary | Long or repeated conversations can vary widely in cost and value |
| Accepted outcome | The product can verify a durable business result | Subjective or delayed acceptance can create disputes |
For an existing SaaS product, start with a hybrid contract: a base subscription includes a defined number of accepted outcome units, with an overage price or credit draw after the allowance. Keep provider tokens, tool fees, infrastructure, and review time inside the cost ledger.
Do not use outcome pricing when acceptance is subjective or cannot be observed within a reasonable reconciliation window. In that case, choose a bounded product unit such as a completed workflow, reviewed document, or processed record batch. Define its maximum scope so one unit cannot expand without limit.
A practitioner analysis of AI coding tools reports unpredictable credit burn and compares included completions, overages, throttling, hybrid, and outcome approaches. Treat that as one author's experience, not a market statistic. Customers need to know what consumes a unit, while the platform needs a hard ceiling on the work hidden inside it.
Define an accepted-outcome contract
Write the acceptance contract before integrating a billing provider. Product, engineering, support, and finance should be able to evaluate the same event and reach the same result.
For each workflow, specify:
- The object being changed or produced.
- The evidence required for acceptance.
- The actor allowed to accept it automatically or manually.
- The deadline after which the outcome becomes rejected or expired.
- The retry and correction work included in the original unit.
- The conditions that create a reversal or credit.
- The price and entitlement versions applied at acceptance time.
Use a state machine such as pending, accepted, rejected, expired, disputed, and reversed. Only the transition into accepted creates a positive billable unit. reversed creates a compensating negative adjustment. A later retry does not create a new unit unless it delivers a separately accepted result under a new customer request.
A portable event can look like this:
{
"billing_event_id": "outcome:tenant_42:ticket_817:resolution:v1",
"tenant_id": "tenant_42",
"workflow_id": "support_resolution",
"subject_id": "ticket_817",
"run_id": "run_29a4",
"agent_release_id": "release_2026_08_05_1",
"outcome_state": "accepted",
"acceptance_rule_version": "support-resolution-v3",
"price_version": "agent-plus-2026-08",
"entitlement_version": "pro-plan-v5",
"quantity": 1,
"accepted_at": "2026-08-05T14:03:00Z"
}
The identifier is deterministic for the billable outcome, not for each execution attempt. If a worker crashes after sending the event and sends it again on resume, both attempts carry the same identifier.
Meter once across retries and resumes
Stripe's meter-event API documentation says to use idempotency identifiers to prevent reporting usage more than once. It also notes that meter events are processed asynchronously, so an upcoming invoice may not immediately reflect a newly accepted event. Design your product ledger as the source of truth for what you emitted and what the billing provider acknowledged.
Use this sequence:
- Create a run with its tenant, workflow, entitlement snapshot, and internal cost budget.
- Reserve the required customer allowance or credit before expensive work starts.
- Append model, tool, infrastructure, and review costs to the run-cost ledger.
- Evaluate the workflow's versioned acceptance rule.
- Create one deterministic billable event when the outcome becomes accepted.
- Deliver it through an outbox and record the provider acknowledgement.
- Release the reservation if the outcome is rejected, expired, or cancelled.
- Append a reversal if an accepted outcome is later invalidated under policy.
The write that accepts the outcome and inserts the billing outbox record should be atomic in your product database. Delivery to the external billing system can then retry safely.
def accept_outcome(tx, run, evidence):
rule = load_acceptance_rule(run.acceptance_rule_version)
if not rule.accepts(evidence):
tx.mark_outcome(run.id, "rejected")
tx.release_reservation(run.entitlement_reservation_id)
return
event_id = deterministic_outcome_id(
tenant_id=run.tenant_id,
workflow_id=run.workflow_id,
subject_id=run.subject_id,
acceptance_rule_version=run.acceptance_rule_version,
)
tx.insert_billable_event_if_absent(
event_id=event_id,
run_id=run.id,
quantity=1,
price_version=run.price_version,
)
tx.consume_reservation(run.entitlement_reservation_id, event_id)
tx.enqueue_billing_delivery_if_absent(event_id)
The if_absent checks must be backed by unique constraints. An in-memory duplicate check is not enough after a process restart or concurrent resume.
Decide which failures are billable
- A provider or platform retry does not create another unit. The customer requested one result, and the platform chose to retry its execution.
- A rejected or expired result releases the reserved unit. Internal cost remains in the run-cost ledger.
- A partial result is billable only if the plan names it as a separate accepted unit. Do not invent a fractional charge after the fact.
- A customer-requested revision reuses the original unit when it corrects an unaccepted result. Create a new unit only when the customer accepts a new scope and the product records that decision.
- Required human review is internal cost. Price it separately only when the customer explicitly purchases a review service with its own acceptance contract.
- A disputed accepted result moves to
disputedwith its evidence and applied rule version. Append a reversal if policy grants the credit.
Never delete an accepted event to make an invoice match. A reversal preserves the audit chain from acceptance to adjustment and lets finance reconcile the product ledger with the billing provider.
Enforce plan gates before the agent runs
Stripe's usage-based billing overview supports usage pricing and adding it to existing flat-rate subscriptions. Your product still owns the entitlement decision that happens before work begins.
Evaluate these gates in order:
- Is the workflow included in the customer's plan?
- Is an included unit, prepaid credit, or approved overage available?
- Does the run fit the plan's maximum scope, tool, and review policy?
- Does the tenant remain below its hard spend or unit limit?
- Does the internal cost budget permit the chosen model and tool plan?
Return a typed product outcome such as upgrade_required, credit_required, limit_reached, or cheaper_mode_available. Do not let the agent discover a billing denial halfway through side effects.
Use soft warnings before a hard limit. Show consumed units, pending reservations, accepted units, reversals, and the next reset date. Pending reservations must be visible because several long-running tasks can otherwise appear to fit the same final allowance.
Work through a support-agent example
Suppose an existing help-desk product charges for accepted ticket resolutions. One billable unit is a ticket whose resolution passes the current acceptance rule, regardless of how many model requests, tool calls, or conversations produced it.
A run reads the ticket, customer account, and plan; drafts a response; updates the record; and waits for either an automated policy check or an agent review. Those steps append costs internally. If a provider timeout repeats the draft call, the retry stays inside the same run. When the ticket reaches the accepted resolution state, the product emits one event keyed by tenant, ticket, workflow, and acceptance-rule version.
If the tool update succeeds but billing delivery times out, the outbox retries the same event ID. If the customer reopens the ticket within the contractual reversal window and support determines that the resolution was invalid, the product appends one reversal. Finance can now see the original accepted unit, the reversal, and the total execution cost without pretending that cost disappeared.
This contract also makes pricing experiments safer. A new price can apply to new acceptance events while every old event keeps its original price_version. A plan migration changes future entitlement snapshots, not historical usage.
Verify margin by workflow and cohort
Do not evaluate AI economics only at the provider account level. Reconcile at least by tenant, plan, workflow, agent release, model route, and acceptance-rule version.
Use definitions that finance and engineering share:
run_cost = model_cost + tool_cost + infrastructure_cost + review_cost
accepted_units = distinct accepted outcome IDs
net_units = accepted_units - reversed units
recognized_agent_revenue = billed unit revenue - credits and reversals
contribution = recognized_agent_revenue - run costs for the same cohort
Late provider costs should append to the original run's cohort. Late reversals should adjust the original billable cohort and the current financial period according to your accounting policy. The product analytics layer should preserve both views rather than silently moving the original event.
Review p50, p95, and worst-case run cost alongside acceptance rate and contribution. Averages alone can hide one workflow whose long tail consumes the margin earned elsewhere. Use those observations to change the internal cost budget, route to a cheaper execution path, narrow the unit's allowed scope, or change the next price version. Do not retroactively change what an accepted historical unit meant.
Test the billing contract before launch
Run the same scenarios against the product ledger, delivery outbox, and billing-provider test environment.
| Scenario | Required result |
|---|---|
| Model or tool retries three times | One accepted outcome can create at most one positive billable event |
| Worker crashes after event delivery | Resume sends the same event ID and does not duplicate usage |
| Acceptance and outbox write race | Both commit together or neither commits |
| Customer lacks allowance | Agent work does not start and no provider cost is created |
| Price changes during a long run | Acceptance uses the price snapshot promised by policy |
| Accepted outcome is disputed | One linked reversal is appended without deleting history |
| Provider cost arrives late | Cost attaches to the original run and cohort |
| Billing provider is unavailable | Accepted event remains in the outbox and retries with bounded backoff |
After launch, reconcile three counts every day: accepted outcomes in the product ledger, acknowledged positive and negative events in the billing provider, and invoice quantities. Alert on missing acknowledgements, duplicate identifiers, stale reservations, reversals without originals, and costs without a valid run.
Avoid common pricing mistakes
Pass token prices through only when the customer explicitly buys inference capacity. A product that sells results should not charge execution attempts, and every retry should retain the original billing key. Price and acceptance-rule changes apply to new events rather than history. Required human review belongs in the cost ledger. Keep margin reporting separate for each workflow instead of blending them into one average.
Also avoid claiming that outcome pricing solves every product. If acceptance is subjective, delayed for months, or controlled by an external party, a completed workflow or bounded usage unit is easier to audit. The best unit is the narrowest one that customers understand, the product can verify, and the platform can deliver inside a controlled cost envelope.
Make the pricing decision
For AI agent pricing inside an existing SaaS product, use a base subscription with included accepted outcome units and a clear overage or credit rule when three conditions hold: acceptance is objective, the outcome maps to durable product state, and disputes can be reversed through policy. Keep tokens and tool calls internal.
If any condition fails, bill a bounded workflow unit instead. Define its maximum records, actions, runtime, and review scope, then expose that limit before the run starts.
Take one production workflow now and write its acceptance state machine, deterministic billing-event key, reversal rule, entitlement gate, and cost-ledger dimensions. Run the eight test scenarios above before connecting the event to a live invoice.
References
- Stripe usage-based billing supports the generic subscription and usage-billing layer.
- Stripe meter-event API supports asynchronous usage processing and idempotent meter-event delivery.
- OpenAI Usage API and Costs API cookbook supports provider cost retrieval and attribution dimensions.
- Sierra outcome-based pricing supports the distinction between consumption and customer outcome units.
- Nibzard AI coding agent pricing provides a practitioner report about credit burn and alternative pricing structures.
- Forbes AI agent pricing guide provides current competitive coverage of common agent pricing models.
- Hacker News question about agentic SaaS cost provides direct practitioner problem language about unpredictable multi-call cost.