fix(tools): stop write_file from coaching destructive overwrite (#3150)

The overwrite guard error ("Set overwrite=true to replace") steered the
model to clobber files like MEMORY.md. Reword write_file's description,
overwrite param, and guard error to prefer append_file/edit_file.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Yue_chen
2026-07-05 14:13:31 +08:00
parent 0f4a997b47
commit 8f891d5dd0
2 changed files with 9 additions and 3 deletions
+6 -3
View File
@@ -882,7 +882,7 @@ func (t *WriteFileTool) Name() string {
}
func (t *WriteFileTool) Description() string {
return "Write content to a file. Content is written byte-for-byte after argument decoding. Standard JSON escaping applies: \\n for newline and \\\\n for a literal backslash-n sequence. If the file already exists, you must set overwrite=true to replace it."
return "Write content to a file, replacing any existing content. Content is written byte-for-byte after argument decoding. Standard JSON escaping applies: \\n for newline and \\\\n for a literal backslash-n sequence. If the file already exists you must set overwrite=true, which replaces the ENTIRE file. To add to or change part of an existing file without losing its current contents, use append_file or edit_file instead."
}
func (t *WriteFileTool) Parameters() map[string]any {
@@ -899,7 +899,7 @@ func (t *WriteFileTool) Parameters() map[string]any {
},
"overwrite": map[string]any{
"type": "boolean",
"description": "Must be set to true to overwrite an existing file.",
"description": "Set to true to replace an existing file in full. This discards the file's current contents — to preserve them, use append_file or edit_file instead of write_file.",
"default": false,
},
},
@@ -923,7 +923,10 @@ func (t *WriteFileTool) Execute(ctx context.Context, args map[string]any) *ToolR
if !overwrite {
if _, err := t.fs.Open(path); err == nil {
return ErrorResult(
fmt.Sprintf("file: %s already exists. Set overwrite=true to replace.", path),
fmt.Sprintf(
"file: %s already exists. To add to it or change part of it without losing the current contents, use append_file or edit_file. Only set overwrite=true if you intend to replace the entire file.",
path,
),
)
}
}
+3
View File
@@ -250,6 +250,9 @@ func TestFilesystemTool_WriteFile_OverwriteDefaultBlocked(t *testing.T) {
assert.True(t, result.IsError, "expected error when overwriting without overwrite=true")
assert.Contains(t, result.ForLLM, "already exists")
assert.Contains(t, result.ForLLM, "overwrite=true")
// The guard must steer toward non-destructive tools rather than only coaching overwrite.
assert.Contains(t, result.ForLLM, "append_file")
assert.Contains(t, result.ForLLM, "edit_file")
// Original content must be untouched
data, err := os.ReadFile(testFile)