# Cheat Sheet

Course: [Graph Engineering](https://www.devtutorials.ai/learn/graph-engineering) · Section: Reference
Source: https://www.devtutorials.ai/learn/graph-engineering/reference/cheat-sheet

> One page to come back to: loop or graph, the graph file format, the five patterns, state contract rules, exits, caps, join policies, gates, the scorecard, graph pack files per tool, and an error index for every linter rule.

## How to Use This Page

This page collects everything from the course in one place: the decision, the file format, the patterns, the rules, the files for each tool, and every message the Graph Lab can show you. Keep it open while you build.

Tool paths and commands change often. The tool table below was checked against the official docs on 19 Oct 2026. Check again before you rely on a path.

## Loop or Graph?

Start with one loop. Add nodes only when you can name what they buy.

| Ask | If yes | Pattern |
|---|---|---|
| Does the work split into independent parts? | Run them at the same time | Parallelization |
| Does the work mix risk levels? | Send risky work down a careful path | Routing |
| Does one step leave dead ends the next should not see? | Hand over a clean, typed result | Prompt chaining |
| Is the work list only found while running? | Start capped workers for it | Orchestrator-workers |
| Is there a clear pass test, and fixes need several tries? | Fix and check until it passes | Evaluator-optimizer |
| Is it a strict step-by-step plan one agent does well? | **Keep one loop** | — |

Research on 260 agent setups: extra agents helped independent, parallel work by up to 80.8%, made strict step-by-step planning 39–70% worse, and hurt tasks one agent already did well.

## The Five Patterns

| Pattern | What it buys | How it fails | The fix |
|---|---|---|---|
| Prompt chaining | Clean context for the next step | Forwarding everything | Writer reads only a typed handoff |
| Routing | Cost matched to risk | Quiet misroutes | Strong router, confidence threshold, careful `else` |
| Parallelization | Less waiting | Races; a hung branch | One field per branch; join timeout and policy |
| Orchestrator-workers | Work found at run time | No limits | Caps on width, depth and spend; topology record |
| Evaluator-optimizer | Fix until a test passes | Weak exits | Oscillation, no progress, flat score, budget |

## Graph File Template

Each node on one line. Copy this and change it.

```yaml
graph: my-graph
checkpoint: after_each_node
kill_switch: GRAPH_PAUSED
nodes:
  - { id: route, kind: router, model: large, min_confidence: 0.7, reads: [ticket], writes: [route, risk_reason] }
  - { id: quick_fix, kind: agent, model: small, reads: [ticket], writes: [diff], exit: { checker: npm test, max_iterations: 4 } }
  - { id: careful_fix, kind: agent, model: large, on_bound: escalate, reads: [ticket], writes: [careful_diff, test_result], exit: { checker: npm test, max_iterations: 8, oscillation: true, no_progress: 2, flat_score: 3, budget: 20000 } }
  - { id: approve, kind: gate, evidence: [careful_diff, test_result, risk_reason], reads: [careful_diff, test_result, risk_reason], writes: [approval] }
  - { id: merge, kind: function, reads: [diff, careful_diff, approval], writes: [merged] }
edges:
  - { from: route, to: quick_fix, when: risk == low }
  - { from: route, to: careful_fix, when: risk == high }
  - { from: route, to: careful_fix, when: else }
  - { from: careful_fix, to: careful_fix }
  - { from: quick_fix, to: merge }
  - { from: careful_fix, to: approve }
  - { from: approve, to: merge }
state:
  route: { type: "low | high", writer: route }
  careful_diff: { type: diff, writer: careful_fix }
  test_result: { type: "pass | fail", writer: careful_fix }
  approval: { type: "approve | reject", writer: approve }
```

### Node Kinds

| Kind | What it is |
|---|---|
| `function` | Plain code: tests, a schema check, a build |
| `model` | One prompt in, one answer out |
| `agent` | A full agent running its own loop |
| `router` | Picks the next edge |
| `join` | Waits for branches and merges them |
| `orchestrator` | Finds work and starts workers |
| `gate` | Waits for a person |

### Edge Kinds

| Written as | Kind |
|---|---|
| `{ from: a, to: b }` | fixed |
| `{ from: a, to: b, when: risk == high }` | conditional (`when: else` is the fallback) |
| `{ from: a, to: a }` | loop-back |
| `{ from: a, to: [b, c, d] }` | fan-out (each target then has an edge to a join) |

## State Contract Rules

1. Every field has **one writer**.
2. Every node lists the fields it **reads**. Nobody reads `*`.
3. Fields another node decides with get a small, exact **type**.
4. Handoffs between chained nodes are **typed shapes**, like `"{cause, steps, file}"`.
5. `checkpoint: after_each_node` saves the state, so a crash resumes and a gate can wait.

## Limits at a Glance

| Where | Setting | Typical value |
|---|---|---|
| Fixer `exit:` | `oscillation` | `true` |
| Fixer `exit:` | `no_progress` | `2` |
| Fixer `exit:` | `flat_score` | `3` |
| Fixer `exit:` | `budget` | tokens for this node |
| Fixer `exit:` | `max_iterations` | 12 or less (backstop) |
| Fixer | `on_bound` | `escalate` |
| Router | `model`, `min_confidence` | `large`, `0.7` |
| Join | `timeout`, `policy` | `10m`, `all` / `quorum` / `partial` |
| Each parallel branch | `timeout` | shorter than the join's, e.g. `5m` |
| Join after an orchestrator | `check_plan` | `true` |
| Orchestrator `caps:` | `width`, `depth`, `spend` | at or below the API limit, `1`, sized for the biggest job |
| Orchestrator | `record_topology` | `true` |
| Graph | `checkpoint`, `kill_switch` | `after_each_node`, `GRAPH_PAUSED` |
| Gate | `evidence` | diff, test result, risk reason |

## The Scorecard

A graph is graded on its run, never on its drawing.

| Number | Bar |
|---|---|
| Correct outcomes | 36 of 40 or more |
| Races | 0 |
| Hung joins | 0 |
| High-risk on the cheap path | 0 |
| False "done" | 0 |
| Size (nodes + edges) | no more than the reference |

## Graphs in Each Tool

### Graph Pack Files

| File | Claude Code | Codex | Cursor |
|---|---|---|---|
| The plan | `graph.md` | `graph.md` | `graph.md` |
| One subagent per node | `.claude/agents/<node>.md` | `.codex/agents/<node>.toml` | `.cursor/agents/<node>.md` |
| Required fields | `name`, `description` | `name`, `description`, `developer_instructions` | `name`, `description` |
| Per-node model | `model:` (sonnet, opus, haiku, a full id, inherit) | `model`, `model_reasoning_effort` | `model:` |
| Shared state | `graph-state.json` + `state-contract.yaml` | same | same |
| Supervisor | `supervisor` subagent | `supervisor` agent | `supervisor` subagent |

None of the three tools has a visual graph runtime. The main agent follows `graph.md` and calls one subagent per node.

## Debugging a Run

1. Find a run that worked on the same kind of input.
2. Read both logs from the top: node, inputs, tokens, time, verdict.
3. The **first** row that differs is the cause. Rows after it are effects.
4. Fix that node only, and run again.

## Human Gates

- Gate the paths with a large blast radius: auth, payments, data migrations.
- Show the diff, the test result and the risk reason.
- Never gate the quick path. Too many approvals means nobody reads them.
- Ticket text never decides whether it needs review.

## First Real Run Checklist

- [ ] Run the test command by hand once.
- [ ] Create `GRAPH_PAUSED`, start the graph, check that it stops. Delete the file.
- [ ] Run the graph on 2 or 3 small tickets.
- [ ] Change a state field by hand between two nodes. The supervisor must stop the graph.
- [ ] Check that `graph-state.json` updates after every node.
- [ ] Read every diff on the first day.

Keep the graph's health numbers each week: tokens per node, which exits fire, how many tickets reach a gate, and how many changes were later reverted. A number that moves is your cue to diff a run.

## Error Index

The Graph Lab's linter rules and the common check messages, what causes them, and the fix. A check message starts with the version it failed on, for example "Version 2: …".

### Graph Linter

| Rule | Cause | Fix | Lesson |
|---|---|---|---|
| `router-no-fallback` | A router has no `when: else` edge | Add `when: else` to the careful path | Routing |
| `two-writers` | Two nodes write the same field | Give each field one writer | Nodes, Edges, Shared State |
| `join-no-timeout` | A join waits forever | Add `timeout: 10m` | Parallelization |
| `orchestrator-no-caps` | No limits on workers | Add `caps: { width, depth, spend }` | Orchestrator-Workers |
| `loop-back-no-exit` | A loop-back node has no `exit:` | Add exits and a turn cap | Evaluator-Optimizer |
| `whole-state` | A node reads `*` | List the fields it needs | Nodes, Edges, Shared State |
| `risk-no-gate` | A high-risk path has no gate | Add a `kind: gate` node before the merge | Human Gates |
| `could-be-loop` | The graph does one loop's job | Use one loop | Loop or Graph? |
| `no-checkpoint` | No `checkpoint:` | Add `checkpoint: after_each_node` | Nodes, Edges, Shared State |
| `no-kill-switch` | An orchestrator with no stop switch | Add `kill_switch: GRAPH_PAUSED` | Orchestrator-Workers |

### Check Messages

| Message starts with | Cause | Fix |
|---|---|---|
| "… has 2 writers" | Two nodes own a field | One writer per field |
| "… reads the whole state" | `reads: ["*"]` | List the fields |
| "The final status is …" | A result was lost or never read | Let one node read both results and decide |
| "After the crash …" | No checkpoint | `checkpoint: after_each_node` |
| "The script writer's context is …%" | The writer reads too much | Give it only `findings` |
| "The handoff is not typed" | `findings` is plain text | Give it a shape in `state:` |
| "The router is right on …%" | A weak router | `model: large` |
| "… high-risk ticket(s) took the cheap path" | Misroutes, no safe fallback | `min_confidence` and a careful `else` |
| "Only … low-risk tickets took the quick path" | Threshold too high | Lower `min_confidence` |
| "Branches write the same field" | A race | One field per branch |
| "One branch hung …" | No join timeout | `timeout:` on the join |
| "The join has no `policy:`" | No rule for missing branches | `policy: all`, `quorum` or `partial` |
| "Branch … has no `timeout:` of its own" | Only the join has a timeout | A shorter `timeout:` on each branch |
| "The join trusted the results …" | Silent worker failures | `check_plan: true` on the join |
| "Only … of 10 scripts test the real cause" | Dead ends still reach the writer | Give the writer only the typed findings |
| "No width cap …" / "… more than the API allows" | Too many workers at once | `width` at or below the limit |
| "No depth cap …" | Workers start workers | `depth: 1` |
| "The spend cap … stopped the run" | Spend cap too low | Size it for the biggest job |
| "The realized topology is not recorded" | No record of what ran | `record_topology: true` |
| "The fixer went back and forth …" | No oscillation exit | `oscillation: true` |
| "Only the budget stopped it …" | Exits missing | Add the exit for that stuck state |
| "A stop on a bound is reported as plain failure" | No escalation | `on_bound: escalate` |
| "… merged with no human gate" | No gate on the risky path | Gate before the merge |
| "A gate shows no evidence" | Reviewer sees nothing | `evidence: [careful_diff, test_result, risk_reason]` |
| "… the reference does the job with …" / "… does this job with …" | The graph is bigger than needed | Remove nodes that move no number |
| "The writer does not read `findings`" / "The investigator does not write `findings`" | The handoff is broken | Investigator writes `findings`; writer reads it |
| "The fixer made the same change again and again …" | No no-progress exit | `no_progress: 2` |
| "The score stayed flat while each try cost more …" | No flat-score exit | `flat_score: 3` |
| "`max_iterations: …` is a weak backstop" | Turn cap too high | 12 or less |
| "… low-risk tickets wait for a person" | Gates on the quick path | Gate only the careful path |
| "The join waits … minutes" | Join timeout too long | 30 minutes or less |
| "`policy: …` is not known" | A typo in the policy | `all`, `quorum` or `partial` |
| "The join does not read …" / "The verifier does not read …" | A branch's result is never merged | List every branch field in the join's `reads` |
| "Add a verifier …" / "The verifier join has no `timeout:` …" | Audits go straight to the fixer, or the verifier can hang | A `kind: join` with a timeout and a policy |
| "The fixer has no test checker …" | Fixes marked done with failing tests | `exit: { checker: <your test command> }` |
| "The … export does not validate" | A node or file is missing | Check the Export tab's message |

## Glossary

- **Node**: one step of work: code, a model call, an agent loop, a router, a join, an orchestrator or a gate.
- **Edge**: a route from one node to the next: fixed, conditional, loop-back or fan-out.
- **Shared state**: the typed record that travels with the work.
- **State contract**: each field's type, its one writer and its readers.
- **Handoff**: the field one node writes for the next.
- **Join policy**: what a join does when a branch is missing: all, quorum or partial.
- **Caps**: limits on an orchestrator's width, depth and spend.
- **Realized topology**: what a run actually started.
- **Stopped on bound**: a loop that stopped because an exit fired, not because it failed.
- **Blast radius**: how much damage a wrong change can do.
- **Graph pack**: the exported files: graph.md, subagents, state contract, supervisor, notes.

## Further Reading

- [How to Implement Graph Engineering, by QA Wolf](https://www.qawolf.com/blog/how-to-implement-graph-engineering-5-composable-patterns)
- [Building Effective Agents, by Anthropic](https://www.anthropic.com/engineering/building-effective-agents)
- [Graph Engineering vs Loop Engineering, by AI Builder Club](https://www.aibuilderclub.com/blog/graph-engineering-vs-loop-engineering)
- [Prompt vs Loop vs Graph Engineering, by MarkTechPost](https://www.marktechpost.com/2026/07/29/prompt-engineering-vs-loop-engineering-vs-graph-engineering/)
- [graphkit, by levi-qiao](https://github.com/levi-qiao/graphkit)
- [Building Coding Agent Workflows with Loop Engineering, on GoPenAI](https://blog.gopenai.com/building-coding-agent-workflows-with-loop-engineering-5686587501e1)
- [Loop Engineering, by Addy Osmani](https://addyosmani.com/blog/loop-engineering)
- [Claude Code subagents](https://code.claude.com/docs/en/subagents) · [Codex subagents](https://learn.chatgpt.com/docs/agent-configuration/subagents) · [Cursor subagents](https://cursor.com/docs/subagents)
