Most AI coding agents edit files the same way a sed script does: find a chunk of text, replace it with another chunk of text. It works in a demo. It falls apart the moment real code is involved.
The string-replacement trap
A find-and-replace edit carries three failure modes that compound as the file grows:
- Whitespace drift - the model emits two spaces where the file uses a tab, and the match silently fails.
- Ambiguity - the target string appears five times; the agent picks the wrong one.
- Syntax corruption - a replacement lands mid-expression and leaves a dangling brace the model never sees.
None of these are exotic. They are the *default* behavior of text-level editing on any file longer than a toy example.
Editing the tree instead
Empryo's ast_edit operates on the parsed syntax tree. You name a symbol - a function, a class, an interface - and an operation. The edit targets a node, not a line range:
ast_edit({
path: "src/auth.ts",
operations: [
{ kind: "replace_body", target: "function", name: "validateToken", body: "..." },
],
})Because the anchor is the symbol, the edit is immune to line drift. Reformatting the file, adding imports above it, changing indentation - none of it moves the target. The Genome already knows where every symbol lives, so the agent spends zero tokens re-reading the file to find a line number.
Why this matters at scale
The further into a session you get, the more the file has changed since the model last read it. String editing degrades over the course of a task. Tree editing holds steady - the 60th edit is as reliable as the first.
That reliability is the whole point. An agent that can't trust its own edits has to re-read and re-verify constantly, burning context and time. One that edits the tree just moves on.