#20076: feat(tool-truncation): use head+tail strategy to preserve errors during truncation
agents
size: S
Cluster:
Context Management Enhancements
## Problem
When tool results exceed the character limit, `truncateToolResultText` keeps the head and discards everything after the cutoff. Error messages, stack traces, and result summaries typically appear at the **end** of tool output — exactly what gets truncated.
This means the model loses the most actionable part of the output (the error) and is left with only the preamble.
## Solution
Introduced a head+tail truncation strategy:
1. **Detect important tails** — checks the last ~2000 chars for error-like patterns (`error`, `exception`, `traceback`, `panic`, etc.), JSON closing structure, or summary keywords
2. **Split the budget** — when important tail content is detected, allocates 70% to head and 30% to tail (capped at 4000 chars)
3. **Clean boundaries** — cuts at newline boundaries to avoid mid-line breaks
4. **Clear marker** — inserts a visible `⚠️ [... middle content omitted ...]` marker between head and tail
Falls back to the existing head-only strategy when the tail doesn't contain important content.
## Example
Before (head-only):
```
$ npm test
PASS src/foo.test.ts
PASS src/bar.test.ts
... [truncated — 50000 chars]
```
After (head+tail):
```
$ npm test
PASS src/foo.test.ts
PASS src/bar.test.ts
...
⚠️ [... middle content omitted — showing head and tail ...]
FAIL src/baz.test.ts
Error: expected 42 but got undefined
at Object.<anonymous> (src/baz.test.ts:15:5)
Tests: 47 passed, 1 failed
```
## Testing
Added two test cases:
- Verifies error content at tail is preserved with the head+tail split
- Verifies normal content without errors uses simple head truncation
Existing e2e tests pass without modification.
<!-- greptile_comment -->
<h3>Greptile Summary</h3>
This PR adds a head+tail truncation strategy to `truncateToolResultText` so that error messages, stack traces, and result summaries at the end of tool output are preserved during truncation instead of being discarded.
- Introduces `hasImportantTail()` to detect error-like patterns, JSON structure, or summary keywords in the last ~2000 chars of text
- When important tail content is detected, allocates 70% of the budget to head and 30% to tail (capped at 4000 chars), with newline-boundary cuts and a visible omission marker
- Falls back to the existing head-only truncation when the tail doesn't contain important content
- The size arithmetic is correct — output stays within `maxChars` through proper budget accounting of both the middle omission marker and the truncation suffix
- Two new test cases cover the head+tail and head-only paths; existing tests pass unchanged
- The `hasImportantTail` detection heuristic is fairly broad (words like "done", "result", "complete" and any trailing `}` will trigger it), which means the head+tail strategy may fire more often than intended, reducing head content by 30% for false positives — this is a non-critical trade-off worth considering tightening over time
<h3>Confidence Score: 4/5</h3>
- This PR is safe to merge — the size arithmetic is correct, edge cases are guarded, and it falls back gracefully to the existing behavior.
- Score of 4 reflects that the implementation is logically sound with correct budget math, proper fallback to head-only truncation, and adequate test coverage. The only concerns are non-critical: the tail-detection heuristic may produce false positives due to broad keyword patterns, which could unnecessarily reduce head content.
- No files require special attention — both changed files are straightforward and self-contained.
<sub>Last reviewed commit: 75f8e0f</sub>
<!-- greptile_other_comments_section -->
<sub>(3/5) Reply to the agent's comments like "Can you suggest a fix for this @greptileai?" or ask follow-up questions!</sub>
<!-- /greptile_comment -->
Most Similar PRs
#5057: fix: add per-tool-result hard cap to prevent context overflow
by hanxiao · 2026-01-31
78.1%
#16261: feat(agents): add two-tier tool output truncation and excludeFromCo...
by ProgramCaiCai · 2026-02-14
77.6%
#8888: fix: increase tool result/error context limits
by joetomasone · 2026-02-04
76.9%
#11274: fix(tools): truncate overly long tool names for API compatibility
by avirweb · 2026-02-07
74.9%
#23648: fix: detect truncated file paths from partial JSON streaming
by davidemanuelDEV · 2026-02-22
73.6%
#16894: Fix text truncation splitting surrogate pairs in web-fetch, subagen...
by Clawborn · 2026-02-15
73.4%
#23803: Fix tool metadata truncation
by kamal-ayman · 2026-02-22
73.3%
#10915: fix: prevent session bloat from oversized tool results and improve ...
by DukeDeSouth · 2026-02-07
73.1%
#4852: fix(agents): sanitize tool pairing after compaction and history tru...
by lailoo · 2026-01-30
72.8%
#8617: fix: truncate large console payloads before writing to file log
by dbottme · 2026-02-04
72.8%