Disclaimer: Cymbal Insurance is a fictional company, and every record in the experiment is synthetic.
The business problem
It usually starts in a monthly cost review. Someone points at the AI line on the invoice. It has grown faster than anything else, and the obvious questions follow: which product is this, which team, which agent? Nobody in the room can answer them with confidence. The money has been spent, the bill is accurate, and it explains almost nothing.
That gap is getting more expensive. Goldman Sachs Research expects AI agents to push token consumption up roughly 24-fold by 2030, to around 120 quadrillion tokens a month. Over the same period, the cost of computing a token is falling 60–70% a year [1]. Read those two numbers together. The unit price keeps dropping while the quantity explodes, so the total bill keeps rising and becomes harder to predict.
Agents are the reason the quantity explodes. A chat exchange might use a couple of thousand tokens. An agent working through a real task (reading documents, calling tools, checking its own work) can use orders of magnitude more [3]. In the experiment later in this post, the first version of a modest insurance-claims agent used 150,796 tokens per claim. That’s for one claim.
I have this conversation almost every week with various leaders. The prototype works, everyone wants to take it to production, and then someone multiplies the pilot’s cost per task by the real transaction volume and the room goes quiet.
This post is about closing that gap: being able to say what every token was for, and whether it was worth it. I’ll call the result a “Token Bill of Materials”. The first half of this post covers the economics: what’s on the bill, why it misbehaves, where the levers are, and how to tie the spend to business value. The second half puts it to the test. I take a Gemini claims agent apart, token by token, and show the numbers, the code and the console steps so you can check my work. Everything is in a public companion repo, tokenomics-paygo-demo, which you can run in your own project.
GitHub repo: https://github.com/Rajdipc/tokenomics-paygo-demo
What “AI tokenomics” actually means
AI tokenomics is the practice of connecting what an AI system consumes to what it produces for the business. It has two halves, and most organizations only do one of them:
- Operational: metering every token, attributing it to an app, team or feature, and engineering it down.
- Strategic: knowing the unit economics, protecting margins, and deciding where the next dollar of AI spend should go.
For anyone who hasn’t had to think about tokens, here is a quick primer. A token is a small piece of text, roughly four characters. Every request bills for the tokens you send in (instructions, documents, conversation history, tool definitions) and for the tokens the model writes back. Two details matter more than people expect. First, a model’s internal reasoning, its “thinking”, is billed at the output rate, which is the expensive one. Second, the API keeps no memory between calls, so in a multi-step agent the whole conversation so far is sent again on every turn. That re-sending is where agent costs compound. The relief valve is context caching: input the model has seen recently can be billed at a steep discount, about 90% off on Gemini [8].
The four meters on an AI bill
Not every AI cost is a token cost. When I look at a typical Google Cloud AI bill, I find four kinds of meter, and each one responds to a different lever:

There’s also a choice about how you buy AI in the first place:
- Packaged software hides the token meter inside a seat price. That’s simple.
- APIs show you every token. That’s transparent, and also volatile.
- Running open-weight models on your own infrastructure gives the most control over long-run cost, but you pay for it in capital and operations.
Most enterprises end up with all three. That’s one reason a single “AI cost” number is meaningless.
Why the usual FinOps playbook struggles
Cloud FinOps grew up around virtual machines and storage. Those workloads are deterministic: a VM costs the same every hour, and you optimize it with reservations and rightsizing. Model calls aren’t like that. The same task can cost twice as much on Tuesday as on Monday because the agent took one extra loop, retried a failing tool, or reasoned a little longer.
The cost drivers are context length and loop count, not uptime. That breaks forecasting that relies on averages. In the experiment below, the median claim used 149,278 tokens and the 95th percentile used 231,640. Budgets have to be built on the tail, not the mean.
Where the money goes: five layers
The most useful map I’ve found splits token cost into five layers, from the infrastructure up to governance. Each layer has its own Google Cloud building blocks.
1. Infrastructure: how you consume capacity. On Gemini Platform you can call models on [5]:
- Standard PayGo, the default
- Priority PayGo, a higher price for more consistent performance
- Flex PayGo, half price for latency-tolerant work, on supported models
- Batch inference, asynchronous jobs at a similar discount
- Provisioned Throughput, reserved capacity for a term
The pricing page also lists Off-peak pricing and a Deferred tier for specific models and agents, so check what’s available for yours [4][5]. If you want a commercial commitment without reserving capacity, Flexible Savings Plans offer discounts in exchange for committed spend [10].
2. Model: what does each task actually need? Gemini comes in tiers, and the price gap between them is wide (following models are used for this blog):
- Gemini 4 Argon for frontier reasoning
- Gemini 3.8 Flash as the workhorse
- Gemini 3.5 Flash-Lite for high-volume extraction and routing
All three are generally available [11]. Model Garden adds open-weight models such as Gemma, plus partner models. The skill is routing: rules for the obvious cases, a cheap model acting as a router, or a cascade where a small model drafts and a larger one only reviews when it’s unsure.
3. Context: what goes into each request. This is the layer with the most waste and the least glamour. The main moves:
- Put static content first so caching can reuse it.
- Keep histories short: start fresh per task, or summarize old turns.
- Send clean, compact text instead of raw JSON dumps.
- Retrieve the passages a question needs rather than whole documents.
4. Harness: how the agent behaves and how you extend it.
- Every tool you declare is sent on every call, so a sprawling toolbox costs money even when it’s unused. A single MCP server that exposes dozens of tools can add 5,000 to 50,000+ schema tokens to every turn.
- Package domain procedures as skills (SKILL.md) and keep workspace rules in AGENTS.md from the start (Principles 2 and 9 in the Eleven Principles guide [2]). Instead of pasting every domain procedure and tool schema into the active system prompt on every call, a skill uses progressive disclosure: the agent keeps only a 30 to 50 token header (name and description) in active context and loads the full workflow instructions and required tools only when a task matches. Persistent rules in AGENTS.md stop the multi-turn corrective re-prompting ("no, format the policy ID like this") that quietly multiplies session tokens.
- Move deterministic work such as ID normalization, schema linting or test runners into commands, hooks or helper scripts that run outside the model loop at zero token cost.
- Delegate narrow jobs to cheaper sub-agents, and put hard limits on retries and loops in code.

5. Governance: who sees the spend and who can stop it.
- Request labels make every Gemini call attributable in Cloud Billing.
- Exporting billing data to BigQuery turns the invoice into something you can query.
- Budgets warn you; Cloud Monitoring alerts catch runaway loops.
At fleet scale, governance needs one more piece: a gateway.
The gateway layer: Apigee
Labels, budgets and loop limits inside one application work well, for one application. Once dozens of teams are building agents, you need controls that sit outside any single codebase. That’s the role of an AI gateway, and on Google Cloud that’s Apigee. These policies are aimed at LLM traffic:
- LLMTokenQuota enforces token budgets per app, product or developer over a time window. It’s the difference between hoping a team stays within budget and knowing it will [12].
- PromptTokenLimit throttles bursts of prompt tokens, like a spike arrest built for LLMs, so one runaway client can’t flood a model backend [13].
- SemanticCacheLookup and SemanticCachePopulate reuse a stored answer when a new prompt means the same thing as an earlier one [14]. This shines on repetitive traffic such as policy FAQs or internal help desks. It does little for unique work like individual insurance claims, and it’s worth being honest about that before you sell it internally.
- Routing and analytics. Apigee can send requests to different models or backends, and its analytics give finance a per-consumer view that supports chargeback.

Apigee has an evaluation option and pay-as-you-go pricing, so you can try this without a long commitment [15]. Later in the post I show where a gateway would sit in front of the demo agent.
The bill you don’t see
The token invoice is the visible part. The full cost of an AI solution includes:
- Building and integrating it into existing systems
- Change management, so people actually use it
- Governance and controls: observability, security, evaluation, compliance
- People: the humans who still review what agents produce
- Upkeep: the ongoing maintenance that keeps prompts, tools and models current
On many projects these add up to more than the tokens, and they never show up as a line item. Model them up front, or the business case will look better on paper than in reality.
Finance teams increasingly ask how to account for tokens. A helpful lens is to split spend by purpose:
- Tokens that build a lasting capability behave like an investment.
- Tokens consumed to run internal workflows are an operating expense.
- Tokens embedded in a product your customers use belong in cost of goods sold, where they affect gross margin.
From a CFO’s point of view, I see four risks:
- Forecasts drift because consumption isn’t modeled.
- Margins leak quietly through AI inside products.
- Capacity decisions get made late and in a hurry.
- The story for the board is weak if nobody can show what the spend returned.
From cost to value
Token counts tell you what you spent. They don’t tell you what you got. So I prefer to track cost per outcome: everything it costs to produce one good business result, divided by the number of good results. In the experiment below, the outcome is “a correctly resolved claim”, and the cost includes tokens, tool calls, human review and the rework caused by wrong decisions.
Every function has an outcome like that, and it’s rarely the metric people report:

Two cautions from the value side:
- Saved time isn’t saved money until someone redeploys it. If an engineer saves half an hour and the team’s work doesn’t change, the margin doesn’t move.
- Adoption follows a J-curve. Productivity often dips while people learn the tools and spend extra time checking the output, before it climbs. Leaders who expect that dip are less likely to cut a program just before it pays off.
The Google Cloud post Why smart teams spend more on AI, makes a point: once teams can measure cost per outcome, they often spend more, because the risk has become quantifiable [3]. It also recommends keeping two separate budgets, one for running agents and one for improving them. That’s a simple habit that stops all the money going to upkeep.
A maturity path: See, Shape, Steer
I find it helpful to think in three stages:
- See. Every model call is labeled, the billing export lands in BigQuery, and you can name the agent, step and model behind any dollar. The signal to watch is the share of Gemini spend that carries labels.
- Shape. You understand why a task costs what it costs, and you change it with model tiering, context hygiene, caching and harness guards. Watch tokens per task, the cached-token ratio and the gap between the median and the 95th percentile.
- Steer. You manage by cost per outcome. You choose consumption options and commitments on evidence, and budgets and gateway quotas enforce your decisions. Watch cost per outcome and the share of it that’s actually tokens.
It also needs owners, not just tools:
- CTO/CIO: model and routing standards.
- CFO: unit margins.
- Business-unit leaders: the outcome metrics.
- Procurement: contracts that reward outcomes rather than volume.
Putting it to the test: a claims agent on Gemini Platform
Everything so far has been a framework. Frameworks are cheap, so I wanted to see what the levers are actually worth on a real workload.
Picture an insurer receiving thousands of claim e-mails a week. It wants an AI agent to read each one, check the policy and the customer’s history, and recommend approve, deny or escalate. The pilot works. Then finance asks the questions that decide whether it goes to production:
- What does one claim cost?
- Why does it cost that?
- What happens to quality if we make it cheaper?
So I built that agent and ran it five times, changing one design decision at a time. For every model call I recorded what the tokens were spent on, and for every claim I checked whether the decision was right. Everything runs on standard pay-as-you-go pricing, and every model is generally available.
Going in, I assumed trimming the 25 tool schemas and the verbose JSON outputs in R1 would deliver the biggest dollar drop. It cut the most tokens, but as the numbers below show, it wasn’t the biggest dollar saving.
About the data (it’s all synthetic)
I didn’t want customer data anywhere near this, and I wanted anyone to be able to reproduce the results, so every record is synthetic and generated with a fixed seed. Cymbal Insurance doesn’t exist. The dataset is big enough to behave like a real book of business:

The answer key is what makes this an experiment rather than a demo. A claim counts as correctly resolved only if the decision matches and the payout is within 1% of the expected amount.
The synthetic data also has limits, and I’d rather name them up front:
- Real e-mails are messier than generated ones.
- Real policy wordings contradict themselves; my handbook and answer key agree perfectly. Treat the accuracy numbers as closer to an upper bound.
- Token counts depend on the size of my handbook and tool payloads. I expect the shape of the bill of materials to carry over to your workload more than the exact numbers.
The setup: one script, everything else in the console
Everything in this experiment lives in the GitHub repo (link shared earler). You can use it in three ways:
- Read it. The README explains the five designs and what each BigQuery view answers. It’s useful even if you never run anything.
- Reproduce it. Clone it in Cloud Shell, set your project, and run one script. The RUNBOOK walks through every Cloud Console step with screenshots, from enabling the API to building the charts.
- Reuse it. Copy the usage-logging and allocation functions from run_experiment.py into your own agent, upload your rows with the same schemas, and the SQL views work on your data unchanged.
git clone https://github.com/Rajdipc/tokenomics-paygo-demo.git
cd tokenomics-paygo-demo && pip install -r requirements.txt
cp .env.example .env # set GOOGLE_CLOUD_PROJECT, then: source .env
python run_experiment.py --runs R0 R5 --n 10 # a small, cheap first run
The codebase in cymbal_claims_agent/ packages both the experiment harness (run_experiment.py) and a deployable Google ADK 2.x agent (root_agent and app). It calls Gemini on Gemini Platform through the Google Gen AI SDK and Google ADK. You can run the entire R0 to R5 benchmark directly from Cloud Shell without deploying infrastructure, and then deploy the winning R5 agent to Cloud Run or Gemini Platform Agent Runtime using the scripts in deploy/. Everything else (BigQuery, Cloud Billing, Cloud Monitoring, Cloud Trace) is set up and inspected in the Cloud Console.

Before running anything, I set two guardrails. Budgets warn rather than cap, so the script also stops itself at a spend limit.


Every request carries labels, which Cloud Billing receives for PayGo traffic [6]:
config = types.GenerateContentConfig(
system_instruction=system, tools=tools,
automatic_function_calling=types.AutomaticFunctionCallingConfig(disable=True),
thinking_config=types.ThinkingConfig(thinking_level="MEDIUM"),
labels={"app": "cymbal-claims", "run": "r5", "step": "adjudicate", "tier": "flash"},
)
response = client.models.generate_content(model="gemini-3.8-flash", contents=contents, config=config)
usage = response.usage_metadata # prompt, cached, thinking and output tokens, as billed
One practical tip: a label key can hold at most 1,000 unique values. Label by run, feature or step, never by claim or user ID.
How the bill of materials is measured
The totals come straight from the API: every response reports prompt tokens, cached tokens, thinking tokens and output tokens. The split is my addition. Because the script assembles each request itself, it knows how much of the prompt was:
- system instructions
- the handbook
- tool schemas
- conversation history
- tool results
- the claim itself
It allocates the billed prompt tokens across those parts in proportion to their size, so the parts always add up to exactly what Gemini billed. The total is a measurement; the split is an engineering estimate. That’s the same deal as a manufacturer’s bill of materials.
Five designs, one agent
The models are all GA:

Regular list prices from the pricing page as of 15 October 2026 [4]. Until 30 November 2026 (Argon) and 31 December 2026 (3.8 Flash), the page shows promotional prices delivered as 50% credits back, so your net bill can be roughly half. More on that in the attribution section.
R0: the prototype everyone builds first
My baseline is what a capable team ships in its first week, and I don’t think it’s a straw man:
- One Gemini 4 Argon agent does everything, with high thinking.
- It’s “helpfully” given 25 tools, 22 of them irrelevant to the decision.
- Tools return the full JSON record from the policy system.
- The handbook is pasted after every claim.
- Three claims share one chat to save setup.
- The prompt asks for detailed justifications.
It works. It cost $0.220 per claim and 150,796 tokens, with 100% accuracy.

Two line items made up almost all of R0’s bill of materials: re-read conversation history (48% of tokens) and the handbook (42%). The claim itself, the only part that changes from one claim to the next, was 0.3%. What surprised me was caching. 80% of R0’s input tokens were billed at the cached rate without my doing anything, because Gemini 4 Argon’s implicit caching recognized the repeated handbook and history. At full input price, the same 50 claims would have cost about $33.38 instead of $10.98. The prototype was being rescued by the platform, and I hadn’t noticed.
R1: trim what goes into each call
Same model, same thinking level. The changes:
- 3 tools instead of 25, scoped via a skill (skills/cymbal-claims-adjudication/SKILL.md). Every tool declaration is re-sent on every call, so unused tools are a tax on each turn. Scoping the agent to the 3 adjudication tools (get_policy, get_claims_history, screen_fraud) mirrors the "use skills from the beginning" principle in the Eleven Principles post [2].
- Compact tool results, plus deterministic ID normalization (003009 → POL-003009). The policy lookup now returns a one-row table with the nine fields the rules use instead of twelve months of billing history and an audit trail.
- A fresh session per claim. In R0, the third claim in a chat re-read the first two claims, their tool results and two extra copies of the handbook. The Eleven Principles post recommends starting a new session for each new topic [2], and the bill of materials shows why.
- Short answers. Forty words of justification instead of 150.
Result: 59,091 tokens and $0.136 per claim (-38% versus R0), at 100% accuracy. Tokens fell by more than half, though dollar cost fell by less than that because much of the multi-turn history I removed in R0 had been billed at Argon’s implicit cached rate anyway.
One detail from building R1 is worth calling out, because it shows why deterministic code and AGENTS.md rules matter. In my first test pass of R1, accuracy dropped from 100% (50/50) to 98% (49/50) on a single claim (CLM-000023) where a customer casually wrote "policy no. 003009" instead of "POL-003009". With R0's verbose prompt, the model inferred the POL- prefix; once I trimmed the prompt in R1, the model passed "003009" literally and denied a valid claim as POLICY_NOT_FOUND. Following Principle 9 of the Eleven Principles post [2] ("treat failures as signals to refine persistent rules or deterministic scripts"), I added four lines of deterministic ID normalization inside Tools.norm_policy_id() and documented the rule in AGENTS.md. Accuracy immediately returned to 100% across R1, R2, R3 and R5, at zero extra token cost.
R2: give each job the right model
The claim actually involves three jobs of very different difficulty:
- Triage: pull out the policy number, dates, type of loss and amount. Gemini 3.5 Flash-Lite with minimal thinking and a JSON schema.
- Adjudication: call the tools and apply the rules. Gemini 3.8 Flash with medium thinking. This mirrors the Eleven Principles advice to start with a balanced model and scale up only when needed [2].
- Senior review: Gemini 4 Argon, called only when Flash reports confidence below 0.8. It sees the gathered facts and the draft decision, not the whole conversation.
Argon reviewed 0% of claims. Cost per claim fell to $0.060 (-56% versus R1) at 100% accuracy.
That review rate isn’t a typo. Gemini 3.8 Flash reported a confidence of 1.0 on all 50 claims, so the senior review never triggered. All of R2’s saving came from moving the work to cheaper models, not from the cascade. Self-reported confidence was useless as a routing signal here. In a real system I’d route on something observable instead, such as claim complexity, claim amount, or disagreement between two cheap passes.
R3: stop paying full price for the same handbook
After R2, the biggest line item is the handbook, re-read on every adjudication call. Context caching bills reused input at a fraction of the normal rate. It works differently on my two models:
- Gemini 3.8 Flash supports explicit caching. I put the instructions, the handbook and the tool schemas into a cache once, and every adjudication call references it. You pay to write the cache at the normal input rate, plus storage for each hour it lives.
- Gemini 4 Argon supports implicit caching only, with durable caching on by default and a minimum of 6,144 tokens [11]. There’s nothing to create. The job is to put the static part of the prompt first, so consecutive reviews share a long identical prefix that the platform can reuse.
cache = client.caches.create(
model="gemini-3.8-flash",
config=types.CreateCachedContentConfig(
system_instruction=OPTIMIZED_SYSTEM,
contents=[types.Content(role="user", parts=[types.Part(text=handbook)])],
tools=tools, ttl="3600s", display_name="tbom-r3-adjudicate"),
)
config = types.GenerateContentConfig(cached_content=cache.name, labels=labels,
thinking_config=types.ThinkingConfig(thinking_level="MEDIUM"))
When does an explicit cache pay for itself? Per cached token, storage costs s per hour, and each read saves (input price − cached price). Break-even is s ÷ (input − cached) reads per hour. For Gemini 3.8 Flash that’s $1.00 ÷ ($1.50 − $0.15), roughly 0.7 reads an hour [4]. Anything busier than that comes out ahead.
One governance note: caching keeps data for a while. If you have data-retention requirements, the zero-data-retention guidance explains how to control or disable it [8].
Result: 97% of input tokens came from cache, and cost per claim was $0.023 (-61% versus R2), including cache writes and storage, at 100% accuracy.
R4: creating a failure scenario to test loop guards and token-burn alerts
The usual story is that cost blow-ups in agents don’t come from one big prompt; they come from retry loops when a downstream dependency misbehaves. Rather than taking that on faith, I created a controlled failure scenario starting from R3: I injected a deterministic upstream timeout (UNAVAILABLE: UPSTREAM_TIMEOUT) into screen_fraud for every fifth claim (8 faulty claims out of 40, or 20% of traffic).
I then ran those 40 claims twice: once without loop guards (R4U), where the system prompt also carried a well-meaning instruction ("Always obtain a successful fraud screening result before you submit a decision"), and once with harness loop guards and an aligned fallback (R4G):
- Without guards (R4U): faulty claims averaged 14.2 model calls (worst case 15) and $0.082 each, about 3.5× the normal claim cost, at 38% accuracy on the faulty slice (87.5% overall, pushing Cost per Outcome to $6.04). Looking at the eight faulty rows in claims.jsonl shows how badly an unguarded loop degrades: four claims (CLM-000015, CLM-000025, CLM-000030, CLM-000040) spun until the 15-call safety ceiling (SAFETY_CAP_REACHED) killed them without a decision; one (CLM-000020, a $10,005 home claim) retried screen_fraud ten times and then hallucinated an unscreened APPROVE instead of escalating; and the remaining three burned 13 to 14 calls retrying a dead service before finally denying or escalating.
- With guards (R4G): I enforced a per-tool circuit breaker of retry_budget=1 (on the second timeout, the tool returns "do not call screen_fraud again; apply handbook Section 2 in order: if steps 1-5 do not deny the claim, use step 6 (SCREENING_UNAVAILABLE)"), capped adjudication calls at max_calls=8, and removed the contradictory prompt line. Faulty claims settled in 4.6 model calls (worst case 6) and cost $0.027 each, cutting faulty-claim spend by 67% versus R4U while achieving 100% accuracy across all 40 claims.
One lesson from testing R4G surprised me and became Rule #4 in AGENTS.md: never let a prompt contradict a loop guard. In an earlier test where I turned on the retry_budget=1 circuit breaker in code without removing the prompt line that demanded a screening score, the model stopped calling the tool after two tries, but spent up to 34,203 thinking tokens ($0.26 on a single call) agonizing over the contradiction between the prompt and the tool error. Loop guards belong in the harness [2], and the prompt has to let the model take the fallback path when the guard trips.
The Cloud Monitoring token-burn rate alert (configured to email id) also caught the R4U failure scenario. During the healthy R5 run, the 1-minute token rate peaked at 645,546 tokens per minute, so I set the alert threshold at 750,000 tokens per minute (~1.2× the healthy R5 peak). When R4U hit the 20% upstream timeout without loop guards, the 15-call retry loops drove the project-wide rate above the threshold for four consecutive minutes (753,318, 801,447, 822,887, and a peak of 905,391 tokens per minute), firing the alert to the email id. When R4G ran immediately afterward with the circuit breaker, the token rate peaked at 726,753 tokens per minute and stayed below the 750,000 threshold. That shows how the two layers work together: per-claim circuit breakers in the harness stop a single looping request in two turns, and a Cloud Monitoring rate alert pages you when an upstream outage causes a fleet spike.

R5: the version I’d ship (and how to deploy it with Google ADK)
R5 is R3 plus the guards. On healthy dependencies the guards never fire, so they cost nothing. Each claim shows up in Cloud Trace with token counts and cost on every model-call span [17], and the model observability dashboard on Gemini Platform shows token throughput by model [16].
To make R5 ready for production deployment rather than just a benchmark script, cymbal_claims_agent/agent.py defines it as a Google ADK 2.x Workflow backed by TBOMLedgerPlugin:
from google.adk.agents import LlmAgent, Workflow
from google.adk.apps import App
root_agent = Workflow(
name="cymbal_claims_agent",
description="Cymbal Insurance TBOM-optimized claims adjudication pipeline (R5).",
sub_agents=[
create_triage_agent(), # gemini-3.5-flash-lite + MINIMAL thinking + JSON schema
create_adjudicator_agent(), # gemini-3.8-flash + static-first SKILL.md & handbook + 4 tools
],
)
app = App(
name="cymbal_claims_agent",
root_agent=root_agent,
plugins=[TBOMLedgerPlugin(run_id="R5")], # attaches Cloud Billing labels & records 6-item TBOM
)
In cymbal_claims_agent/tbom.py, TBOMLedgerPlugin hooks into ADK's before_model_callback and after_model_callback. Before each model turn, it injects the low-cardinality Cloud Billing labels (app=cymbal-claims, experiment=tbom, run=r5, step=triage|adjudicator, tier=flash-lite|flash) into llm_request.config.labels and sizes the six prompt components. After each turn, it reads llm_response.usage_metadata (including cached_content_token_count and thoughts_token_count), computes list-price USD cost, and appends an itemized TBOM receipt to session.state["tbom_calls"].
The deploy/ directory ships scripts for both Google Cloud deployment targets, using a least-privilege service account (roles/aiplatform.user, roles/cloudtrace.agent, roles/monitoring.metricWriter, roles/logging.logWriter):
- Option A: Cloud Run (deploy/03_deploy_cloud_run.sh). Builds the container via Cloud Build and deploys cymbal_claims_agent/fast_api_app.py to Cloud Run (–min-instances=0 –max-instances=4), exposing GET /api/health, POST /api/adjudicate (which returns the decision, accuracy check, and itemized TBOM receipt), and the ADK web UI.
- Option B: Gemini Platform Agent Runtime (deploy/04_deploy_agent_runtime.py). Packages root_agent and cymbal_claims_agent/ into a managed ReasoningEngine on Gemini Platform (vertexai.agent_engines.create), with managed session state and streaming queries.
- Smoke test and teardown (deploy/05_test_deployed_agent.py and deploy/99_destroy.sh). Sends claim CLM-000001 to either Cloud Run or Agent Runtime, verifies the $86,176.66 ESCALATE (ABOVE_AUTHORITY) decision and the 5-call TBOM receipt (52,245 cached tokens on gemini-3.8-flash), and tears down all deployed resources when you are done.


The results
To analyze the results I loaded the three result files into BigQuery, then pasted the SQL views from the repo into BigQuery Studio. Every chart below comes from the query results’ Visualization tab [19].





Each move saved money in a different way. R1 cut the most tokens: more than half of them, mostly re-read history. But R2 and R3 made the biggest percentage cuts to the bill, without changing the token count at all. R2 moved the same tokens to cheaper models, and R3 moved them to the cached rate. That’s the pattern I’d look for in any agent: count tokens to find the waste, but price them to find the savings. The tail closed as well. In R0 the 95th-percentile claim used 1.6× the median’s tokens; in R5 it used 1.0×, so a budget built on R5 can be close to the average. The R4 runs show how fast that changes: with the flaky dependency, the ratio jumped to 4.7×.
Choosing how to pay for the tokens
Everything above ran on Standard PayGo. Gemini Platform has more ways to consume the same models. I didn’t run them; instead I re-priced the exact tokens I measured with public list prices. That tells you the price of each option, not how it behaves under load.

The Flex change really is one client setting:
flex_client = genai.Client(
vertexai=True, project=PROJECT, location="global",
http_options=types.HttpOptions(api_version="v1", timeout=600_000, headers={
"X-Vertex-AI-LLM-Request-Type": "shared", # use only Flex, skip any PT
"X-Vertex-AI-LLM-Shared-Request-Type": "flex"}))

When should you commit? Provisioned Throughput only pays if you use what you reserve. I didn’t used any. Instead I ran a sizing what-if in BigQuery: take R5’s tokens per claim, imagine 40,000 claims on a weekday with a business-hours peak and quiet weekends, and ask how much traffic a reservation would cover at different sizes.

From sql/09_pt_what_if.sql. It's a sizing model, not a price quote.
Sizing for the peak buys certainty, but only 44% of that reservation does useful work over a week. Google’s own guidance agrees that you generally don’t need to provision for peak demand [5]. The lesson I take: commit to a token volume you’ve already minimized, not the prototype’s.

From tokens to cost per outcome
Tokens aren’t what the insurer is buying; correctly resolved claims are. So the last view adds everything else it takes to get one claim right: tool calls, human review of escalations, and rework when the agent is wrong. The unit costs are assumptions for a fictional insurer ($0.0004 per internal API call, $12 per human review, $18 per rework), and they sit in one small table you can edit (sql/00_reference_tables.sql).

Across the waterfall, Cost per Outcome came down from $2.86 per correctly resolved claim in R0 to $2.66 in R5, while keeping 100% accuracy (50 out of 50 claims right, zero rework). Two things in that chart stood out to me:
- Tokens dropped from 7.7% of total outcome cost in R0 ($0.220 of $2.86) to 0.9% in R5 ($0.023 of $2.66). Once the token bill is down to 2.3 cents, over 99% of the remaining $2.66 Cost per Outcome is the $2.64 per claim spent on human review of the eleven legitimate escalations (11 × $12 ÷ 50).
- Quality dominates token price. In my first test pass before I added Tools.norm_policy_id(), that one un-normalized policy number ("policy no. 003009") caused a single wrong decision (49/50, or 98% accuracy). The $18 human rework penalty added $0.37 per correct claim, nearly twice R0's entire $0.22 token bill, and temporarily pushed R5's Cost per Outcome up to $2.92 even after an 89% token cut. Adding four lines of ID normalization in the tool brought Cost per Outcome right down to $2.66.
This is the strongest argument I know for reporting Cost per Outcome next to Cost per Token. Cutting the model bill by 89% is real money at production scale. Once you reach R5, though, the next dollar of engineering effort shouldn’t go into shaving another tenth of a cent off the prompt. It should go into better triage and upstream data hygiene that safely reduce the $2.64 human escalation load and prevent $18 rework events. Your ratio will differ, which is why computing v_cpo_by_run on your own workload is worth doing.
Checking the estimate against the invoice
My script’s cost figures are estimates at list price. Cloud Billing is the truth. The detailed billing export in BigQuery, broken down by the labels on each request, shows what was really charged [7].


Two things to expect in that table:
- Promotional credits. While the promotions run, you’ll see the gross cost and a matching credit, so net cost is about half of my estimate.
- Cache storage. Explicit-cache storage has no request label, so it appears as its own SKU. The v_estimate_vs_invoice view lines up the estimate and the invoice, so neither surprises you.
Going further: put a gateway in front
Everything in this experiment controls cost from inside one application. At fleet scale I’d add Apigee in front of Gemini, as described earlier:
- LLMTokenQuota: a token budget per consuming app [12]
- PromptTokenLimit: protection against prompt bursts [13]
- Semantic caching: for traffic that genuinely repeats [14]
- Analytics: per-consumer usage for chargeback
For this demo the pattern would be to create an Apigee organization (evaluation or pay-as-you-go [15]), deploy a proxy in front of the Gemini endpoint with LLMTokenQuota attached, and send R5’s traffic through the proxy. When the quota runs out, the gateway, not the agent, refuses the call. I haven’t run that step in this post, because it means deploying a gateway. The outline is in step 11 of the RUNBOOK.
What I’d do differently
- I’d run each configuration more than once. Model outputs vary, and 50 claims per run is enough to see big effects but not small ones.
- I’d add a design between R1 and R2 that retrieves only the handbook sections a claim needs. For rarely reused reference material, retrieval can beat caching. For a handbook read on every call, caching wins.
- I’d log tool arguments, not just tool names, from day one. Catching the "003009" → "POL-003009" normalization issue took inspecting the raw claim text; logging tool arguments makes input-format mismatches trivial to spot in BigQuery.
- I’d route the senior review on an observable signal from the start. A confidence score the model gives itself never dropped below 1.0.
- I’d audit every system prompt against every tool error message before shipping (AGENTS.md Rule #4). A circuit breaker in code only saves tokens if the prompt allows the model to take the fallback path without burning thinking tokens on a contradiction.
- I’d make the fraud score an active threshold rule in the handbook rather than an advisory check on healthy runs, so the answer key tests both fraud-score escalations and upstream timeouts.
Conclusion: make the bill explainable, then make it smaller
The organizations that pull ahead with AI won’t be the ones with the smallest bill. They’ll be the ones that can explain theirs: which agent spent what, on which step, for which outcome, and what changes if you move a lever. Once a bill can be explained, the conversation stops being about whether you can afford AI and becomes a question of where to put the next dollar.
The experiment made that concrete for me. I didn’t get the agent’s cost down by tuning prompts on instinct. I got there by writing down what every token was for. Once the bill of materials was visible, the decisions were straightforward:
- remove the freight (and scope tools & domain workflows via SKILL.md and AGENTS.md)
- give each job the right model
- stop paying full price for the same handbook
- put hard stops on loops, and align prompt fallbacks with those guards
- measure cost per correct claim instead of cost per token
The last one turned out to be the most important. The token bill fell by 89% ($0.220 to $0.023 per claim) and Cost per Outcome came down from $2.86 to $2.66 at 100% accuracy. Yet as my first un-normalized test pass showed, a single avoidable mistake ($18 rework) can wipe out every cent of token savings if you don’t protect accuracy alongside price. Cheaper only counts when it’s still right.
None of these moves needed a reservation, a preview model or a new platform. All of it ran on pay-as-you-go, on GA models.
If you lead a team, the takeaway is this: an AI bill you can explain is one you can grow with confidence. If you build agents, the takeaway is this: your agent has a bill of materials whether you write it down or not. Writing it down is the cheapest optimization you’ll make.
What to do next
- Label every Gemini call with low-cardinality keys: app, team, feature, step, model tier. Labels reach Cloud Billing for PayGo traffic [6].
- Turn on the detailed Cloud Billing export to BigQuery and one token-burn alert this week, before you optimize anything [7][18].
- Write the Token Bill of Materials for one agent. Log usage_metadata for every call and split the prompt into instructions, documents, tool schemas, history, tool results and user input. One afternoon is enough to find your biggest line item.
- Pick one outcome metric for that agent, and report cost per outcome next to accuracy at your next review.
- Run the experiment and deploy the agent yourself. Clone github.com/Rajdipc/tokenomics-paygo-demo, start small with python run_experiment.py –runs R0 R5 –n 10, deploy the production ADK agent in cymbal_claims_agent/ to Cloud Run (bash deploy/03_deploy_cloud_run.sh) or Gemini Platform Agent Runtime (python deploy/04_deploy_agent_runtime.py), and follow the RUNBOOK for every console step. The script stops itself at –max-usd, and bash deploy/99_destroy.sh tears down all resources when you finish. If you adapt it to your own agent, open an issue or a pull request with what you learned.
- Share what you find. Tell me in the comments which line item surprised you most. If you’d like help running an AI tokenomics assessment for your organization, talk to your Google Cloud team.
Bibliography
- AI Agents Forecast to Boost Tech Cash Flow as Usage Soars
- Guide to AI Tokenomics: Eleven Principles for Token Efficient Software Engineering
- Tokenomics: Why smart teams spend more on AI, on purpose
- Generative AI pricing on Gemini Platform
- Google Cloud Consumption options — Standard PayGo, Flex PayGo and Priority PayGo
- Monitor cost using custom metadata labels
- Export Cloud Billing data to BigQuery
- Context caching overview and Zero data retention
- Create a batch job from BigQuery
- Flexible Savings Plans
- Model cards: Gemini 4 Argon, Gemini 3.8 Flash, Gemini 3.5 Flash-Lite
- Apigee LLMTokenQuota policy
- Apigee PromptTokenLimit policy
- Apigee SemanticCacheLookup policy
- Apigee pricing
- Model observability
- Find and explore traces
- Alerting overview and Create, edit, or delete budgets and budget alerts
- Run a query (Visualization tab) and Analyze with BigQuery data canvas
The Token Bill of Materials: A Measured Guide to AI Tokenomics on Google Cloud was originally published in Google Cloud – Community on Medium, where people are continuing the conversation by highlighting and responding to this story.
Source Credit: https://medium.com/google-cloud/the-token-bill-of-materials-a-measured-guide-to-ai-tokenomics-on-google-cloud-81f6203fcbbc?source=rss—-e52cf94d98af—4
