Examples
Outcome-based pricing
Sell a finished job. Budget the run. Meter every call that belongs to it.
Acme Support sells “one drafted reply” for $0.50. A reply may take several model calls. Seams does not invoice the $0.50; your product does, but it caps how much inference one reply may burn and attributes every call to that run so you can see cost per ticket.
| Surface | Rule |
|---|---|
| Product price | $0.50 per completed reply (your checkout) |
| Outcome | support-reply with a $0.05 inference ceiling |
| Attribution | Same outcome_id on every call for that ticket |
| Wallet | Team plan allotment or paygo wallet funds the inference |
An outcome ceiling is not the sticker price. It is the budget for provider spend on one job. Charge the customer in your app when the run succeeds; use Seams so a single ticket cannot spend the month.
Define the outcome
seams outcomes add support-reply \
--name "Support reply" --limit 0.05
seams outcomes show support-replyawait seams.outcomes.add("support-reply", {
displayName: "Support reply",
ceilingMicros: "50000", // $0.05
})seams.outcomes.add(
"support-reply",
display_name="Support reply",
ceiling_micros="50000",
)Attribute every call in the job
Pass the outcome slug and a stable id for this run. Same id across retrieve → draft → rewrite is one run; a new ticket id starts another.
curl https://<app>.gw.ourseams.com/v1/chat/completions \
-H "Authorization: Bearer ak_acme_…" \
-H "Content-Type: application/json" \
-d '{
"model": "acme/smart",
"messages": [{ "role": "user", "content": "Draft the reply" }],
"seams": {
"outcome": "support-reply",
"outcome_id": "ticket_8842"
}
}'const completion = await openai.chat.completions.create({
model: "acme/smart",
messages,
// @ts-expect-error seams extension on the provider body
seams: { outcome: "support-reply", outcome_id: ticketId },
})completion = client.chat.completions.create(
model="acme/smart",
messages=messages,
extra_body={"seams": {"outcome": "support-reply", "outcome_id": ticket_id}},
)Charge when the job completes
Your product decides when a reply is done. Bill $0.50 (or decrement an included “replies” counter) on that success path. If a call returns spend_limit_exceeded while attributed to the run, the ceiling was hit, stop the job and surface it; do not silently retry. Use outcomes.runs in the console or API to inspect cost per run (spentMicros, status), not as the invoice key.
// after your agent finishes ticket 8842 successfully
await billCustomer(orgId, { cents: 50, idempotencyKey: "ticket_8842" })
// if a gateway call during the job returned spend_limit_exceeded
await markTicketNeedsReview("ticket_8842")Combine with a plan
Pro can include 200 replies / month as a product counter you own, while Seams still meters inference against the wallet or a monthly credit allotment. The outcome ceiling protects unit economics per job; the plan price covers volume.
| Status | What to do |
|---|---|
running | Job still open; more calls may attribute |
done | Finished inside the ceiling; safe to charge your outcome price |
capped | Ceiling hit; do not silently retry; surface it |
failed | Stopped for a non-money reason |