Build a Coding Agent
Stage 5 of 7v1 · 21b7f0bd

Surgical Search-and-Replace Patching

Implement the agent patching mechanism, replacing exact substrings and rejecting ambiguous or non-existent matches.

Why Coding Agents Use Surgical Patches

If a language model had to rewrite a 500-line file just to fix a single if condition, it would consume hundreds of tokens and risk dropping methods, hallucinating imports, or corrupting indentation.

Modern coding agents like Claude Code, Aider, and Cursor rely on surgical search-and-replace patching (patch_file). The agent specifies old_str (the exact substring to replace) and new_str (the replacement). To protect codebase integrity, the runtime enforces an essential invariant: old_str must match exactly once in the target file. If it matches zero times or more than once (ambiguity), the patch must be rejected.

Input and Output Protocol

Your program receives JSON on stdin:

{
  "op": "patch_file",
  "workspace": {
    "calc.py": "def add(a, b):\n    return a - b\n"
  },
  "path": "calc.py",
  "old_str": "    return a - b",
  "new_str": "    return a + b"
}

On success, emit compact JSON with keys in alphabetical order on stdout:

{
  "content": "def add(a, b):\n    return a + b\n",
  "path": "calc.py",
  "status": "ok"
}

Keys:

  • content: the complete updated file content after applying the patch.
  • path: the path of the patched file.
  • status: "ok".

Validation Rules and Errors

  1. The target path must exist in workspace.
  2. Count the occurrences of old_str in the file:
    • Count is 0: write error to stderr and exit with code 1.
    • Count is greater than 1: write error to stderr and exit with code 1 (prevents editing the wrong location).
  3. If JSON is invalid or operation is unknown, exit with code 1.

Acceptance Criteria

  • Replaces the single occurrence of old_str with new_str.
  • Preserves indentation and all surrounding lines.
  • Rejects missing targets and ambiguous multiple matches with exit code 1.