Aug 11, 2026 · 5 min · Dev Guides

Claude Code sends 33k tokens before reading the prompt; OpenCode se...

Claude Code sends 33k tokens before reading the prompt; OpenCode se...

A one-line request such as rename getUser() to fetchUser() can arrive at the model as a 33,001-token prompt. In one observed setup, Claude Code contributed roughly 33,000 tokens of instructions, tool definitions, and environment context before the developer’s text; OpenCode contributed about 7,000. That 26,000-token difference is larger than many production prompts in their entirety.

Those numbers are not universal benchmarks. Client version, enabled tools, MCP servers, project instructions, and provider routing all change the payload. But the underlying problem is real: an agentic coding client is a prompt compiler, and the text you type is only one of its inputs.

What “before reading the prompt” actually means

The model does not literally process a hidden 33,000-token request and then open a second message containing your prompt. The client usually submits one ordered context containing some combination of:

  1. A system prompt defining behavior and constraints.
  2. Tool schemas for file access, search, shell commands, edits, and task tracking.
  3. Instructions from repository files.
  4. Environment metadata such as the working directory and platform.
  5. MCP server tools and their descriptions.
  6. Conversation history.
  7. Your new user message.

“Before” means these tokens appear earlier in that sequence. A simplified request might look like this:

{
  "model": "sonnet-4.6",
  "system": "You are a coding agent... [thousands of tokens]",
  "tools": [
    {
      "name": "read_file",
      "description": "Read a file from the workspace...",
      "input_schema": {
        "type": "object",
        "properties": {
          "path": { "type": "string" },
          "start_line": { "type": "integer" },
          "end_line": { "type": "integer" }
        },
        "required": ["path"]
      }
    }
  ],
  "messages": [
    {
      "role": "user",
      "content": "Rename getUser() to fetchUser()."
    }
  ]
}

The model needs enough of this scaffolding to behave like a coding agent rather than a chat box. The problem is not that overhead exists. The engineering question is whether each token earns its place on every turn.

Where 33,000 tokens come from

A large system prompt alone is rarely the whole explanation. Agent overhead tends to accumulate across several layers.

SourceWhy it is includedCommon failure mode
Core agent instructionsDefines workflow, safety rules, and editing behaviorRepeats similar rules in multiple sections
Tool schemasTeaches the model how to call toolsVerbose descriptions and duplicated examples
MCP integrationsExposes external services and resourcesEvery server publishes every tool on every turn
Repository instructionsAdds project-specific conventionsLarge global files apply to unrelated tasks
Environment contextIdentifies platform, paths, and capabilitiesStatic details are resent unnecessarily
Conversation historyPreserves task stateRaw tool output remains in context indefinitely
Sub-agent definitionsEnables specialized delegationDefinitions are loaded even when delegation is irrelevant

Tool schemas are a particularly easy source of bloat. A client with 40 tools does not merely send 40 names. It may send descriptions, JSON Schema properties, nested enums, validation constraints, and usage guidance for each one.

MCP makes this worse when used indiscriminately. Connecting GitHub, a database, an issue tracker, browser automation, observability, and cloud infrastructure can add dozens or hundreds of tool definitions. Asking for a local TypeScript rename does not require the model to understand the full schema of create_incident, query_warehouse, and rotate_deployment.

In practice, repository instructions are the next common gotcha. Teams often copy documentation into an agent file because “more context helps.” A 6,000-token architecture guide then accompanies CSS edits, typo fixes, and dependency updates—even when none of it affects the task.

The cost is more than the first request

The obvious cost is input-token billing. Suppose two clients contribute 33,000 and 7,000 tokens respectively:

difference = 33,000 - 7,000 = 26,000 input tokens

At an illustrative uncached input price of $3 per million tokens, the difference is:

26,000 / 1,000,000 × $3 = $0.078 per request

Across 1,000 agent turns per day, that becomes $78 per day before output tokens. Substitute the actual input, cached-input, and cache-write prices for your selected model; they differ by provider and model.

Prompt caching can make a stable prefix substantially cheaper, but it does not make the overhead free. Four separate effects matter:

A 33,000-token prefix consumes 16.5% of a 200,000-token context window before source files or command output appear. On a 1-million-token model such as Fable 5, it consumes only 3.3%, but that does not eliminate billing or attention trade-offs. Larger windows reduce the capacity constraint; they do not justify sending irrelevant material.

Measure the request, not the text box

Do not estimate overhead from the visible prompt. Capture usage at the provider boundary.

The most reliable measurements come from server-reported usage fields. Anthropic-style, OpenAI-style, and Gemini-style APIs expose different response structures, so normalize them in your gateway:

{
  "timestamp": "2026-03-12T10:15:00Z",
  "client": "coding-agent-a",
  "model": "sonnet-4.6",
  "input_tokens": 33142,
  "output_tokens": 418,
  "cache_read_tokens": 29810,
  "cache_write_tokens": 0,
  "user_message_tokens": 23,
  "tool_count": 47
}

Then calculate an operational approximation:

def request_overhead(input_tokens: int,
                     user_tokens: int,
                     injected_file_tokens: int = 0) -> int:
    return max(0, input_tokens - user_tokens - injected_file_tokens)

sample = request_overhead(
    input_tokens=33142,
    user_tokens=23,
    injected_file_tokens=0,
)

print(sample)  # 33119

This is not a perfect semantic split. Some APIs count images, tool results, or cached content differently, and local tokenizers may disagree with provider accounting. Server usage is the billing authority.

For a useful comparison, run a controlled canary:

  1. Start a new session with no conversation history.
  2. Use the same model and provider.
  3. Disable optional MCP servers.
  4. Send the same tiny prompt, such as Reply only with OK.
  5. Record input tokens, cache fields, tool count, and latency.
  6. Enable integrations one at a time and repeat.
  7. Run a second warm request to separate cold cache writes from cache reads.

A shell-level summary over normalized JSON logs is enough to expose regressions:

jq -s '
  group_by(.client) |
  map({
    client: .[0].client,
    requests: length,
    avg_input: (map(.input_tokens) | add / length),
    avg_cache_read: (map(.cache_read_tokens // 0) | add / length),
    avg_tools: (map(.tool_count) | add / length)
  })
' usage.jsonl

Track percentiles as well as averages. A client may look efficient in fresh sessions while growing badly after 20 tool-heavy turns.

Reducing overhead without crippling the agent

The wrong optimization is deleting every instruction until the client becomes cheap but unreliable. Optimize relevance and lifecycle instead.

Load tools progressively

Start with filesystem search, file reading, editing, and shell execution. Add deployment, database, browser, or issue-tracker tools only when the task requires them.

If the API requires all tools up front, route tasks through profiles:

TOOL_PROFILES = {
    "local_code": ["search", "read_file", "edit_file", "run_tests"],
    "database": ["search", "read_file", "query_db", "inspect_schema"],
    "release": ["search", "read_file", "run_tests", "create_release"],
}

This also reduces the chance that the model selects a plausible but inappropriate tool.

Make schemas compact, not ambiguous

Remove prose that restates JSON Schema, duplicated examples, and ornamental wording. Preserve details that affect correctness.

{
  "name": "read_file",
  "description": "Read a UTF-8 text file. Line numbers are 1-based.",
  "input_schema": {
    "type": "object",
    "properties": {
      "path": { "type": "string" },
      "start": { "type": "integer", "minimum": 1 },
      "end": { "type": "integer", "minimum": 1 }
    },
    "required": ["path"],
    "additionalProperties": false
  }
}

“Make descriptions shorter” has a limit. Removing the fact that lines are 1-based may save a few tokens and create repeated failed calls.

Scope project instructions

Keep global instructions short: build commands, critical conventions, and non-negotiable constraints. Put Python, frontend, infrastructure, and release guidance in directory-specific files loaded only when relevant.

Prefer:

Run: npm test
Format: npm run lint:fix
Never edit generated files under src/generated/
Frontend-specific guidance: apps/web/AGENTS.md

over embedding the entire engineering handbook.

Compact history deliberately

Retain decisions, changed files, failing tests, and unresolved questions. Drop repetitive directory listings and successful command output. Summaries must be treated as lossy state: preserve exact error messages or code fragments when the next step depends on them.

Applying this to Claude, GPT, and Gemini APIs

The same design applies whether an agent targets Sonnet 4.6, Haiku 4.5, GPT-5.5, Gemini 3, or another model. Provider syntax changes; context economics do not.

At the platform layer, log:

This makes multi-model routing more meaningful. A cheaper model can still produce an expensive request if the client wraps every turn in a huge prefix. Conversely, a larger model may be cost-effective when prompt caching is stable and it completes the task in fewer turns.

If you use AI Prime Tech for lower-cost Claude, GPT, or Gemini API access, preserve this telemetry across routes. Lower unit pricing helps, but reducing 26,000 unnecessary tokens is a structural saving that applies to every provider.

Practical takeaways

The goal is not the smallest possible prompt. It is the smallest prompt that still gives the model the tools, constraints, and state required to finish the task correctly.

PN
Priya Natarajan · ML Platform Lead

Priya leads ML platform engineering and has shipped retrieval and agent systems at scale. She focuses on prompt engineering, RAG, context management, and getting the most performance per dollar from frontier models.

Get cheaper Claude API access

One API key for Claude Opus 4.8, Sonnet 4.6, Haiku 4.5, Fable 5, plus GPT & Gemini — up to 80% off official pricing, pay-as-you-go.

Get Your API Key →
AI Prime Tech is an independent third-party API gateway. Claude™ and Anthropic® are trademarks of Anthropic, PBC. No affiliation or endorsement is implied.