🧭 How toAIIntermediate✨ AI-assisted

How to Budget 1M Output Tokens on Gemini 4 Argon

WittyTech Daily··5 min read
#gemini 4 argon#token budget#cost control#streaming

Argon lifts the output limit from 64K to 1M tokens, so one reply that never stops can cost $10 to $20. This guide builds a worst-case cost function, a dollar-based cap on Gemini 4 Argon output tokens, and a streaming guard that stops a runaway response.

One caveat first. Google announced Argon on September 30, 2026, but access is limited to trusted cyber defenders through the Fairwind Program. There is no public model ID, and Argon is not on the Gemini API pricing page yet. So the snippets use <argon-model-id>, no Argon-specific parameters, and only documented Gemini API options. You can test the guard today on any model you can call.

1. Turn the published Argon rates into a worst-case cost per call

The announcement lists intro rates of $2 per million input tokens and $10 per million output tokens, rising to $4 and $20 later (no end date given). Cached input is 95% off the input price. So 1M output tokens costs $10 at intro rates and $20 at standard rates.

from dataclasses import dataclass

@dataclass(frozen=True)
class Rates:
    input_per_m: float             # USD per 1M input tokens
    output_per_m: float            # USD per 1M output tokens (assumed to include thinking)
    cached_discount: float = 0.95  # cached input is 95% off the input price

ARGON_INTRO = Rates(input_per_m=2.0, output_per_m=10.0)
ARGON_STANDARD = Rates(input_per_m=4.0, output_per_m=20.0)

def worst_case_usd(rates, input_tokens, max_output_tokens, cached_tokens=0):
    fresh = input_tokens - cached_tokens
    cached_rate = rates.input_per_m * (1 - rates.cached_discount)
    input_cost = (fresh * rates.input_per_m + cached_tokens * cached_rate) / 1_000_000
    return input_cost + max_output_tokens * rates.output_per_m / 1_000_000

With a 50,000-token prompt and a 1M output cap, this returns $10.10 at intro rates and $20.20 at standard. Caching 45,000 of those input tokens only brings the standard figure to about $20.03: caching trims the bill, not the ceiling. I assume the 95% discount applies to whichever input rate is active. Cache storage fees are unpublished for Argon and left out.

2. Cap Gemini 4 Argon output tokens from a dollar budget

Pick what one call may cost, subtract the input cost, and convert the rest into tokens.

def max_output_for_budget(rates, budget_usd, input_tokens, cached_tokens=0, hard_cap=1_000_000):
    remaining = budget_usd - worst_case_usd(rates, input_tokens, 0, cached_tokens)
    if remaining <= 0:
        raise ValueError("Input alone exceeds the budget")
    return min(hard_cap, int(remaining * 1_000_000 / rates.output_per_m + 1e-6))

At standard rates, $0.50 per call with a 50,000-token prompt allows 15,000 output tokens. At intro rates it allows 40,000. The 1e-6 absorbs float rounding. Pass the result as max_output_tokens inside generation_config.

Budget for thinking too. The pricing page lists output prices as including thinking tokens for the models it covers, and the announcement is silent on Argon, so assume thinking bills as output. A Google moderator says on the developer forum that max_output_tokens caps thinking plus response tokens combined, yet a user in that thread reported totals near double the limit. Don't trust the cap alone.

3. Stream the response and stop at a client-side limit

A response that can reach 1M tokens should stream, so you can show partial output and cut it off. This uses the Interactions API, which the current streaming docs show.

from google import genai

client = genai.Client()
MODEL = "<argon-model-id>"  # placeholder: Google has not published one yet
RATES = ARGON_STANDARD      # plan on the higher rate

def run_guarded(prompt: str, budget_usd: float) -> tuple[str, float]:
    input_tokens = client.models.count_tokens(model=MODEL, contents=prompt).total_tokens
    cap = max_output_for_budget(RATES, budget_usd, input_tokens)

    stream = client.interactions.create(
        model=MODEL,
        input=prompt,
        stream=True,
        generation_config={"max_output_tokens": cap},
    )

    parts, est_tokens, usage = [], 0.0, None
    for event in stream:
        if event.event_type == "step.delta" and event.delta.type == "text":
            parts.append(event.delta.text)
            est_tokens += len(event.delta.text) / 4  # about 4 characters per token
            if est_tokens > cap:
                break  # the server ignored the cap: stop reading
        elif event.event_type == "interaction.completed":
            usage = event.interaction.usage

    text = "".join(parts)
    if usage is None:  # cut early or never completed: assume the worst
        return text, worst_case_usd(RATES, input_tokens, cap)
    billed_output = (usage.total_output_tokens or 0) + (usage.total_thought_tokens or 0)
    cost = ((usage.total_input_tokens or 0) * RATES.input_per_m
            + billed_output * RATES.output_per_m) / 1_000_000
    return text, cost

The loop estimates tokens from visible text at about 4 characters per token, Google's rule of thumb. Thought tokens never appear in the text stream, so this undercounts: it is a tripwire for a server that ignores your cap, not an accountant. The real numbers arrive in usage on the interaction.completed event. The cost line sums output and thought tokens and prices all input at full rate, so it is an upper bound. Google's docs don't say whether disconnecting stops billing, so an early break assumes the worst case.

4. Add a daily ceiling so many small calls can't add up

class DailyBudget:
    def __init__(self, limit_usd: float):
        self.limit_usd = limit_usd
        self.spent_usd = 0.0

    def check(self, worst_case: float) -> None:
        if self.spent_usd + worst_case > self.limit_usd:
            raise RuntimeError(
                f"Budget guard: ${self.spent_usd:.2f} spent, next call could add ${worst_case:.2f}"
            )

    def record(self, cost_usd: float) -> None:
        self.spent_usd += cost_usd

daily = DailyBudget(limit_usd=50.0)
daily.check(worst_case=0.50)  # the per-call budget from step 2
text, cost = run_guarded(prompt, budget_usd=0.50)
daily.record(cost)

Check the worst case before each call and record the actual cost after. This one lives in memory. With several workers, keep the total in Redis or your database.

Gotchas

  • No model ID yet. Don't guess one from the product name. The code fails until Google publishes it.
  • Access is Fairwind only. Google says broader access starts with paid API customers and Google AI Ultra subscribers, with no date.
  • Intro pricing has no published end date. Keep rates in one object so a change is a one-line edit.
  • Context window and cache storage pricing aren't in the announcement. Call count_tokens before sending, and reconcile your ledger against your first invoice.

A 1M-token output limit turns a prompt bug into a $20 line item, so set the ceiling before access opens, not after the invoice arrives.

← More in AI