Before any solution makes sense, you need to understand what token efficiency means and why it matters.
A token is a small unit of text (roughly 3-4 characters or 0.75 words). AI models charge based on tokens processed — both input (what you send) and output (what the model generates).
An AI agent doesn't just answer once. It works in multiple turns:
Turn 1: [System Prompt] + [Tool Definitions] + [User Message] → Model responds
Turn 2: [System Prompt] + [Tool Definitions] + [Turn 1 history] + [New message] → Model responds
Turn 3: [System Prompt] + [Tool Definitions] + [Turn 1+2 history] + [New message] → Model responds
Notice the problem: Every single turn re-sends the system prompt and tool definitions. As conversations grow longer, token costs compound rapidly.
| Type | What it is | Cost level |
|---|---|---|
| Output tokens | What the model generates | Most expensive |
| Uncached input tokens | Input sent fresh each time | Moderately expensive |
| Cached input tokens | Input reused from cache | Cheapest |
Key insight: The goal is to shift spending from uncached → cached, and eliminate unnecessary tokens entirely.
The system prompt is a set of instructions sent to the model before every conversation turn. It tells the agent how to behave, what rules to follow, and how to use tools.
Early AI models needed very explicit instructions:
These guardrails were necessary because models were less capable.
As models improved, they learned these behaviors naturally. The explicit instructions became redundant dead weight.
Before: Long lists of "DO NOT", "You MUST", "IMPORTANT" rules
After: Simply define what a tool does — models comply on their own
Result: ~66% reduction in system prompt size
Think of it like employee training. A new hire needs a 50-page manual. A senior expert needs a one-page brief. The instructions didn't get less important — the recipient got smarter.
Principle learned: Regularly audit static instructions. What was necessary for less capable systems may be unnecessary overhead for more capable ones.
When an agent can use tools (like searching the web, reading files, running shell commands), each tool's full description must be included in the request so the model knows the tool exists and how to use it.
Cursor added many powerful tools over time. But here's the critical insight:
Most tools are needed in fewer than 20% of conversations
Sending all tool definitions every turn is like carrying every tool in your toolbox to every job site — even when you only need a hammer.
STATIC CONTEXT (always included):
├── High-frequency tools (read, search, edit, shell)
├── Tools models hallucinate without seeing (ask_question)
└── Product-critical tools (create_plan for Plan Mode)
DYNAMIC CONTEXT (loaded only when needed):
└── All other tools → loaded on-demand
They ran A/B tests measuring:
This is important — they didn't just guess. They measured quality impact alongside efficiency gains.
Result: 60% reduction in static-context description tokens
Principle learned: Separate "always needed" from "sometimes needed." Load resources on demand rather than preemptively.
When you send the same text to a model repeatedly, the provider can cache (save) the processed version and reuse it instead of reprocessing from scratch. Cached tokens cost significantly less.
For caching to work, the beginning of the request must be identical across turns. But if variable content (like user-specific settings) was mixed into the stable content (like tool definitions), the cache would break.
BEFORE (cache breaks easily):
[System Prompt + Variable User Settings + Tool Definitions + Conversation]
↑ This changes → everything after it can't be cached
AFTER (cache preserved):
[Stable: System Prompt] ← BREAKPOINT
[Stable: Tool Definitions] ← BREAKPOINT
[Variable: User settings, environment info] ← "phantom user message"
[Growing: Conversation history]
By placing explicit breakpoints after stable content, later turns can reuse the unchanged prefix even as the conversation grows.
Variable, request-specific content (skills, subagent info, environment details) was moved past the cache boundaries into a special container. This keeps the cacheable prefix clean and stable.
Result: 20% reduction in cold cache misses
Principle learned: Structure your data so that stable content comes first and variable content comes last. This maximizes the reusable prefix for caching.
When an agent reads code files, it traditionally numbered every single line because:
But line numbers add tokens:
1 def hello():
2 print("world")
3 return True
When reading tens of thousands of lines per session, this adds up significantly.
Number only every 10th line instead of every line:
1 def hello():
def goodbye():
def maybe():
10 def another():
def function():
Models can still cite code accurately (interpolating between numbered lines), but token overhead drops substantially.
Result: 1.6% reduction in cache-read tokens with no quality loss
Principle learned: Small per-unit savings multiply dramatically at scale. Even a few tokens per line × millions of lines = meaningful cost reduction.
A subagent is a separate AI agent spawned by the main (parent) agent to handle a specific subtask. The key efficiency benefit:
Parent Agent: [Full conversation history — 50,000 tokens]
↓ spawns
Subagent: [Fresh context — starts at 0 tokens]
↓ completes task, returns summary
Parent Agent: [Receives compact result, not full subagent history]
Subagents don't share context with each other, which means:
This is the fundamental tension: isolation saves tokens, but coordination costs tokens
Fix 1: Remove over-eager subagent instructions Earlier prompts strongly encouraged using subagents for codebase exploration. But models had learned this pattern naturally through training. The extra instructions were causing too many subagents to be spawned unnecessarily.
Before: Explicit instructions → models over-use subagents
After: Remove instructions → models use subagents more appropriately
Fix 2: Tighten model selection for subagents Cursor can spawn subagents using different (cheaper) models. But agents were choosing different models too freely. Now they only switch models when:
Result: More balanced subagent usage without unnecessary coordination overhead
Principle learned: Context isolation between agents is powerful but has coordination costs. Use subagents when the task is truly independent; avoid them when shared context is needed.
Here's how all five strategies interact as a unified system:
EVERY AGENT TURN:
┌─────────────────────────────────────────────┐
│ STATIC (cached, trimmed) │
│ • Lean system prompt (-66%) │
│ • Only high-frequency tools (-60%) │
│ ← CACHE BREAKPOINT → │
│ VARIABLE (past cache boundary) │
│ • User settings, environment │
│ ← CACHE BREAKPOINT → │
│ DYNAMIC (loaded on demand) │
│ • Rare tools (loaded only when needed) │
│ GROWING (conversation history) │
│ • File reads with sparse line numbers │
│ • Subagent results (not full histories) │
└─────────────────────────────────────────────┘
Combined result: 7% reduction in total token costs without quality degradation
| Strategy | Mechanism | Result |
|---|---|---|
| Trim system prompt | Remove redundant instructions modern models don't need | -66% system prompt size |
| Dynamic tool loading | Load rare tools on-demand, not upfront | -60% static tool tokens |
| Cache breakpoints | Separate stable from variable content | -20% cold cache misses |
| Sparse line numbers | Number every 10th line instead of every line | -1.6% cache-read tokens |
| Strategic subagents | Balance isolation benefits vs. coordination costs | More efficient task delegation |