fix(tools): enforce read-before-write guard for write_file#2554
Open
nsalvacao wants to merge 4 commits intoQwenLM:mainfrom
Open
fix(tools): enforce read-before-write guard for write_file#2554nsalvacao wants to merge 4 commits intoQwenLM:mainfrom
nsalvacao wants to merge 4 commits intoQwenLM:mainfrom
Conversation
Part of QwenLM#2499 — new error type for the content-loss guard in write_file tool. Generated by Nuno Salvação <nuno.salvacao@gmail.com> & Co-Authored with Nexo <nexo.modeling@gmail.com>
Instructs the LLM to always read existing files before overwriting them with write_file, and to prefer edit for targeted changes. Part of QwenLM#2499 Generated by Nuno Salvação <nuno.salvacao@gmail.com> & Co-Authored with Nexo <nexo.modeling@gmail.com>
Updates tool schema description to instruct the LLM to read existing files before overwriting them, following the pattern established by the edit tool (edit.ts:26). Part of QwenLM#2499 Generated by Nuno Salvação <nuno.salvacao@gmail.com> & Co-Authored with Nexo <nexo.modeling@gmail.com>
When write_file is called on an existing file (>=100 chars) and the proposed content is less than 50% of the original length, the write is blocked with an educational error instructing the LLM to read the file first. The guard is bypassed when content was modified by the user. Fixes QwenLM#2499 Generated by Nuno Salvação <nuno.salvacao@gmail.com> & Co-Authored with Nexo <nexo.modeling@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
TLDR
Prevents
write_filefrom overwriting existing files with hallucinated/truncated content by adding a 3-layer defense: system prompt instruction, tool description warning, and a runtime content-loss guard that blocks writes when proposed content is significantly shorter than the original.Screenshots / Video Demo
Before (the problem): The agent calls
write_fileon an existing 200-line file without reading it first, replacing it with ~20 lines of hallucinated content. Data loss.After (the fix): When the proposed content is <50% of the original file length, the write is blocked with an educational error:
The original file is preserved. The LLM is guided to read first, then retry.
Dive Deeper
Approach & Rationale
Problem:
write_fileis stateless — no instruction or mechanism tells the LLM to read before writing. Theedittool avoids this by design (itsold_stringparam forces knowledge of current content), butwrite_filehas no equivalent.Alternatives considered:
write_filecalls. Rejected: hooks are user-configurable, not a reliable default safeguard.Decision: Defense-in-depth with 3 complementary layers, each independently useful:
prompts.tswrite-file.tsedittool patternwrite-file.tsproposed.length / original.length < 0.5(files ≥100 chars)Guard bypass conditions: new files, small files (<100 chars), empty files, user-modified content.
Reviewer Test Plan
npx vitest run packages/core/src/tools/write-file.test.ts(6 new tests for the guard)npx vitest run packages/core/src/core/prompts.test.tsTesting Matrix
Linked issues / bugs
Fixes #2499