DEV Community

HIROKI II
HIROKI II

Posted on

Claude Code Token Waste: Don't Feed Raw Data to the Model. Let Scripts Filter First

KD Agentic cover

Last Tuesday afternoon, I watched a backend engineer sigh in front of his terminal.

He was deep into refactoring an older payment and refund module. To diagnose a recent cluster of failed transactions, he typed a natural instruction into Claude Code: "Inspect the last 100 failed refund records from the production database, identify the most common error types, and update our validation interface accordingly."

The assistant complied eagerly. It issued a database query tool call. A second later, the terminal screen turned into a blur of rapid scrolling.

What flooded back was 80 kilobytes of raw, unfiltered JSON. One hundred transaction objects, each carrying full customer delivery addresses, third-party payment gateway transaction hashes, cryptographic HMAC signatures, internal timestamps, and verbose UI metadata dictionaries.

What followed is painfully familiar to anyone using modern coding agents: the assistant's thinking indicator spun for nearly ninety seconds. When it finally generated its response, it had completely discarded the initial requirement not to modify legacy interface signatures. Even worse, it miscalculated the aggregate refund amount by two orders of magnitude.

A single query had consumed over 40,000 tokens—several dollars burned in under two minutes for three basic numbers.

The engineer asked me: "Are model context windows still too small? Or did I write the prompt wrong?"

Neither. The model wasn't lacking intelligence, and the prompt was entirely reasonable. The root cause was physical: we dumped tens of kilobytes of raw infrastructural noise directly onto the model's active reasoning desk.

Here is how to solve this ingestion crisis permanently. You do not need a more expensive model or complex multi-agent orchestration. You only need three lightweight deterministic boundaries to cut token waste by over 70% and keep your agent coherent through multi-step refactoring.

The Two-Window Experiment: Rescuing the Model's Reasoning Desk

Before diving into complex project setups, run this one-minute test in any two ordinary chat windows. It demonstrates the stark difference between payload indigestion and clean execution.

Imagine you have a test payload from a payment webhook containing twenty transaction records:

[
  {"id": "tx_9011", "user": "Alex", "amount_cents": 19900, "status": "failed", "error": "insufficient_funds", "meta": {"trace_id": "tr_88192a", "client_ip": "192.168.1.10", "retry_count": 3, "gateway": "stripe_v3"}},
  {"id": "tx_9012", "user": "Bella", "amount_cents": 4900, "status": "succeeded", "error": null, "meta": {"trace_id": "tr_88192b", "client_ip": "10.0.0.1", "retry_count": 0, "gateway": "paypal_v2"}},
  {"id": "tx_9013", "user": "Chris", "amount_cents": 8900, "status": "failed", "error": "card_expired", "meta": {"trace_id": "tr_88192c", "client_ip": "172.16.0.4", "retry_count": 1, "gateway": "stripe_v3"}}
]
Enter fullscreen mode Exit fullscreen mode

(Real payloads often span hundreds of rows with ten times as many nested fields.)

Window A: The Direct Dump

In your first window, paste the raw JSON dump and ask:

"How many failed transactions are there, what are the error reasons, and what is the total dollar amount?"

The model computes the answer, but observe the cost: to return three numbers, it ingested thousands of irrelevant IP addresses, trace IDs, and punctuation marks.

Worse, try your follow-up prompt: "Refactor our customer notification template based on these errors, and make sure to include support phone 1-800-555-0199."

With its attention diluted by thousands of noisy characters, the model frequently forgets the support number or mixes successful transactions into the notification list.

Window B: The Local Script Buffer

Now open a clean window. Do not paste the full payload. Show only the schema of the first item, and prompt:

"I have a local file named data.json containing transactions matching this schema. Do not read the file into your prompt. Write a 4-line Python script that extracts the failure count, error breakdown, and total dollar amount, and prints the result to stdout."

The assistant writes clean, deterministic code:

import json

with open("data.json", "r", encoding="utf-8") as f:
    items = json.load(f)

failed = [x for x in items if x.get("status") == "failed"]
errors = {}
for x in failed:
    err = x.get("error", "unknown")
    errors[err] = errors.get(err, 0) + 1

total_cents = sum(x.get("amount_cents", 0) for x in failed)
print(f"FAILED_COUNT={len(failed)}")
print(f"ERRORS={errors}")
print(f"TOTAL_DOLLARS={total_cents / 100:.2f}")
Enter fullscreen mode Exit fullscreen mode

You run python process.py in your local terminal. It returns three lines instantly:

FAILED_COUNT=2
ERRORS={'insufficient_funds': 1, 'card_expired': 1}
TOTAL_DOLLARS=288.00
Enter fullscreen mode Exit fullscreen mode

You feed those three lines back to the assistant for your next engineering step.

Look at the structural shift:

  • Token Ingestion Cut by 98%: The model read 30 characters instead of 5,000.
  • 100% Deterministic Accuracy: Calculations ran in Python's runtime, eliminating arithmetic hallucinations.
  • Pristine Context: The working memory remains entirely focused on core business logic.

The core rule is simple: If deterministic local code can crush the noise in four lines, never let raw strings enter the model's context window.

Why 1M Context Windows Still Crash on Step 5

A common objection is: "Modern frontier models support 200k or 1M context windows. Why worry about a few tens of kilobytes?"

This reflects a dangerous engineering misconception: Context capacity is not active working memory.

Empirical benchmarks on coding agents (such as LangWatch's research on optimal context windows) reveal that while models can store enormous documents, their precision on strict constraint-following deteriorates rapidly once uncurated noise exceeds 8,000 to 10,000 tokens.

Uncontrolled tool dumps trigger three systemic failures:

  1. The Dilution Effect: LLMs allocate attention probabilistically. When 90% of the prompt consists of HTTP headers and JSON syntax, attention across critical architectural rules is diluted.
  2. Compounding Prefill Costs: In multi-turn agent sessions, you do not pay for new tokens in isolation. Every subsequent turn re-submits the entire conversation history for prefill computation. A 40,000-token dump on turn 1 is billed five times by turn 5.
  3. The Rediscovery Tax: Research on coding agent behavior (such as Gjalla's analysis of developer trajectories) shows agents spend over 40% of their tokens repeatedly searching and re-reading identical files because noisy context pushes earlier observations out of focus.

The Three-Layer Defense for Complex Projects

To maintain lean, reliable execution across large repositories, integrate these three lightweight patterns into your daily workflow.

Layer 1: Code Execution as a Context Buffer

This architecture mirrors Anthropic's official engineering guidance on Code Execution with MCP.

Instead of the naive loop:

Model calls tool → Tool returns 50KB JSON → Entire payload enters prompt history

Modern workflows treat tools as executable libraries inside a local sandbox:

Model writes a brief script → Script calls tools in sandbox memory → Filtering and aggregation occur in-memory → Only stdout returns to the prompt

When scanning fifty server logs for an exception, instruct your agent:

"Do not read each log file into chat. Run a local Python or Shell one-liner to grep for NullPointerException, aggregate occurrences by file and line, and print only the top 3 stack frames and counts."

The assistant returns:

Found 14 occurrences across 3 files:
- src/auth/service.py:104 (11 times)
- src/payment/handler.py:56 (2 times)
- src/utils/token.py:22 (1 time)
Enter fullscreen mode Exit fullscreen mode

Your context absorbs 80 tokens rather than 80,000.

Layer 2: Scratchpads on Disk

Why do coding agents forget requirements mid-task? Because early instructions roll off the attention curve as prompt history expands.

The fix is straightforward: Evict state from conversation memory to disk.

Before starting a multi-file refactoring task, have your agent initialize a minimal tracking file, such as .codex_task.md:

# Task: Refactor Authentication Middleware

## Verified Architectural Facts
- Legacy token validation uses HS256 with key stored in JWT_SECRET.
- New implementation must support dual-verification during a 14-day migration window.

## Execution Checklist
- [x] 1. Locate all direct imports of JwtValidator (3 modules identified).
- [/] 2. Implement backward-compatible wrapper in src/auth/compat.py.
- [ ] 3. Add unit tests for dual-token resolution.
- [ ] 4. Run test suite to verify zero regressions.

## Open Risks
- Connection pool does not re-fetch public keys on socket timeout.
Enter fullscreen mode Exit fullscreen mode

This delivers two immediate operational benefits:

  1. Safe Context Compaction: You can reset or compact the session at any time (/compact or fresh session), prompt "Read .codex_task.md and proceed with step 3", and resume with 100% active memory.
  2. Zero Rediscovery: Verified facts are committed to disk, eliminating repetitive search loops.

Layer 3: Test-Slicing Over Whole-Repo Sweeps

When facing an elusive bug, the default approach is asking the agent to inspect five directories. The agent reads dozens of files, burns thousands of tokens, and hallucinates a speculative fix.

High-efficiency developers invert the sequence: Force the agent to author a minimal failing reproduction test before touching production code.

Prompt:

"Do not edit implementation files yet. Write a 10-line reproduction test in tests/repro_test.py that submits a zero-dollar order and asserts that it throws an explicit validation error. Run pytest to confirm it fails."

Terminal output:

FAILED tests/repro_test.py::test_zero_amount_checkout - ValueError: Amount must be positive
Enter fullscreen mode Exit fullscreen mode

The problem space is now physically constrained: the agent only needs to edit the checkout handler until this 10-line test passes. Whole-repository guessing is completely bypassed.

Measurable Engineering Gains

Applying this three-layer protocol delivers immediate, tangible results:

  • Token Consumption: Multi-hour refactoring runs drop from 400k+ tokens to under 100k tokens—a sustained 65% to 75% cost reduction.
  • Execution Speed: Terminal latency drops dramatically since the model is not parsing giant prefills on every turn.
  • Architectural Coherence: Without context pollution, the agent maintains strict constraint adherence across ten or more file edits.

When Not to Do This: Honest Boundaries

Every practical engineering pattern has sensible boundaries:

  1. Skip the Harness for Simple Edits: If you are tweaking a CSS class, fixing a typo, or writing an isolated helper function, do not create scratchpad files or custom scripts. Standard chat prompts are already optimal.
  2. Never Automate Destructive Writes: Sandboxed scripts should be strictly restricted to read-only queries, data filtering, and local parsing. Any database mutation (UPDATE, DELETE) or file deletion must be reviewed by human eyes before execution.
  3. Keep Reproduction Slices Minimal: Do not ask the agent to build an exhaustive end-to-end integration suite to reproduce a bug. A three-line test that exercises the broken branch is all you need.

Conclusion: Let Code Compute, Let Models Decide

The AI coding ecosystem has spent years racing on benchmark scores and expanding context windows.

Yet real-world engineering efficiency obeys a timeless principle: Large language models excel at reasoning over dense, curated information. Deterministic code excels at microsecond filtering and arithmetic aggregation.

Stop treating frontier models as text transmission pipes. Keep raw data in sandbox memory, keep state on disk, and guide fixes with minimal test slices.

When your agent travels light, it ships faster, stays coherent, and protects your budget.


Sources & Technical References

Top comments (0)