When you cannot tell what a model call cost: freeze, then reconcile
Sometimes a model call times out and you do not know whether the provider charged you. Never record that as zero. Mark it uncertain, stop new paid calls, and let a named person reconcile it with the provider's statement. Refusals before generation are the exception.
π― For A developer or operator who pays for model calls through an API
- Why an unknown cost must never be stored as zero
- How a freeze and a named reconciliation work
- Which failures cost nothing and which stay uncertain
β The problem
You send a request. The connection drops after thirty seconds. Was it charged? The provider might have generated the whole answer, part of it, or nothing. If your ledger stores zero, your books are wrong in the cheerful direction. If it stores a guess, they are wrong in an unknown direction.
π§ The rule: unknown is unknown
In our metered transport every attempt writes a row, including retries and fallbacks. The cost column can hold a number or the explicit state "uncertain". An uncertain row freezes new paid calls on that lane. The freeze is lifted by one action only: a named person reconciles the row against the provider's activity page and records the real amount and a reason. The agent that hit the problem cannot lift the freeze. An empty name is rejected on purpose.
Three kinds of failure get different treatment.
- Refused before generation. A client error such as a rejected request or "no funds on the account" means the provider produced nothing. The cost is zero and the row is not uncertain. Recording it as uncertain once stopped a pipeline for a day for no reason.
- Timeout or server error. The provider may have done the work. The row stays uncertain.
- Charge above the reservation. Before each task the transport reserves a maximum. If the provider reports a larger charge, the lane freezes until a person acknowledges the difference.
π Where we are today
On 3 November 2026, 22:06 UTC the ledger held 10,150 rows. Open uncertain rows with no reconciliation: 0. Reconciliations recorded in total: 2. Over-reservation acknowledgements: 1.
The acknowledgement is a good example. A provider charged $0.08773 against a reservation of $0.08566, an overrun of $0.00207, about a fifth of a cent. The lane stayed frozen until the account was checked and a person recorded the decision. It is a tiny amount, and the point is the procedure, because the same rule applies when the amount is large.
π οΈ Practice: add the freeze to your own setup
- Store cost as a number or as an explicit unknown. Never default to zero.
- Write one row per attempt, including every retry and fallback, with the provider's request id when you have it.
- Classify failures: refused before generation (zero), timeout or server error (unknown), success (provider-reported cost).
- Before a task starts, reserve its maximum cost. Refuse the task when the daily cap would be passed.
- When a row is unknown, block new paid calls and send a message to the person who owns the account.
- Write a short reconciliation command that needs a row id, the actual amount, a reason and a non-empty name. Log it.
β Check yourself
- Simulate a timeout. The row is uncertain and the next paid call is refused with a clear reason.
- Simulate a rejected request. The row costs zero and nothing is frozen.
- Try to reconcile with an empty name. It fails.
- After a reconciliation, paid calls resume and the record shows who did it and why.
π§ When this does NOT work
- Providers with no activity page. If you cannot see what was charged, you cannot reconcile. Treat every uncertain row as spent at its reservation until the invoice arrives.
- Delayed billing. Some charges appear a day later. Reconcile after the statement is final, not on the first look.
- Shared accounts. Charges from other users on the same key look like overruns. Use separate keys per lane.
- Freezes that block too much. A freeze on the whole system for a one-cent uncertainty is costly. Scope it to the lane that has the unknown.
- Human bottleneck. If only one person can reconcile, the lane waits for them. Name a deputy.
π Evidence
| What we measured | Open uncertain rows, reconciliations and acknowledgements in our metered transport ledger |
| When | 3 November 2026, 22:06 UTC |
| Artifact | The transport ledger database in our private deployment: 10,150 rows, 0 open uncertain, 2 reconciliations, 1 acknowledgement |
| Limit | One ledger, one team. The example amounts are small and are shown for the procedure |
β‘οΈ Next
See how a daily cap and session ids fit with this in A daily AI budget that fails closed, and what a record of a run proves in Agent task receipts.
Sources
- A daily AI budget that fails closed: caps and session ids.
- Agent task receipts: what they prove: evidence per run.
- Costs, budgets and limits: limits.
- Recovery after a failed, stuck or uncertain run: what to do when a run is uncertain.
π Article connections
Open the full knowledge graph βPublished article links. Select a node to open its article at the heading.
Article links Β· keyboard / text view
Same topic
- A vector base is a map, not a source: what we learned from retrieval
- Splitting a big task for a cheap model: the 24,000-byte lesson
- Skills, MCP tools and rules: three ways to give an agent capabilities
- Eight shell and git mistakes our agents made, and the rule for each
- Several agents, one repository: ownership rules from real incidents
- Keep provider keys out of the agent: one gateway, one token per task
Next steps
Related reading
A vector base is a map, not a source: what we learned from retrieval
A vector base finds passages that are close in meaning to your question. It does not know which are true or current. Treat every hit as a pointer: open the file it names, check the hash, and take numbers from the artifact, never from the retrieved paragraph.
AI agents and MCP explainedSplitting a big task for a cheap model: the 24,000-byte lesson
A cheap model does well on one small, well-defined job and badly on a big pile. We cap a task at 24,000 bytes and refuse larger ones before any model is called. Split by unit, one file or one country per task, and check the size before you start.
AI agents and MCP explainedSkills, MCP tools and rules: three ways to give an agent capabilities
Agents get abilities in different ways. A rule constrains what they do, a skill tells them how to do a job, and an MCP tool lets them call a function. Each has its own risk, so declare all three in a register and test that nothing exists unlisted.
AI agents and MCP explainedEight shell and git mistakes our agents made, and the rule for each
Agents write shell commands fast and confidently, and some of the failures repeat. Here are eight real mistakes from October 2026, what each one broke, and the one-line rule we wrote after it. Copy the rules into your own agent instructions.
π¬ Comments