DEV Community

Mattias chaw
Mattias chaw

Posted on

Build a Context-Window Budget Profiler for AI Agents

Build a Context-Window Budget Profiler for AI Agents

Long-context agents fail quietly before they fail loudly. A coding agent may keep adding repository files. A support agent may keep attaching customer history. A research agent may keep carrying old notes forward because nobody defined when context should be summarized, cached, trimmed, or sent to a different model.

The result is not only a bigger bill. It is also a routing problem. A request that looked like a small DeepSeek V4 Flash execution step can become a long-context planning step. A Qwen coding prompt can cross a context tier. A Kimi request can become attractive for repeated large context, but expensive if the output is loose. A GLM reasoning call can be worth the spend for a short decision and still be wrong for bulk extraction.

This article shows how to build a context-window budget profiler before the request leaves your gateway. The goal is not to pick one model forever. The goal is to classify the request, estimate the cost surface, choose a route, and log the decision with enough detail that engineering, finance, and support can explain what happened later.

All pricing below was checked on August 21, 2026. AIWave's public pricing pages currently list DeepSeek V4 Flash at $0.638 input, $1.914 output, and $0.0203 cache-hit input per 1M tokens; DeepSeek V4 Pro at $1.914 input, $5.742 output, and $0.0638 cache-hit input per 1M tokens. AIWave's predictable-pricing page keeps those all-day AIWave rows separate from official DeepSeek peak and off-peak rows. Official DeepSeek rows on that page are lower than AIWave's all-day rows, so the value claim should be operational simplicity, unified billing, and multi-model routing, not a universal price-floor claim.

Why Context Needs Its Own Gate

Most teams already have a rate limit. Some have a per-tenant daily budget. Fewer have a context profiler. That missing layer matters because long-context usage changes the economics before the request runs.

A 2,000-token prompt with a 600-token answer is easy to reason about. A 95,000-token prompt with a 4,000-token answer is different. The second request is more sensitive to cache-hit behavior, context-tier rules, output caps, fallback policy, and retry behavior. If it fails and retries twice, the bill impact and latency impact can be much larger than a normal chat completion.

The profiler should run before dispatch and answer five questions:

Question Why it matters Example control
How many input tokens are fresh? Fresh input usually costs more than cached input. Require summarization above a threshold.
How many tokens are expected from cache? Repeated repository or policy context can change effective cost. Track cached_input_tokens separately.
What output cap is allowed? Output can dominate cost for reasoning-heavy models. Cap by task class, not by user prompt.
Which context tier applies? Some providers vary behavior or billing by context length. Route large contexts to approved model families only.
What fallback is allowed? Fallback can hide route drift and surprise bills. Store fallback_reason and policy version.

This is especially useful for Tier 1 and Tier 2 SaaS teams serving US, UK, Germany, Japan, Singapore, and similar markets. Those teams are usually less interested in a one-off prompt price and more interested in whether a product feature can keep a predictable unit cost across many tenants.

Pricing Surfaces to Track

A context profiler should not store a vague "model price." It should store a rate-card snapshot with a source date and separate fields for input, cached input, output, and special context rules.

For example, as of August 21, 2026:

Model family Public pricing surface to model Why the profiler cares
DeepSeek V4 on AIWave AIWave V4 Flash: $0.638 input, $1.914 output, $0.0203 cache-hit input per 1M tokens. AIWave V4 Pro: $1.914, $5.742, $0.0638. Good for unified OpenAI-compatible routing and all-day planning, with explicit source-date logging.
DeepSeek official Peak and off-peak rows should be modeled separately from AIWave all-day rows. Teams comparing direct official access need timezone and traffic-mix math.
QwenCloud QwenCloud documents pay-as-you-go billing, context caching, context-window behavior, failed-call billing behavior, Batch API discounts, and tool fees. Large coding prompts need context-tier and tool-cost fields, not only input/output rates.
Z.AI GLM Z.AI currently lists GLM-5.2 and GLM-5.1 at $1.40 input, $0.26 cached input, and $4.40 output per 1M tokens. Reasoning routes need output caps and cache visibility.
Kimi K3 Kimi K3 public material lists a 1M-token context window with $0.30 cache-hit input, $3.00 cache-miss input, and $15.00 output per 1M tokens. Long-context tasks can work well when repeated context is cached and output is controlled.

Do not let these rows collapse into one number. A routing decision based on 20,000 fresh input tokens is not the same as one based on 20,000 mostly cached tokens. A model with a large context window is not automatically the right route if the expected answer is huge. A model with a strong reasoning profile may be worth it for a short plan and wrong for repeated extraction.

A Route Contract for Long Context

The profiler should produce a route contract before the model call. The contract can be stored in request metadata and copied into your usage ledger after completion.

Here is a compact contract shape:

{
  "policy_version": "context-budget-2026-08-21",
  "source_date": "2026-08-21",
  "tenant_id": "acct_481",
  "task_kind": "coding_agent_patch",
  "requested_model_family": "deepseek",
  "selected_model": "deepseek-v4-flash",
  "estimated_input_tokens": 42000,
  "estimated_cached_input_tokens": 31000,
  "max_output_tokens": 1400,
  "context_band": "medium",
  "fallback_allowed": true,
  "fallback_model": "qwen3-coder-plus",
  "fallback_reason": "capacity_or_schema_retry"
}
Enter fullscreen mode Exit fullscreen mode

This object is intentionally boring. That is the point. Boring route metadata is easy to diff, search, and explain. If a customer asks why their coding-agent bill changed after a release, you can compare policy versions and context bands rather than guessing from raw prompts.

The contract also keeps prompt design honest. A prompt can ask for a detailed plan, but the gateway still owns the output cap. A prompt can attach a large repository tree, but the profiler can summarize or reject it before dispatch. A model can fail with a retryable error, but the route contract defines whether fallback is allowed.

Python Profiler Example

The following Python example uses an OpenAI-compatible client with AIWave's endpoint. It estimates cost using a dated AIWave DeepSeek row, selects a route by task kind and context band, and returns metadata that can be written to a ledger.

import os
from dataclasses import dataclass, asdict
from openai import OpenAI

client = OpenAI(
    api_key=os.environ.get("AIWAVE_API_KEY", "YOUR_API_KEY_HERE"),
    base_url="https://aiwave.live/v1",
)

@dataclass(frozen=True)
class PriceRow:
    model: str
    input_per_m: float
    output_per_m: float
    cache_hit_per_m: float
    source_date: str

@dataclass(frozen=True)
class RouteDecision:
    model: str
    max_output_tokens: int
    context_band: str
    estimated_usd: float
    policy_version: str
    source_date: str
    reason: str

AIWAVE_FLASH = PriceRow(
    model="deepseek-v4-flash",
    input_per_m=0.638,
    output_per_m=1.914,
    cache_hit_per_m=0.0203,
    source_date="2026-08-21",
)

AIWAVE_PRO = PriceRow(
    model="deepseek-v4-pro",
    input_per_m=1.914,
    output_per_m=5.742,
    cache_hit_per_m=0.0638,
    source_date="2026-08-21",
)

def rough_tokens(text: str) -> int:
    return max(1, len(text) // 4)

def estimate(row: PriceRow, input_tokens: int, cached_tokens: int, output_cap: int) -> float:
    fresh_input = max(input_tokens - cached_tokens, 0)
    return (
        fresh_input / 1_000_000 * row.input_per_m
        + cached_tokens / 1_000_000 * row.cache_hit_per_m
        + output_cap / 1_000_000 * row.output_per_m
    )

def band(input_tokens: int) -> str:
    if input_tokens < 8_000:
        return "small"
    if input_tokens < 64_000:
        return "medium"
    return "large"

def choose_route(task_kind: str, prompt: str, cached_tokens: int = 0) -> RouteDecision:
    input_tokens = rough_tokens(prompt)
    context_band = band(input_tokens)

    if task_kind in {"architecture_review", "release_blocker"} and context_band != "large":
        row = AIWAVE_PRO
        output_cap = 2200
        reason = "high_value_reasoning"
    else:
        row = AIWAVE_FLASH
        output_cap = 1400 if context_band != "large" else 900
        reason = "bounded_execution"

    return RouteDecision(
        model=row.model,
        max_output_tokens=output_cap,
        context_band=context_band,
        estimated_usd=round(estimate(row, input_tokens, cached_tokens, output_cap), 6),
        policy_version="context-budget-2026-08-21",
        source_date=row.source_date,
        reason=reason,
    )

def complete_with_profile(task_kind: str, prompt: str, cached_tokens: int = 0):
    decision = choose_route(task_kind, prompt, cached_tokens)
    response = client.chat.completions.create(
        model=decision.model,
        messages=[{"role": "user", "content": prompt}],
        max_tokens=decision.max_output_tokens,
    )
    return {
        "response_id": response.id,
        "route": asdict(decision),
    }
Enter fullscreen mode Exit fullscreen mode

This example is deliberately conservative. It does not try to predict exact tokenizer behavior. It gives the gateway a pre-dispatch estimate, a route reason, and a cap. In production, replace rough_tokens with the tokenizer used by your SDK or gateway and write the final observed usage beside the estimate.

Cache-Aware Controls

Caching is where long-context agents either become practical or become confusing. A repository index, policy manual, or customer history bundle may appear in many requests. If the provider exposes cache-hit pricing or cache read fields, the profiler should treat cached tokens as a separate dimension.

A good cache-aware ledger has at least these fields:

Field Description
input_tokens Total prompt tokens submitted.
cached_input_tokens Tokens billed or reported as cache-hit input.
fresh_input_tokens input_tokens - cached_input_tokens, calculated and stored.
cache_namespace Stable key for repository, tenant, or document set.
cache_source_version Hash or version of the content used to build the cache.
cache_policy Whether the route required, preferred, or ignored cache.

This lets you answer better questions. Did the agent become expensive because prompts got longer, because cache-hit share dropped, because output grew, or because retries increased? Each cause points to a different fix. Longer prompts may need summarization. Lower cache-hit share may need namespace repair. Larger output may need stricter response schemas. More retries may need route or capacity work.

When to Trim, Summarize, or Reroute

The profiler should have actions, not only warnings. A warning that says "large context" is easy to ignore. A policy that says "summarize before dispatch above 64,000 estimated input tokens unless task kind is legal_review" is enforceable.

Use a simple action ladder:

  1. Keep the request as-is when estimated input and output are inside the tenant budget.
  2. Trim low-value context when the prompt exceeds the task band's threshold.
  3. Summarize repeated context into a cached artifact when the same namespace appears often.
  4. Switch to an approved long-context route when summarization would remove important evidence.
  5. Block or require review when the request exceeds both budget and approved routes.

This ladder should be visible in logs. The user-facing product may only show "request needs review" or "context was summarized," but the internal ledger should store the exact action. That gives support enough detail to debug without exposing sensitive prompt content.

Rollout Plan

Start with read-only profiling. Run the profiler for a week without blocking traffic. Compare predicted bands, selected routes, actual token usage, cache-hit share, latency, retry count, and customer-visible outcomes. This gives you a baseline before you enforce caps.

Next, enforce output caps and route reasons. Output caps are usually the least controversial first control because they reduce runaway completions without changing the user's input. Then add context-band thresholds for the highest-volume task kinds. Finally, add fallback restrictions for expensive or sensitive routes.

For a SaaS team, the operating dashboard should include route mix by tenant, cost by task kind, cache-hit share by namespace, retry count by model, and blocked requests by reason. Segment the dashboard by policy version. When a release changes routing behavior, you should see it the same day.

Internal Links for the Implementation

If you are building this on AIWave, start with the Chat Completions documentation, then check the model catalog, the live pricing page, and the predictable-pricing calculator. For DeepSeek-specific routing, review the AIWave model pages for DeepSeek V4 Flash and DeepSeek V4 Pro.

For external source checks, keep links to the official DeepSeek pricing docs, DeepSeek rate-limit docs, QwenCloud pricing docs, Z.AI pricing docs, and Kimi K3 public page. Recheck those pages before changing a production rate card.

Final Checklist

Before you ship a context-window budget profiler, make sure the gateway can do the following:

Requirement Pass condition
Dated price rows Every estimate stores source URL and source date.
Context bands Small, medium, and large prompts have explicit policy behavior.
Cache fields Cached and fresh input tokens are logged separately.
Output caps Caps are selected by task kind and route, not by prompt text alone.
Fallback logs Every fallback stores model, reason, and policy version.
Tenant budgets Pre-dispatch estimates check remaining budget before the API call.
Replay tests Route changes are tested against real historical prompts before rollout.

The important shift is architectural. Long-context support is not just a bigger number in a model table. It is a product surface with cost, latency, privacy, quality, and support consequences. A profiler turns that surface into a controlled system: estimate before dispatch, route with a reason, cap the output, observe the final usage, and keep every decision tied to a dated rate card.

Top comments (0)