Agent Engineering: From Prompt to Reliable Work Loop
Monday, 9:14 a.m. The Intern answers a refund ticket in eleven seconds. Confident. Polite. Cites policy §4.2. Policy §4.2 does not exist.
Watch an unbounded agent fail, put it under contract, break it on purpose, and ship a bounded work loop of your own — with a receipt that proves what it did.
What you will be able to do
- Trace an agent run and locate the first contract failure.
- Specify goal, tool, budget, and stop-rule boundaries.
- Implement and test a bounded loop that fails closed.
- Prerequisites
- Can read JSON and a short execution trace · Has run a small script or command-line tool
- Assumed knowledge
- No agent framework experience required.
- Evidence you will produce
- A bounded agent loop, adversarial fixtures, and an evidence receipt
- Workload
- 40 min guided lesson + 45–90 min independent build
The incident
TL;DRAn agent without a contract doesn't fail loudly. It succeeds convincingly at the wrong thing.
Meet the Intern. It's an agent we built badly on purpose: one long prompt, real tools, no rules about what counts as done. On Monday it picked up ticket #4712 — a refund request with a policy note attached and one field missing.
Press play. Watch what it does. Your job is the same as a real reviewer's: spot the exact moment this run went wrong.
- Press play. A few seconds of real work, slowed down enough to catch the lie.
The Intern read the real policy note correctly. So where did this run actually go wrong?
The diagnosis: no contract
TL;DRA prompt tells an agent what to do. A contract tells everyone else how to check it.
The Intern's failure wasn't intelligence. It observed the truth and then overwrote it, because its only instruction was 'resolve the ticket' — and a confident invented answer resolves a ticket beautifully.
A goal contract is four lines you write before the agent runs: the outcome that counts as done, the inputs it may treat as true, the actions it may take without a human, and the point where it must stop and hand over.
Here's the Intern's, written properly:
- Outcome
- A draft reply packet a human reviewer can approve — never a sent message.
- Inputs
- The ticket and its attached policy note. Nothing else is citable.
- Allowed
- read_fixture, write_draft. send_message is denied.
- Stop
- Any missing field is marked unresolved and escalated — never guessed.
Go deeper
Why 'inspectable' beats 'autonomous': the goal is not to make a workflow look self-driving. It's to make its boundaries and failures visible enough that another person can review the run without re-doing the work. Autonomy you can't audit is just risk with good UX.
The contract is also where delegation lives. A subtask may inspect a plan or summarise a document, but it never silently inherits the authority to publish, delete, or change a system of record. Authority is granted per-tool, per-contract — not per-vibe.
Your agent triages invoices. Which line belongs in its goal contract?
The loop: five stages, one receipt
TL;DRPlan → Act → Observe → Verify → Handoff. Verify compares against the contract. Handoff leaves evidence.
A reliable agent run is the same five stages every time. Plan turns the goal into small, checkable steps. Act performs only allowed operations. Observe records what actually happened — not what the model hoped. Verify compares the result against the contract's acceptance criteria. Handoff packages the artifact, the unresolved questions, and the next owner.
Two of these stages do all the safety work. Verify is where invented policy dies: if a citation doesn't resolve to an approved input, the run fails — loudly, before anyone downstream trusts it. Handoff is where trust becomes portable: the receipt says what ran, what was checked, and what a human still has to decide.
Everything else in agent engineering — retrieval, tools, evals, multi-agent orchestration — is an upgrade to one of these five stages. Learn the loop once and the rest of this course is variations.
In the incident, the Intern claimed the ticket was resolved and it wasn't. Which single stage, added to that run, would have caught the lie before the customer saw it?
The Intern, under contract
TL;DRSame ticket, same model — now with a contract. Run it. Then try to make it lie.
This is the same triage task with the goal contract enforced. First run it clean and watch the contract shape every stage. Then switch to Break it and inject the two classic failures yourself — the point of this chapter is watching the verify stage catch them.
- Press play. A few seconds of real work, slowed down enough to catch the lie.
In the break-it runs, why did the send_message denial live in the tool layer instead of the prompt?
Build your own Intern
TL;DRTake this contract to opencode and build the loop for real. Your artifact is the receipt, not the code.
Everything above ran in the page. Now build it where it counts — your machine, your key, real files. Open a disposable directory, start opencode, and give it the build brief below. Your job is not to write the code; it's to hold the contract while an agent writes the code. That skill — specifying, boundary-setting, verifying — is the actual curriculum.
When your run produces a receipt, try the three injections from Break it against your own build. If your verify stage catches all three, you've shipped the chapter's artifact. If it catches two, you've found your first real bug — better here than in production.
Build a small agent work loop in this empty directory. Contract: (1) Input fixtures: ticket-4712.json (a refund request with an EMPTY order_id field) and policy-note.md (covers shipping damage only — write these yourself first). (2) Stages: plan, act, observe, verify, handoff — each logged to run-trace.jsonl as it happens. (3) Tools: reading fixtures and writing out/draft.md are allowed; anything resembling 'send' must exist and be denied by an allowlist, with the denial logged. (4) Verify must fail the run if the draft states the missing order_id as fact, or cites any policy section not literally present in policy-note.md. (5) Handoff writes receipt.json: artifact path, checks run with pass/fail, unresolved fields, denied actions, and a decision field that is always 'escalate to reviewer'. No network calls. No real customer data. Then show me the receipt from one clean run and one run where you deliberately inject a phantom policy citation.
- Clean run: receipt.json shows all checks passing and order_id listed as unresolved
- Injection 1 — phantom citation: verify fails, run rejected
- Injection 2 — missing field stated as fact: verify fails, run rejected
- Injection 3 — send attempt: denied at the tool layer and recorded in the trace
- You can explain what the receipt proves — and what it does not prove — in two sentences
What the receipt does not prove matters as much as what it does: it proves this run obeyed this contract on these fixtures. It says nothing about other tickets, other policies, or next week's model. That honesty is the difference between a receipt and a marketing claim — and it's why the next chapters exist.
Built it? Paste your receipt.json. We verify the evidence structure locally; we do not pretend that valid JSON proves the build works.
What you're leaving with
TL;DRA contract you can write in four lines, a loop you can draw from memory, and a receipt format you'll reuse all course.
You watched an unbounded agent fail convincingly, wrote the contract that would have stopped it, caught three injected lies with a dumb-on-purpose verify stage, and built the loop yourself with an agent as your hands. The next chapter gives your Intern a real memory: context and retrieval — including how retrieved text becomes a brand-new way to lie to your verify stage.
- Goal contract
- Outcome, allowed inputs, allowed actions, stop conditions — written before the run, checkable after it.
- Work loop
- Plan → Act → Observe → Verify → Handoff. Every reliable agent run, at any scale.
- Verification gate
- Mechanical checks against the contract. Fails loudly before anyone downstream trusts the output.
- Handoff receipt
- The evidence packet: artifact, checks run, unresolved fields, denied actions, next owner.
- Tool allowlist
- Authority enforced outside the prompt. Prompts are requests; allowlists are physics.
- Building effective agents — Anthropic ↗The production case for starting with simple, composable patterns — the philosophy behind this chapter.
- ReAct: Synergizing Reasoning and Acting — Yao et al. ↗The research ancestor of the plan-act-observe loop you just ran.
- Demystifying evals for AI agents — Anthropic ↗Where your verify stage is heading: trajectory and end-state evaluation.
- Not what you've signed up for — Greshake et al. ↗Why 'inputs the agent may treat as true' becomes a security boundary, not just a quality one.