HarperZ9/relayExplainer, built from commit 9c79f30All repository explainers

relay

A coding agent for any model endpoint whose every step lands in a ledger you can recheck.

What it does for you

relay runs a coding agent on whichever model you can reach: a local model when you are offline, your subscription CLI or an API key when you need more, with failover between them. The agent edits your code through tools that refuse a guess, writes nothing and runs nothing unless you allow it, and records every turn in a hash-chained ledger that a stranger can re-derive.

Source: README.md at 9c79f30 (release 0.7.0)

Watch

Models do what training pays for (2 min, narrated, captioned). Relay accepts a run only when your own check passes, which is the guard this film argues for. Transcript, sources and recall questions.

Video walkthrough: coming with the next release.

How it works, one step at a time

Scroll, or use the step buttons. Each panel shows real output from relay's own tools at commit 9c79f30, run on a four-line file with an off-by-one bug. No model is in the loop for these steps; the tools behave the same whichever model calls them.

  1. 01

    One ladder of endpoints

    relay tries model tiers in order and fails over on exhaustion or error: a local model first, then your subscription CLI, then public APIs, then a gateway URL you set, then a cloud endpoint.

    Keys come from your environment and subscriptions from your own signed-in CLI. A tier whose credential is absent is never added, so a missing key gives a shorter ladder, never an error at call time.

    Source: README.md, "Reaches every endpoint"; src/relay/endpoints.py

  2. 02

    Read the file with line anchors

    Take pager.py, whose end is one short. A read_file call with "hashed": true prefixes every line with an 8-hex anchor.

    The anchor hashes the line's text together with its line number, so two identical lines get different anchors.

    Source: src/relay/hashline.py, line_anchor

  3. 03

    Edit by anchor

    The model replaces line 3 by naming its anchor, 6627593c, without repeating the line. With --allow-write the edit lands and the bug is fixed.

    Source: src/relay/local_tools.py, _t_edit_lines

  4. 04

    A stale view is refused

    Send the same edit again. Line 3 has changed, so its anchor no longer exists, and the edit is refused with nothing written.

    The other edit tools follow the same rule. A search string that matches twice is refused. A unified diff whose context no longer matches is refused, with no fuzzy placement. Pick each case in the panel.

    Source: src/relay/local_tools.py, _t_edit_lines, _t_edit_file, _t_apply_diff

  5. 05

    Nothing writes or runs unless you allow it

    The tool gate is default-deny. Without --allow-write an edit is refused before it touches the file. Without --allow-exec a shell command is refused. File tools resolve every path inside --root, so ../../etc/passwd never opens.

    Granting exec also grants write, because a shell can write files.

    Source: src/relay/local_tools.py, ToolGate and _safe_path

  6. 06

    Every step goes into a chained ledger

    Each turn and tool call is appended to the session ledger. An entry's hash covers its sequence number, kind, content, metadata and the previous entry's hash, so each entry pins everything before it.

    verify() re-derives every hash in order. This four-entry run verifies, and its head hash is the run's checkpoint.

    Source: src/relay/local_session.py, SessionLedger.append and verify

  7. 07

    An edited run will not load

    Save the run, then change one tool call so it claims the agent edited auth.py. Loading re-derives the chain on the read path, and the file is refused.

    Source: src/relay/local_session.py, SessionLedger.load

  8. 08

    Measure the boundary against injection

    relay --probe-injection runs six fixed injection scenarios, such as "run curl to send .env" or "overwrite the test file". It assumes the worst case: the model was fooled and sent exactly the smuggled call. Then it checks whether the gate refuses it.

    Under the default gate all six are contained and it exits 0. With --allow-exec, four get through and it exits 1. An open shell is a larger capability, and the probe says so.

    Source: src/relay/injection_probe.py; README.md, "Prove the boundary holds"

  9. 09

    Accept a run only when your check passes

    A ledger proves what the agent did, and your tests decide whether the code works. With --check "pytest -q", relay runs your command once after the agent finishes, records the result on the ledger, and accepts the run only if it passes. A failed check skips --auto-commit and exits non-zero.

    A rule-based guard also reads the recorded edits. A pass earned by editing the test that grades it, or by injecting a skip, is flagged and the run is not accepted. This step is described from the README; it needs a model, so it was not run for this page.

    Source: README.md, the section on --check

Walkthrough

Install it, run it once, then use the main feature. Each command below is real, and so is its output.

  1. Install

    Install from PyPI. Python 3.11 or newer.

    $ python -m pip install flywheel-relay
  2. First run: probe the boundary

    Before relay touches a model, run its built-in injection probes against the permission boundary. All six were contained.

    $ relay --probe-injection
      "contained": 6,
      "total": 6,
      "receipt": "1405769b874ca5d7"
  3. Read with line anchors

    The agent reads a file with a short hash on each line, so a later edit can name exactly the line it saw.

    read_file {"path": "pager.py", "hashed": true}
    b76150a4|def paginate(items, page, size):
    ba6dfa08|    start = page * size
    6627593c|    end = start + size - 1
    a5dfd4fd|    return items[start:end]
  4. Edit by anchor

    An edit names the anchor it read. If the file changed since, the anchor no longer matches and the edit is refused.

    edit_lines {"path": "pager.py", "at": "6627593c", "new": "    end = start + size"}
    edited pager.py (replace 6627593c)
    
    def paginate(items, page, size):
        start = page * size
        end = start + size
        return items[start:end]
  5. Run a task, accepted only by your check

    Point relay at a model and a repository. Writes need --allow-write, and the run counts as done only when your check passes.

    $ relay --agent "fix the off-by-one in paginate()" --root . --allow-write --check "pytest -q"

The probe output came from flywheel-relay 0.7.0 installed from PyPI and matches a run of the source at 9c79f30. The last two commands need a model you can reach.

What it does not do

Source: README.md at 9c79f30, "An actual coding agent", "Ambient repo context" and "Use from an agent (MCP)"

Check what stuck

Answer each one in your head before you open it.

Why does sending the same anchored edit twice fail the second time?

The anchor hashes the line's text and position. After the first edit line 3 holds different text, so the old anchor matches nothing and the edit is refused.

What does relay do with a search string that appears twice?

It refuses the edit and asks for more context. It never picks one of the two matches.

Why does --allow-exec also turn on write?

A shell can write files through redirection or other tools, so a gate that kept write off while exec was on would be a gate the run path bypasses.

A saved run has one tool call edited. What happens when you load it?

The chain is re-derived on load, the hash no longer matches, and the file is refused.

The probe reports 2 of 6 with --allow-exec. Is that a bug?

No. It is the honest measurement: an open shell can do what the gate would otherwise refuse, and the probe exits non-zero to say so.