Research-backed calculator guide

AI Agent Cost Ledger JSON Schema: Join Model, Tool, Review and Outcome Events

Design a vendor-neutral AI agent cost ledger JSON schema that joins runs, model calls, tools, retries, human review, outcomes, usage, prices, and reconciliation status.

● First-party sources checked▧ Original calculation examples◌ Estimate, not a vendor quote

Quick answer

An AI agent cost ledger JSON schema should treat cost as an event-level fact, not as one number attached to a conversation. Give every run a stable run_id, every event an event_id, and every provider request an attempt_id. Connect child events to a parent_event_id, while also retaining a correlation_id for subagents that execute in a separate trace. Store the raw provider usage beside normalized usage, identify the exact price-table version used, and mark whether the amount is estimated, provider-reported, reconciled, or unknown.

The minimum useful chain is: trigger → agent step → model request → tool call → retry or fallback → human review → accepted outcome. A ledger that omits the outcome can tell you what was spent, but not cost per successful task. A ledger that stores only normalized dollars cannot explain a provider variance later. A ledger that relies on timestamps instead of durable IDs breaks as soon as work is concurrent.

Provider APIs illustrate why the contract must preserve detail. Anthropic’s usage reporting can expose uncached input, cached input, cache creation, output, model, workspace, service tier, and server-tool usage, while its cost report is a separate daily, USD-denominated view.[1] OpenAI’s Agents observability guidance describes session events, saved items, turns, subagents, and best-effort token usage; it also warns that recorded usage can be null or change as accounting arrives.[3] Your internal schema should be able to retain both kinds of evidence without pretending they are the same.

Run your scenario

Turn this framework into an editable estimate.

Use dated, source-linked assumptions and see cost per request, successful task and month.

AI API invoice reconciliation calculator

What the ledger must join

Start with identifiers before choosing columns. run_id represents one user-visible task. workflow_id identifies the deployed workflow version. event_id identifies one immutable occurrence. parent_event_id expresses nesting when it exists. correlation_id joins events that belong to one business task even when a framework creates separate traces. attempt_id identifies one provider attempt, including a retry that returns an error or a fallback that succeeds elsewhere.

Keep these identifiers immutable. If a retry is mistakenly written over the first attempt, you lose the evidence needed to explain duplicate charges. If a child agent gets a new run ID with no correlation link, the parent’s total will understate cost. If a human review happens outside the trace, you cannot connect review labor or the accepted decision to the inference that produced it.

The event envelope can be small and stable:

{
  "event_id": "evt_01J...",
  "run_id": "run_01J...",
  "workflow_id": "support_triage@2026-11-02",
  "event_type": "model_request",
  "occurred_at": "2026-11-02T10:15:02Z",
  "parent_event_id": "evt_parent...",
  "correlation_id": "corr_01J...",
  "attempt_id": "att_01J...",
  "actor": {"agent_id": "triage-agent", "tenant_id": "acme", "user_id": "u_123"},
  "status": "succeeded"
}

event_type should be an allow-list such as trigger, agent_step, model_request, tool_call, retry, human_review, and outcome. Do not overload one event with fields that mean different things. A tool_call can have a duration and external charge, but it should not masquerade as a model request simply because a tool internally calls a model.

For a model_request, preserve provider-native fields exactly as received. A practical usage_raw object may contain input_tokens, output_tokens, cache_read_input_tokens, cache_creation_input_tokens, reasoning_tokens, audio seconds, image units, request count, and provider request ID. Store usage_normalized separately with canonical names and units. Never replace a missing value with zero unless the provider explicitly says zero; use null plus a reason such as not_reported or not_applicable.

The cost object should separate calculation from confidence:

{
  "currency": "USD",
  "cost_status": "estimated",
  "price_table_id": "openai-public-2026-11-02",
  "price_table_version": "2026-11-02T00:00:00Z",
  "lines": [
    {"meter":"input_tokens","quantity":12000,"unit":"tokens","unit_price":2.00,"price_unit":"1M tokens","amount":0.024},
    {"meter":"output_tokens","quantity":2500,"unit":"tokens","unit_price":10.00,"price_unit":"1M tokens","amount":0.025}
  ],
  "total": 0.049
}

A useful state machine is estimated → provider_reported → reconciled, with unknown available whenever required usage or price evidence is missing. Do not silently move backward. If a late provider correction changes the amount, append a reconciliation adjustment event and retain the original estimate. Anthropic notes that analytics exports can be revised as late events arrive and reconciliation runs.[2] That is a strong reason to make corrections additive and auditable.

The price table needs more than a model name. Include provider, deployment or region when relevant, service tier, context-window band, token meter, currency, effective-from and effective-to timestamps, and the source URL. OpenAI’s pricing page lists separate input, cached-input, and output rates per million tokens and also prices non-token units such as web search calls and container time.[4] A ledger that has only model and total_cost cannot prove which rate or meter produced the number.

Visual schema walkthrough

This original table is a compact demonstration of the joins and calculations. The figures are illustrative assumptions, not a vendor quote. It uses the OpenAI pricing page’s displayed GPT-6.1 Sol standard rates as an example: $2.00 per million input tokens, $0.10 per million cached input tokens, and $10.00 per million output tokens, checked on 2026-11-02.[4]

Event and joinInputs capturedNormalized calculationOutput and confidence
run_42 / evt_1 trigger1 task, tenant=acme, no provider usageNo model charge$0.000; not_applicable
run_42 / evt_2 model request, att_112,000 uncached input; 2,500 output; GPT-6.1 Sol(12,000 / 1,000,000 × $2.00) + (2,500 / 1,000,000 × $10.00)$0.049; estimated
run_42 / evt_3 tool call1 search call; same run_id, parent evt_2Keep tool meter separate from token lines; use the provider’s tool price when reportedSeparate line; estimated or provider_reported
run_42 / evt_4 retry, att_24,000 input; request failed after provider acceptancePrice the accepted usage if the provider bills it; do not overwrite att_1Add a second attempt line; status depends on invoice evidence
run_42 / evt_5 human review90 seconds review; reviewer decision acceptedOptional internal labor rate × minutes; keep it outside provider inference total$0.30 at an assumed $20/hour; estimated
run_42 / evt_6 outcomeaccepted=true, quality score 0.92provider_cost + review_cost, divided by one accepted taskCost per accepted task is $0.349 under the assumptions

If the retry was not billed, record provider_reported_amount=0 for that attempt only after you have evidence. Until then, the correct state is unknown or estimated, not zero. Likewise, review labor is an internal assumption and should never be confused with an OpenAI invoice amount.

Worked cost example: from attempts to accepted outcome

Assume one support task has two GPT-6.1 Sol requests. The first request uses 12,000 input tokens and 2,500 output tokens. A second request is a retry with 4,000 input tokens and 800 output tokens. Assume both are accepted for billing, no cache discount applies, and the model rates above remain effective. The first request costs $0.049. The retry costs (4,000 × $2 / 1,000,000) + (800 × $10 / 1,000,000) = $0.016. Model cost is therefore $0.065.

Now add one web-search tool call only if your provider invoice reports a charge for it. OpenAI’s pricing page currently shows web search at $10 per 1,000 calls, so one call would be $0.010 under that displayed rate.[4] Add an assumed 90 seconds of human review at $20 per hour: $20 × 90 / 3,600 = $0.50, not $0.30—the table’s $0.30 row is intentionally a separate lower-rate illustration and should not be mixed into this scenario. The fully loaded task estimate is $0.065 + $0.010 + $0.50 = $0.575.

The accepted-outcome metric is $0.575 per accepted task when one task produces one accepted outcome. If three attempts were required and only one outcome was accepted, divide by one accepted outcome, not by three requests. For a batch, calculate both cost_per_run and cost_per_accepted_outcome; they answer different operational questions.

The invoice-reconciliation step then compares the ledger’s provider portion of $0.075 with the provider export. Review labor remains internal. If the provider export says $0.085, the variance is $0.010. Do not force the ledger to match by editing the original event. Add a reconciliation record with the provider invoice row ID, observed amount, variance, checked time, and resolution such as tool_meter_missing or price_version_mismatch.

Reconciliation and data-quality rules

Run reconciliation at the provider’s reporting grain. Anthropic’s legacy cost endpoint reports daily USD costs and separates token, web-search, and code-execution cost types; its usage endpoint supports finer time buckets and dimensions.[1] Anthropic’s analytics response also includes a data_refreshed_at watermark and warns that grouped rows can be capped, so an export may be incomplete or non-exhaustive for a grouping.[2] Treat those facts as ledger metadata: source_grain, refreshed_at, is_complete, and grouping_limit belong in the reconciliation record.

OpenAI’s observability guidance similarly describes usage as best-effort and says missing usage does not mean zero usage.[3] In practice, use a daily exception queue for events with null usage, missing price-table matches, negative quantities, duplicate provider request IDs, or a provider total that differs beyond tolerance. A small absolute tolerance can be useful for rounding; a large unexplained variance should remain visible.

For privacy, keep prompts and tool payloads out of the financial fact table unless there is a justified retention policy. Store content references or hashes, not unrestricted transcripts. Restrict high-cardinality identifiers in rollups, but retain them in the immutable event store so an auditor can trace a daily aggregate back to attempts.

When this schema is the right tool

Use this design when one task can fan out across models, providers, tools, retries, or human reviewers. It is especially useful for chargeback, budget guardrails, incident review, and cost per successful task. For a simple one-model monthly estimate, the AI Agent Cost Calculator is faster. For tail-risk controls, compare the same ledger’s run distribution with the AI agent budget guardrail and P95 calculator. For build-versus-buy planning, use the AI agent development cost estimator.

The schema is not a billing guarantee. Provider contracts, rate cards, discounts, taxes, reserved capacity, and marketplace fees can change the final invoice. It also cannot infer business value from a successful HTTP response. That is why accepted_outcome, quality evidence, and human decisions should be first-class fields rather than after-the-fact spreadsheet columns.

FAQ

What is an AI agent cost ledger JSON schema?

It is a structured contract for recording every billable or cost-relevant event in an agent workflow and joining those events to a run and an outcome. It preserves raw usage, normalized meters, price-table identity, cost status, and reconciliation evidence so engineering and finance can answer both “what did this request cost?” and “what did this accepted task cost?”

Should retries get their own ledger events?

Yes. Give each provider attempt its own attempt_id and event. A retry can consume tokens, fail after acceptance, or be free under a provider policy. Overwriting the first request hides that distinction and makes invoice variance impossible to explain. Link retries to the same run_id and parent step, but never reuse the original attempt ID.

What is the difference between estimated and reconciled cost?

Estimated cost is calculated from observed usage and a price table. Provider-reported cost is the amount exposed by a provider usage or cost export. Reconciled cost is the amount matched to a provider billing row or accepted reconciliation result. Keep all three when possible; a reconciled total should not erase the estimate that helped operate the system in real time.

Do tool calls belong in the same ledger as model calls?

Yes, but as separate event types and meters. A tool may be free, priced per request, priced by bytes or seconds, or may invoke another model. Keeping it separate prevents double counting and lets you distinguish provider inference spend from search, code execution, retrieval, or internal labor.

How do I calculate cost per successful or accepted task?

Sum the provider, tool, and optionally internal review costs for all events sharing a run_id, then divide by the number of accepted outcomes. For a single accepted task, the denominator is one even if the workflow used several attempts. For aggregate reporting, state whether the denominator is runs, completed tasks, or accepted outcomes; these metrics are not interchangeable.

Is OpenTelemetry required?

No. OpenTelemetry can provide useful trace and span conventions, but the ledger contract only requires durable identifiers, event timestamps, usage, cost, and outcome fields. If your tracing system uses separate traces for subagents, preserve a shared correlation_id so the financial join survives framework-specific trace boundaries.

Primary sources checked

Pricing and product behavior can change. These sources support the time-sensitive claims in this guide; verify current provider terms before committing spend.

  1. Anthropic Usage and Cost API
  2. Anthropic Get Token Usage Over Time
  3. OpenAI Agents API Observability and Usage
  4. OpenAI API Pricing

About the Author

Zunair Ali Syed is a doctoral researcher in Management Sciences at Minhaj University Lahore and a research consultant with experience in academic research and editing since 2011. He runs QuickEduHelp, with professional interests in digital learning, research methods, and evidence-based academic support.