Cut Coding Agent Token Use with Better Tool Output: JSON Is Not Always the Answer

·13 min read·Evergreen Tools Team
Coding agent token optimization

💡 Tool TipOptimizing agent token costs? Try Evergreen Tools' AI Token Counter, AI Code Reviewer, Code to Markdown

Teams usually focus their cost controls on model choice, prompt length, and request limits. Those are worthwhile levers, but a less visible one sits in the interfaces between agents and developer tools: the format of the data returned to the model. "Token costs are shaped not only by what coding agents read, but also by how development tools package that information." When a tool returns a long list of similarly shaped records, sending verbose JSON can make the agent pay repeatedly for field names, quotation marks, and structural syntax. The content is useful; much of the representation is not. For agentic development workflows, the output format is an engineering decision, not a cosmetic one.

1. The Problem: Repeated Structural Overhead

Consider an issue list. Each entry may include an identifier, rule, severity, file, line number, message, status, and estimated remediation effort. In conventional JSON, those labels appear for every record: {"key": "AZ1002fQ9x", "severity": "BLOCKER", "component": "src/main/java/com/acme/UserRepo.java", "line": 29, "status": "OPEN"}. That is readable and useful for many systems. But an agent inspecting 25, 100, or 500 findings does not need to be told the meaning of severity or component hundreds of times. Repeating those labels consumes context that could instead hold more relevant evidence, instructions, or source code.

// The problem: a long list of similarly shaped records
// in verbose JSON. Each finding repeats field names,
// quotation marks, and structural syntax the model has
// already seen 24 times before this one.
[
  { "key": "AZ1002fQ9x", "severity": "BLOCKER",
    "component": "src/main/java/com/acme/UserRepo.java",
    "line": 29, "status": "OPEN" },
  { "key": "AZ1002fQ9y", "severity": "CRITICAL",
    "component": "src/main/java/com/acme/AuthService.java",
    "line": 41, "status": "OPEN" }
  // ... 23 more records, repeating the same labels
]

2. TOON: Token-Oriented Object Notation

Token-Oriented Object Notation (TOON) is one approach to this problem. It keeps a schema-like header for a uniform array and then sends each record as a row. The field names appear once, while the values remain intact. It is a lossless encoding of the JSON data model for the data shapes it targets. "A regular structure gives a model an explicit set of fields to expect, which can make review and validation more predictable." The result is not merely smaller text: the agent receives the same findings, but with less repeated scaffolding around them.

Token-oriented output format
// Token-Oriented Object Notation (TOON): a schema-like
// header once, then each record as a row. Lossless for
// uniform arrays, dramatically less scaffolding.
#schema
key,severity,component,line,status
AZ1002fQ9x,BLOCKER,src/main/java/com/acme/UserRepo.java,29,OPEN
AZ1002fQ9y,CRITICAL,src/main/java/com/acme/AuthService.java,41,OPEN
// The agent gets the SAME findings with less repeated
// structure around them. Field names appear once, values
// stay intact, and validation becomes more predictable.

3. The Real Numbers: 49% and 33%

The author measured a representative 25-issue comparison: TOON used 49% fewer characters than pretty-printed JSON and 33% fewer than minified JSON. The TOON project’s published benchmarks also report lower token usage for uniform tabular datasets, alongside comparable retrieval accuracy in its test set. Those results should be treated as directional evidence, not a substitute for measuring a production payload with the model a team has selected. The useful unit of analysis is a team’s actual tool output and actual model. Character counts are a helpful first signal, but tokenization differs across models. Capture a representative response, run it through the tokenizer relevant to the workflow, and compare it with the current default.

// Real-world CLI comparison from the article: the Sonar
// CLI can return an issue list as JSON or TOON. The
// first command preserves a baseline, the second reports
// savings for the actual payload, the third applies the
// compact format only where the consumer is an agent.
# 1. Default JSON output (baseline)
sonar list issues -p my-org_my-app --severities BLOCKER,CRITICAL --format json > issues.json

# 2. Evaluate the same data with the TOON CLI
npx @toon-format/cli issues.json --stats

# 3. Return compact, lossless output directly to an agent
sonar list issues -p my-org_my-app --severities BLOCKER,CRITICAL --format toon

4. Compounding in Loop Calls

The last case matters because coding agents increasingly call tools in loops. An agent may list findings, inspect affected files, make a change, run an analysis, and list the remaining findings. A modest reduction in one response compounds when the same workflow runs across repositories and iterations. Still, compactness is not the only requirement. The format must preserve the fields the agent needs to make a sound decision. It must be accepted by the toolchain. And it should be validated against the tasks that matter: identifying the highest-priority finding, locating the affected code, and determining whether remediation is complete. A cheaper context that causes a weaker decision is not a cost improvement.

Measure token usage before changing format

5. Code Walkthrough: Formats, Measurement, and Rules

The code blocks in this post unpack the pattern. Block one shows the problem itself: a long list of similarly shaped records in verbose JSON. Block two is the TOON format: a schema header followed by row records. Block three is the real CLI comparison from the article: preserve a baseline, report savings for the actual payload, and apply the compact format only where the consumer is an agent. Block four is the measurement script: compare both formats with your own tokenizer instead of assuming a universal percentage. Block five is the selection rule: choose the format by consumer and data shape, and remember the compounding effect of loop calls.

// Measure, don't assume. Character counts are a first
// signal, but tokenization differs across models. Capture
// a representative response and run it through the
// tokenizer relevant to YOUR workflow.
async function compareFormats(payload, tokenizer) {
  const json = JSON.stringify(payload);
  const toon = toToon(payload);            // header + rows
  const jTokens = tokenizer.count(json);
  const tTokens = tokenizer.count(toon);
  return {
    jsonChars: json.length,
    toonChars: toon.length,
    jsonTokens: jTokens,
    toonTokens: tTokens,
    savingsPct: Math.round((1 - tTokens / jTokens) * 100),
  };
}
// Published TOON benchmarks report lower token usage for
// uniform tabular datasets with comparable retrieval
// accuracy -- treat them as directional evidence, then
// measure your own production payload.

6. The Broader Lesson: Agent Cost Is a Context-Design Problem

Agent cost is partly a context-design problem. Teams can reduce unnecessary context in several complementary ways: retrieve only relevant files, return tool results at the right level of detail, and avoid repeatedly transmitting structural overhead. None of these changes requires reducing the quality bar for code or security findings. Start with the highest-volume structured call in an agent workflow. Measure the baseline. Change one format setting. Then assess token consumption, response quality, and task completion together. That approach is intentionally modest: it avoids a platform rewrite and makes the trade-off visible. As AI-assisted development increasingly becomes a routine part of engineering work, disciplined choices about what agents see, and how they see it, will be as important as the models they use.

// The durable rule: choose the format by consumer and
// data shape. JSON stays the right choice for nested or
// irregular data; TOON wins for large uniform collections.
const FORMAT_RULE = {
  "nested_or_irregular": "json",          // keep JSON
  "large_uniform_array": "toon",          // header + rows
  "human_reading": "pretty-json",         // readability
  "agent_consuming_loop": "toon",         // compounds across
};                                        // iterations
// Coding agents call tools in loops: list findings,
// inspect files, make a change, list remaining findings.
// A modest reduction in one response compounds when the
// same workflow runs across repositories and iterations.
// But: a cheaper context that causes a weaker decision is
// not a cost improvement -- preserve the fields the agent
// needs, validate against real tasks, then ship.

📌 Frequently Asked Questions

Why does JSON make coding agents spend more tokens?

When a tool returns a long list of similarly shaped records, verbose JSON makes the agent pay repeatedly for field names, quotation marks, and structural syntax. The content is useful; much of the representation is not (source: The New Stack, 2026-08-31).

Why does JSON make coding agents spend more tokens?

When a tool returns a long list of similarly shaped records, verbose JSON makes the agent pay repeatedly for field names, quotation marks, and structural syntax. The content is useful; much of the representation is not (source: The New Stack, 2026-08-31).

Why does JSON make coding agents spend more tokens?

When a tool returns a long list of similarly shaped records, verbose JSON makes the agent pay repeatedly for field names, quotation marks, and structural syntax. The content is useful; much of the representation is not (source: The New Stack, 2026-08-31).

Why does JSON make coding agents spend more tokens?

When a tool returns a long list of similarly shaped records, verbose JSON makes the agent pay repeatedly for field names, quotation marks, and structural syntax. The content is useful; much of the representation is not (source: The New Stack, 2026-08-31).

Why does JSON make coding agents spend more tokens?

When a tool returns a long list of similarly shaped records, verbose JSON makes the agent pay repeatedly for field names, quotation marks, and structural syntax. The content is useful; much of the representation is not (source: The New Stack, 2026-08-31).

What is TOON?

Token-Oriented Object Notation, a lossless encoding that keeps a schema-like header for a uniform array and sends each record as a row. The author measured 49% fewer characters than pretty-printed JSON and 33% fewer than minified JSON on a 25-issue comparison.

What is TOON?

Token-Oriented Object Notation, a lossless encoding that keeps a schema-like header for a uniform array and sends each record as a row. The author measured 49% fewer characters than pretty-printed JSON and 33% fewer than minified JSON on a 25-issue comparison.

What is TOON?

Token-Oriented Object Notation, a lossless encoding that keeps a schema-like header for a uniform array and sends each record as a row. The author measured 49% fewer characters than pretty-printed JSON and 33% fewer than minified JSON on a 25-issue comparison.

What is TOON?

Token-Oriented Object Notation, a lossless encoding that keeps a schema-like header for a uniform array and sends each record as a row. The author measured 49% fewer characters than pretty-printed JSON and 33% fewer than minified JSON on a 25-issue comparison.

What is TOON?

Token-Oriented Object Notation, a lossless encoding that keeps a schema-like header for a uniform array and sends each record as a row. The author measured 49% fewer characters than pretty-printed JSON and 33% fewer than minified JSON on a 25-issue comparison.

Will TOON replace JSON?

No. JSON remains a broadly supported interchange format and can be more compact for nested or irregular data. The practical question is narrower: when a model needs to consume a large uniform collection, can the tool return the same information in a representation designed for that shape?

Will TOON replace JSON?

No. JSON remains a broadly supported interchange format and can be more compact for nested or irregular data. The practical question is narrower: when a model needs to consume a large uniform collection, can the tool return the same information in a representation designed for that shape?

Will TOON replace JSON?

No. JSON remains a broadly supported interchange format and can be more compact for nested or irregular data. The practical question is narrower: when a model needs to consume a large uniform collection, can the tool return the same information in a representation designed for that shape?

Will TOON replace JSON?

No. JSON remains a broadly supported interchange format and can be more compact for nested or irregular data. The practical question is narrower: when a model needs to consume a large uniform collection, can the tool return the same information in a representation designed for that shape?

Will TOON replace JSON?

No. JSON remains a broadly supported interchange format and can be more compact for nested or irregular data. The practical question is narrower: when a model needs to consume a large uniform collection, can the tool return the same information in a representation designed for that shape?

Does fewer characters always mean fewer tokens?

Not necessarily. Tokenization differs across models. Character counts are a helpful first signal, but you should capture a representative response, run it through the tokenizer relevant to your workflow, and compare it with the current default.

Does fewer characters always mean fewer tokens?

Not necessarily. Tokenization differs across models. Character counts are a helpful first signal, but you should capture a representative response, run it through the tokenizer relevant to your workflow, and compare it with the current default.

Does fewer characters always mean fewer tokens?

Not necessarily. Tokenization differs across models. Character counts are a helpful first signal, but you should capture a representative response, run it through the tokenizer relevant to your workflow, and compare it with the current default.

Does fewer characters always mean fewer tokens?

Not necessarily. Tokenization differs across models. Character counts are a helpful first signal, but you should capture a representative response, run it through the tokenizer relevant to your workflow, and compare it with the current default.

Does fewer characters always mean fewer tokens?

Not necessarily. Tokenization differs across models. Character counts are a helpful first signal, but you should capture a representative response, run it through the tokenizer relevant to your workflow, and compare it with the current default.

Where should I start optimizing?

Start with the highest-volume structured call in an agent workflow. Measure the baseline, change one format setting, then assess token consumption, response quality, and task completion together. Remember the compounding effect of loop calls.

Where should I start optimizing?

Start with the highest-volume structured call in an agent workflow. Measure the baseline, change one format setting, then assess token consumption, response quality, and task completion together. Remember the compounding effect of loop calls.

Where should I start optimizing?

Start with the highest-volume structured call in an agent workflow. Measure the baseline, change one format setting, then assess token consumption, response quality, and task completion together. Remember the compounding effect of loop calls.

Where should I start optimizing?

Start with the highest-volume structured call in an agent workflow. Measure the baseline, change one format setting, then assess token consumption, response quality, and task completion together. Remember the compounding effect of loop calls.

Where should I start optimizing?

Start with the highest-volume structured call in an agent workflow. Measure the baseline, change one format setting, then assess token consumption, response quality, and task completion together. Remember the compounding effect of loop calls.