ADK-Rust: Provider-Native File Editing
ADK-Rust is a useful counterexample to the dominant pattern in coding agents. Instead of building a giant custom editing engine with many recovery layers, it mostly wraps provider-native editing surfaces and keeps the local execution layer thin, typed, and strict.
Why It Belongs in a File-Editing Blog
ADK-Rust is not a coding product. It is a framework. That makes its editing design more interesting because it answers a different question: should a framework invent one universal file-editing protocol, or should it let providers speak their own native editing dialects?
ADK-Rust mostly chooses the second path. The result is a smaller local mutation layer, sharper failure messages, and less framework-specific prompt burden for providers that already know how to edit.
Anthropic Path: Thin Local Executor
The key file is
repos/adk-rust/adk-tool/src/builtin/anthropic.rs. It
implements provider-native text-editor wrappers and a local executor
for four concrete operations: view,
str_replace, insert, and
create.
| Command | Behavior | Constraint |
|---|---|---|
view |
Read file contents or directory listings | Optional ranges use positive 1-based line numbers |
str_replace |
Replace exactly one string occurrence | Fails on zero or multiple matches |
insert |
Insert text at a line index | The target line must exist and is 1-based |
create |
Create a new file and parent directories if needed | Fails if the file already exists |
match matches {
0 => Err(invalid_input(format!("old_str not found in '{path}'"))),
1 => {
let updated = content.replacen(old_str, new_str, 1);
tokio::fs::write(&resolved, updated).await?;
Ok("success".to_string())
}
_ => Err(invalid_input(format!(
"old_str appears multiple times in '{path}'; use a more specific match"
))),
}
Strict on purpose
There is no whitespace-normalized matcher, no anchor fallback, and no diff rescue pass. ADK-Rust would rather fail loudly than guess.
OpenAI Path: Declaration, Not Local Patch Parsing
The OpenAI builtin file makes the philosophy even clearer. The
OpenAIApplyPatchTool declares an
x-adk-openai-tool with type: "apply_patch",
marks itself as a built-in, and then returns an error saying actual
outputs must be handled through the Responses API item protocol.
In practice that means ADK-Rust does not try to become its own patch engine. It tells the provider what native capability exists and expects the provider protocol layer to carry the patch semantics.
json!({
"name": self.name(),
"description": self.description(),
"x-adk-openai-tool": {
"type": "apply_patch"
},
})
Bash Is the Escape Hatch
ADK-Rust also exposes Anthropic-native bash tools. The local runtime
executes sh -lc, captures stdout and stderr, and reports
the exit code back to the caller. That means the framework still has a
real mutation escape hatch even when the structured editor path is not
enough.
From a file-editing perspective, ADK-Rust sits between two worlds: it is not a giant local editor engine, but it is also not a purely abstract API wrapper with no filesystem muscle.
How It Compares
| Repo | Main editing idea | Failure strategy |
|---|---|---|
| Cline | Custom search/replace plus layered fallbacks | Try more forgiving matchers until something lands |
| Codex / Claude Code | Patch-oriented mutation surface | Patch parsing plus runtime validation |
| OpenCode | Exact edits plus a large fallback stack | Nine matching layers before giving up |
| ADK-Rust | Provider-native wrappers | Return precise errors and let the caller or model retry |
What I Would Steal from It
Thin adapters beat fake universality
If a provider already has a first-class editing contract, wrapping it cleanly can be better than teaching every model a large house format.
Strict errors are useful
Exact-match failure messages give the model enough structure to self-correct without the framework guessing at what the user meant.
Keep sandboxing separate
ADK-Rust does not pretend every file-edit path is equally safe. Sandboxing stays an explicit optional layer.
Do not overclaim
ADK-Rust does not have the fanciest local matcher in this set. It has a more framework-appropriate promise, and the repo is honest about that.