[FEATURE] Clear oversized inputs of validation-failed tool calls from context — a failed Write's full content is dead weight
Preflight Checklist
- [x] I have searched existing requests and this feature hasn't been requested yet
- [x] This is a single feature request (not multiple features)
Problem Statement
When a tool call fails before execution (pre-execution validation), its full input stays in the transcript and is re-read on every subsequent turn, even though it has near-zero informational value.
Concrete example (reproduced on 2.1.215): a Write to a file that hasn't been Read in the session fails with File has not been read yet. Read it first before writing to it. The failed call's entire content payload — potentially thousands of tokens for a large file — remains in context for the rest of the session. Note the failure reason is unrelated to the payload: the same call would have failed with any content. And the retry (after Read) re-generates the full content anyway, so the failed copy is never referenced again. Net effect: a large failed Write costs its full content twice (failed attempt + successful retry), and the dead copy is re-read on every later turn.
The same argument applies to other validation-rejected calls (schema errors, InputValidationError, etc.): zero side effects, failure reason independent of the argument values, dead weight retained until compaction.
Related:
- #67691 reports the symptom side of this: failed tool calls accumulating and burning context/usage in a retry loop.
- The harness already clears old tool results (microcompact), and the API has context editing (
clear_tool_uses_20250919with optionalclear_tool_inputs: true) — but both are age/threshold-based. Neither targets the one category that is provably worthless: inputs of calls that never executed. Ironically, age-based mechanisms are the worst fit here — a just-failed huge Write is by definition the most recent content, so it survives the longest.
Proposed Solution
When a tool call fails pre-execution validation, the harness replaces its oversized input fields with a compact placeholder in all subsequent API requests, keeping small fields intact:
{"file_path": "/path/to/file", "content": "[cleared: ~3,400 tokens; call failed read-check validation]"}
Suggested gating (both conditions AND-ed):
- Failure class — only pre-execution validation failures. These never executed, so there are no side effects to debug, and the input demonstrably didn't matter. Calls that executed and then failed keep their inputs (those are needed for debugging).
- Size threshold — only clear fields above N KB. This naturally protects the cases where the failed input is the signal: e.g.
Edit'sold_stringon "String to replace not found" must stay visible, or the model loops retrying the same string.
Properties:
tool_use/tool_resultid pairing is preserved (only field values are replaced), so the transcript stays structurally valid.- Applied on the immediately-following request, the rewrite happens at the tail of the transcript, so prompt-cache loss is minimal — and the harness already accepts cache-loss-for-context trades elsewhere (microcompact).
- Retry quality is unaffected: the retry happens within the same assistant turn where thinking blocks are preserved, and Write-style retries re-emit the full content regardless of whether the failed copy is visible.
- Not silent: the placeholder itself documents what happened — both the model and anyone auditing the transcript can see that a failed attempt was cleared and why (in contrast to the silent result-clearing frustration documented in #42542).
Alternative Solutions
/compact/ microcompact: age-based and lossy; as noted above, age-based selection is the worst fit for just-failed content.- API-side context editing (
clear_tool_inputs: true): the closest existing primitive, but also age/threshold-driven rather than failure-aware. The harness knows which calls failed validation and can act surgically on the very next request. - Hook-based redaction (#71983 proposes this for tool_results): would let integrators build something similar themselves, but validation-failed inputs are a category the harness can safely handle by default, with no integration work.
Priority
Medium - Would be very helpful
Feature Category
Performance and speed
Use Case Example
- Agent writes a large generated file (~40 KB) with
Write, but the file already existed and hadn't been Read in this session → read-check rejects the call before execution. - Agent Reads the file, then retries
Writewith the full content. Two copies of the ~10k-token payload now sit in the transcript. - The session continues for another 100 turns; the failed copy is re-read on every turn, contributing nothing.
- With this feature, from the turn after the failure onward, the failed copy costs ~20 tokens instead of ~10,000.
Additional Context
Empirically verified on 2.1.215: Write's read-check rejects the call before execution; the full failed input remains addressable in later turns (the model can quote it verbatim); retries re-emit the content in full. Happy to provide transcripts.
✍️ Author: Claude Code with @carrotRakko (AI-written, human-approved)