A bug fix is a conversation, so the graph must cycle
Graph Engineering pattern 2 of 15: the Investigator–Fixer Loop. Why bug fixing wants a deliberately cyclic pair, why the roles must not share a conviction, and why the exit condition is written before the loop starts.
A bug fix is not a task. It is a conversation with a system that keeps answering back: diagnose → fix → retest → diagnose. The cycle is not an unfortunate side effect of imperfect understanding. It is the work — and a topology that forbids cycles forbids the work.
Context for new readers: rysh is an agentic terminal multiplexer, and this is pattern 2 of 15 in the Graph Engineering series — designing agent organizations as graphs, with the topology chosen per class of work. Pattern 1 was the star, an acyclic shape for independent subtasks. Bug fixing is its opposite: the subtask is the iteration.
The problem
A defect is observed. Its cause is unknown or partially known. The path to resolution necessarily alternates between understanding — reproduce, read logs, form causal hypotheses — and intervening — change code, run tests. Each intervention produces new information that revises the understanding. No amount of up-front decomposition removes that loop; it can only drive it underground.
The topology
Investigator <----> Fixer
diagnose -> fix -> retest -> diagnose
...until the exit condition is met
A deliberately cyclic, bidirectional pair. The investigator owns truth: it reproduces the bug, examines logs and failing tests, and proposes causes. The fixer owns change: it modifies the implementation against the diagnosis. Results — passing or failing — return to the investigator, which either declares the exit condition met or produces a refined diagnosis and sends the loop around again.
Why two agents instead of one
Anchoring. An agent that both diagnoses and fixes defends its first hypothesis and starts patching symptoms — the single most expensive failure in automated debugging. Splitting the roles splits the conviction: the investigator has no stake in the fixer's patch. Its job is to break it. The two roles can share a codebase; they must not share a belief.
The discipline that makes cycles safe
The exit condition is written before the loop starts. "Loop until fixed" without a testable definition of fixed is an unbounded loop; a cycle with a written exit condition and resource bounds is a fence the work can iterate freely inside. The exit is concrete: the reproduction no longer reproduces, the regression test passes, no new failures appear — within bounded iterations, tokens and wall-clock.
Where it breaks
- No exit condition. The loop becomes a runaway, or a judgment call made by whichever agent tires first.
- Role collapse. One agent doing both jobs reintroduces the anchoring the pattern exists to prevent.
- Symptom whack-a-mole. If the investigator only reports "test X fails" rather than causal claims, the fixer optimizes for the test, not the defect. A diagnosis is a causal statement.
The dimension answers
| Dimension | Answer |
|---|---|
| Nodes | Investigator, fixer |
| Edges | Bidirectional pair |
| Cycles | The point of the pattern — bounded, with a written exit condition |
| Humans | Optional escalation when the loop exhausts its bounds |
| Exit rule | Reproduction eliminated and regression test passes, within bounds |
Where rysh fits
The cycle discipline is enforceable in code, not just requested in a prompt. In rysh, a loop needs a written exit condition or it does not loop — and every loop is bounded on tokens, wall-clock and iteration count, enforced in the execution loop itself. "Where is iteration allowed?" is one of the ten questions Graph Engineering asks of every topology; for bug fixing the answer is: right here, inside a fence the loop cannot talk its way out of.
Honest scope
- The investigator/fixer split is an organizational design you build on rysh's primitives, not a shipped two-agent product.
- The bounds are bounds on execution — they do not certify that the fix is good; a judge is a signal, not a proof.
- rysh is open-core: the CLI is Apache-2.0, the server is proprietary. It runs on Claude, with your own key.
Next: pattern 3, the PR Review Graph — where independence between reviewers is the property everything else depends on.
Building this with design partners → rysh.ai/design-partner