old_string drifts from the file by whitespace, indentation, or line endings.
edit_file or apply_patch is advertised first, based on the agent’s model family.Quick Start
Agent edits a file safely (no boilerplate)
String-name resolution — no import needed
edit_file and apply_patch resolve by name. Enable them via tools=["edit_file", "apply_patch"] in Python, tools: [edit_file, apply_patch] in YAML, or --tools edit_file,apply_patch from the CLI — no explicit import required. Or grab the curated bundle with toolsets=["coding"].praison "prompt" or praisonai tui launch now includes edit_file and apply_patch in the default toolset (the new edit group in Interactive Tools). Under the default approval_mode="auto" they are context-approved so nothing blocks; set PRAISON_TOOLS_DISABLE=edit or ToolConfig(enable_edit=False) to opt out.Direct SDK use (automatic protection)
Replace all occurrences
How It Works
Safe by Default: Concurrency & Staleness
Every read-modify-write on the same file is serialised by a per-file lock, and every write checks whether the file changed since it was last read — both run automatically acrossFileTools, EditTools, and apply_patch.
Per-File Locking
Automatic Staleness Guard
Which Override Do I Need?
Precedence Ladder
expected_hash > force=True > automatic last-read-hash guard.
force=True Examples
How Fuzzy Matching Works
edit_file walks a deterministic ladder of matching strategies and stops at the first strategy that produces a confident match. Exact matches always win; fuzzy strategies only engage when an exact substring is not found. Existing code keeps behaving exactly as before — only previously-failing edits now succeed.
- Similarity threshold:
0.7(constant_BLOCK_ANCHOR_THRESHOLDin source) - Disproportionate-length guard: rejects blocks more than 2× or less than half the
old_stringline count - Tie-breaking: two equally-scored candidates are treated as ambiguous (not silently picked)
old_string values routinely drift by whitespace, indentation, or line endings. The fuzzy ladder makes the first attempt succeed when the target is unambiguous, saving retry turns and tokens.Multi-file Patches with apply_patch
apply_patch lets an agent Add, Update, and Delete multiple files in a single atomic call — all changes succeed together or none are committed.
Agent Quick Start
Direct SDK use
Patch Format Reference
*** Begin Patch / *** End Patch are accepted and stripped.
Update hunk syntax:
@@ hunk runs through the same fuzzy ladder as edit_file, so whitespace/indentation drift in the old block is tolerated.
Atomicity Guarantees
apply_patch Error Messages
Post-edit Diagnostics
After a successful edit,edit_file and apply_patch can run a lightweight checker on the modified file and append concise diagnostics to the tool result — so the agent sees the problem and fixes it in the same loop.
Agent Quick Start
Diagnostics block appears, the agent self-corrects in the next turn — no separate “run the linter” task required.
Three modes
Configure the mode
Which checker runs?
The first installed candidate for the file extension is used. Nothing installed → diagnostics are silently skipped and the tool returns the plain success string.Output format
Guarantees
- Backward compatible —
automode keeps the success string unchanged when the edit is clean. - Never breaks an edit — a missing, slow, or crashing checker is silently skipped (logged at
DEBUG). - Bounded — 10-second timeout per file; output capped at 2000 characters and truncated cleanly beyond that.
- Sandbox-safe —
eslintruns with--no-config-lookupso workspace-controlled configs/plugins cannot execute code;tscruns per-file without atsconfig.json. - Zero overhead in
offmode — all imports are deferred.
Post-edit Formatting
After a successful edit,EditTools can run a configured language-appropriate formatter on the touched file and persist the formatted result. Default is "off" — byte-for-byte identical to prior behaviour. A missing or failing formatter never turns a successful edit into a failure.
Agent Quick Start
Three modes
"off".
Built-in formatters
./node_modules/.bin/prettier) resolve relative to the edited file’s directory, not CWD. Formatter runs under a 10-second timeout; timeouts are swallowed. The on-disk hash baseline is only refreshed when the formatter exits 0.
Custom formatter overrides
formatters maps lowercase extensions to (tool_name, argv_template). Use {path} in argv entries; if omitted, the path is appended.
Configuration Options
File Editing Functions
Edit Parameters
Constructor Parameters (EditTools / create_edit_tools)
Confining the no-workspace fallback
Pin the fallback base directory even when noWorkspace object is wired up.
workspace= is set, root is ignored. When neither is set, the base defaults to the current working directory captured at construction — later os.chdir() calls do not move the boundary.Error Messages
Common Patterns
Code Refactoring
Configuration Updates
Surviving Concurrent Edits
Atomic Multi-file Rename
Best Practices
Read before you edit — the guard is automatic
Read before you edit — the guard is automatic
read_file call (via edit_tools or file_tools) arms the automatic staleness guard for the next write or edit on that path. The guard fires without any extra parameters; just read first and the protection is in place.Use force=True only for intentional blind overwrites
Use force=True only for intentional blind overwrites
force=True bypasses the automatic staleness guard on edit_file, apply_patch, and write_file — but the per-file lock still applies. It’s not a “skip all safety” flag; it only allows the write to proceed when the file changed since the last read. Use it for deliberate rollbacks or idempotent snapshots, not as a routine escape from proper read-before-write discipline.Same path = same lock, different paths = parallel
Same path = same lock, different paths = parallel
Search Before Edit
Search Before Edit
search_files to locate patterns before editing so you know scope and can craft a unique old_string.Use the returned diff for verification
Use the returned diff for verification
edit_file returns a bounded unified diff (10 lines max, 200 chars per line) so you rarely need a second read.Make old_string unique
Make old_string unique
replace_all=True only when every occurrence should change.Line endings and BOM are preserved
Line endings and BOM are preserved
Use apply_patch for multi-file changes
Use apply_patch for multi-file changes
apply_patch when changes span multiple files and must succeed/fail together (rename, refactor, dependency bump). Use edit_file when changing one file in one place — it returns a focused diff and avoids patch syntax overhead.Patch hunk format is not unified diff
Patch hunk format is not unified diff
@@ to separate hunks and === to separate old from new — this is not unified diff format. Add/Delete sections must not contain @@/=== markers.Workspace Security
Workspace Security
Post-edit diagnostics mode
Post-edit diagnostics mode
post_edit_diagnostics at its default ("auto"). When the checker reports problems, the tool result includes a Diagnostics (<tool>): block — instruct the agent to fix the reported issues in its next edit. Switch to "on" if you want positive no problems found confirmations in traces, or "off" if you’re in a sandbox with no checkers available.Related
Workspace
Bot Default Tools
Toolsets
coding toolset to get edit_file + apply_patch + code search + shell + todos in one line
