Skip to content

What's next

You’ve built a governed agent in seven files, and — if you’ve done Part 2 — the same agent again as a five-stage system with a deterministic core. Here’s the honest map of the territory beyond both.

The loop you built is the fully general shape — and full generality is rarely what you want. The common patterns are all ways of taking autonomy back:

Pattern The idea Use when
Prompt chaining Fixed steps, each feeding the next The workflow is known in advance
Routing Model classifies once, code picks the path Varied input, few outcomes
Parallelisation Several calls at once; section the work, or vote Independent chunks, or flaky answers that stabilise under majority vote
Orchestrator–workers A model decides the subtasks, delegates, synthesises The subtasks aren’t known in advance
Evaluator–optimiser One model produces, another critiques, loop You can describe “good” but not the path to it

The discipline: use the least autonomous pattern that solves your problem. Autonomy is a cost you pay because you must, not a feature you buy because it’s impressive. Most production “agents” are routing plus a couple of tools — and that’s the right call.

You saw why on the failures page: one passing run is a coin that landed heads. Before trusting an agent with anything:

  1. Write down the cases that matter, with the correct answer for each
  2. Run each case at least five times
  3. Score per-case, never in aggregate
  4. Watch the case the system exists for — that’s where accuracy collapses first

This can be twenty lines of Python. The formality isn’t the point; the repetition is.

The local setup you built is the same client/server architecture as every hosted API — the only differences are the address and the key. Moving to a hosted model (Claude, GPT) is: change the client import, add the API key, change the model string. The loop, the tools, the gate, the log — untouched.

What changes for real is behavioural: a frontier model follows instructions far more reliably than a 3B model. Resist the temptation to conclude the guardrails are no longer needed. “More reliable” is still not deterministic — the architecture stays.

Each is a small change, and each closes a real gap:

  • Approver identity in the audit log — an authenticated user id, not a typed name
  • Policy version in every log entry, so records survive the policy changing
  • A turn cap on the loop — for turn in range(MAX_TURNS) instead of while True. On a paid API, a stuck loop is an invoice
  • A tool registry — a dict mapping allowed names to functions, so the model can only reach tools you listed. Never resolve a tool name with eval() or globals(); the model’s input comes from the outside world, and that’s a path from “attacker writes a support ticket” to “arbitrary code runs”
  • Argument validation — wrap tool calls in try/except TypeError; models sometimes send arguments that don’t exist

The model judges, the code rules, a human decides, and everything is written down.

Everything else — frameworks, patterns, models — is implementation detail around that stance.


Built by Nhial Majok. The course code is on GitHub, and every block on this site runs as shown — if one doesn’t, that’s a bug worth reporting.