EDNA Open Playbook
AI Agents That Actually Work
The open Enterprise DNA playbook for designing, building, evaluating and deploying agents inside real businesses.
Version 1.0.0 · Generated 23 July 2026 · CC-BY-4.0 content, Apache-2.0 code
Introduction
The Demo Is Not the System
The problem this playbook solves
A good demo is easy. You give the model a clean prompt, it produces a clean answer, and everyone in the room nods. Then you try to put that same idea into a real business and it falls apart. The inputs are messy. The task has twenty steps, not one. A wrong answer is not a funny screenshot, it costs money or breaks trust.
Here is the honest version. The model is not the whole system. The model is one part. The reliability lives in everything around it.
The core idea
An agent is only useful when it can see the work, do the work and prove the work was done. That single sentence is the thesis of this playbook. Most failed agent projects skip the first and third parts. They wire a model to a task, watch it produce text, and call it finished. But text appearing is not the same as work being done.
A useful business agent is built from five layers:
Business-ready agent = Model + Context + Tools + Workflow + Verification
- The model reasons and writes.
- The context is what it sees, when it sees it and what stays out.
- The tools are the safe, clear actions it can take in the real world.
- The workflow is the control loop that manages state, retries, stopping and proof.
- The verification is how you know the outcome is actually correct.
Take any one of these away and the system gets unreliable in a way that is hard to debug.
Why the demo lies to you
Look at the difference between a demo and a real deployment.
- A demo gets a clean prompt. A real business gets incomplete inputs.
- A demo runs once. A real workflow runs every day.
- A demo can be rescued by a human watching it. A real agent needs escalation and recovery built in.
- A demo looks finished when text appears. A real task is finished only when the outcome is verified.
None of this means agents do not work. It means the work is in the system around the model, and that is exactly what the next ten chapters build.
How to read this
There are three paths through the book, and you can switch at any time.
- Executive: the mental model, where agents pay off, what can go wrong and what a credible deployment looks like. About 90 minutes.
- Operator: turn one real process into a controlled agent workflow. Three to four hours with a few labs.
- Builder: the full architecture and every core lab. Eight to twelve hours.
What changes after this chapter
You stop asking “can the model do this” and start asking “can the whole system see the work, do the work and prove it.” That is the question the rest of the playbook answers.
Next: Chapter 1, What an AI Agent Actually Is.
Chapter 1
What an AI Agent Actually Is
The real business problem
People use the word agent for very different things. A chatbot is called an agent. A single API call is called an agent. A twenty step automated workflow is called an agent. When the word means everything, it helps no one decide what to build or what to buy.
So before any code, you need a definition you can actually reason with.
The core idea
An agent is a system that takes a goal, decides the next step on its own, takes that step using tools, looks at the result and repeats until the goal is met or it stops. The important part is “decides the next step on its own.” That is what separates an agent from a fixed script.
A simple test. If you can draw the whole thing as a flowchart where every branch is known in advance, you have a workflow, and a workflow is often the right answer. If the path depends on what the model finds along the way, and the number of steps is not fixed, you have an agent.
A simple model
Think of three levels.
- A prompt is one question and one answer. No memory of the task, no actions in the world.
- A workflow is a fixed sequence of steps, some of which may call a model. The steps do not change based on the result.
- An agent is a loop. Goal, decide, act, observe, repeat. The steps are chosen at run time.
Most real business systems are a mix. A fixed workflow that hands a few hard, open ended sub tasks to an agent is usually more reliable than one giant agent that tries to do everything.
A concrete example
Take “prepare a weekly account summary for each client.” A pure prompt cannot do it, because the data lives in several places. A fixed workflow can pull the data and format it, but it struggles when a client has an odd situation the template did not expect. An agent can handle the odd cases, decide which numbers matter and write the exceptions in plain language. The best build uses a workflow for the predictable parts and an agent only for the judgement.
What breaks
The most common mistake is reaching for an agent when a workflow would do. Agents are harder to test, cost more per run and fail in stranger ways. Use the smallest tool that solves the job. There are cases where you should not use an agent, and knowing them is part of the skill.
Decision rules
- If the path is fully known in advance, build a workflow, not an agent.
- If the task needs judgement on unpredictable inputs, an agent earns its place.
- If a wrong answer is expensive, the agent needs verification before you trust it, which is Chapter 8.
Related lab
Map an Agent-Worthy Workflow. You will take a real process from your own work, score it, and decide whether it deserves an agent at all.
Practical checklist
- You can state the goal in one sentence.
- You can say what “done” means and how you would check it.
- You have decided workflow, agent, or a mix, and you can say why.
What changes after this chapter
You have a definition you can defend in a meeting and use to choose the right tool. Next you learn how to pick the work that is actually worth automating.
Next: Chapter 2, Pick Work Worth Automating.
Chapter 2
Pick Work Worth Automating
The real business problem
Most agent projects die at the whiteboard, not in the code. Someone picks a task that sounds impressive, the team builds around it for a month, and then it never gets trusted enough to run on its own. The model was fine. The work was wrong.
The failure is almost always the same. The task had no clear finish line, or the inputs were a mess, or nobody could tell whether the output was actually right without redoing the work by hand. When that is true, no amount of clever prompting saves you.
So before you touch a model, you need a way to look at a piece of work and say, honestly, whether an agent belongs anywhere near it. That is what this chapter gives you. After it, you will be able to score a real task, rank a few candidates and pick a first use case you can defend to a room full of skeptical people.
The core idea
The right work to automate is not the most exciting work. It is the most checkable work that also has real value.
That distinction matters more than anything else in this playbook. Exciting work is the demo that makes people say wow. Checkable work is the task where you can look at the result and know, quickly and cheaply, whether it is correct. An agent you cannot check is an agent you cannot trust, and an agent you cannot trust gets switched off within a week.
So you are hunting for the overlap of four things. Real value if it runs without you. A clear boundary around what it does and does not touch. Inputs that are good enough to act on. And an outcome you can verify without redoing the whole job. Miss any one of those and the project gets shaky in a way that is hard to fix later.
A simple model
Score every candidate task from one to five on four dimensions. Keep it on one page.
- Value if automated. How much time, money or risk does this remove if it runs on its own. Low value work is not worth the build cost, even when it is easy.
- Boundary clarity. Can you say in one sentence what the task does and where it stops. Fuzzy scope is the single biggest red flag on this list.
- Input quality. Are the inputs complete, consistent and available. Messy or missing inputs raise the cost of everything downstream.
- Verifiability. How easily can you tell the output is correct. This is the one people skip, and it is the one that decides whether you can ever trust the thing.
Add the four scores. A task that lands high on all four is a strong first candidate. A task that scores a nine because it is dazzling on value but a two on verifiability is a trap, and the sum hides it. Look at the shape, not just the total. One low score, especially on boundary or verifiability, should stop you.
A concrete example
Take an accounting firm choosing its first agent. Three candidates come up.
| Candidate task | Value | Boundary | Input quality | Verifiable | Read |
|---|---|---|---|---|---|
| Draft a monthly management report per client | 5 | 3 | 3 | 4 | Strong, once scoped tightly |
| Answer any client question by email | 4 | 1 | 2 | 2 | Exciting, uncheckable, avoid |
| Categorise bank transactions for review | 4 | 5 | 4 | 5 | Best first use case |
The email answering agent is the one everyone wants to demo. It also has no boundary and no cheap way to check it was right before a client reads it. The transaction categoriser is boring by comparison. It also has a clear scope, clean inputs and an outcome a human can verify in a glance, because a category is either sensible or it is not. Start there. Win trust on the boring, checkable task, then move up the ladder.
Notice the report task in the middle. Good value, but the boundary score is soft. If you narrow it to one report type with a fixed template, the boundary score climbs and it becomes a real second candidate. Scoping is not just measurement. It is how you turn a shaky task into a buildable one.
The implementation pattern
Here is the pattern I use to go from a list to a decision.
- List three to five processes you repeat every week. Real ones from your own work, not aspirations.
- Write the goal of each in one sentence. If you cannot, the boundary is not clear enough yet. That is useful information, not a failure.
- Score all four dimensions, one to five. Be honest on verifiability. Ask “how would I know this was wrong” and if the answer is “I would have to redo it,” score it low.
- Rank by shape, not just sum. Kill anything with a one or two on boundary or verifiability, however high the value.
- Pick one. Write two sentences on why it wins. That written reason is the thing you defend later when someone asks why you did not start with the flashy one.
Once you have your winner, you face a second decision. Do you build it, buy it, or bring in a specialist. Match the choice to how standard the task is and how much of your real edge lives inside it.
| Route | Use it when | Watch out for |
|---|---|---|
| Buy an existing tool | The task is common and someone already sells a good agent for it | Your data or process is odd enough that the tool cannot bend to fit |
| Build it yourself | The task carries your real edge, or no tool fits your inputs and checks | You underestimate the verification and workflow layers, not the model |
| Bring in a specialist | High value, high risk, and you lack the in-house skill to build it safely | Handing over a task you have not scoped, so the specialist scopes it for you |
The order matters. Look for something to buy first, because a task common enough to be sold is rarely worth building from scratch. Build when the work carries your edge or the checks are specific to you. Bring in help when the value is high, the risk is real and the skill is not in the room yet. In every case you still do the scoring first. A specialist handed an unscoped task will scope it for you, and you will pay for that twice.
What breaks
The second failure is choosing on excitement. The demo-worthy task and the trustworthy task are rarely the same task, and the difference does not show up in a five minute pitch. It shows up three weeks later when nobody can tell if the output is right.
Decision rules
There are also tasks you should simply not hand to an agent. Anything where a wrong answer is expensive and cannot be caught before it lands. Anything where the rules change constantly and there is no stable definition of correct. Anything that is really a judgement call your customers expect a named human to own. Knowing these cases is not caution. It is the skill.
Related lab
The lab turns this chapter into a worksheet. You take three to five real processes from your own work, score each on value, boundary clarity, input quality and verifiability, then pick one first use case and write down why it wins. It is a one page opportunity map, not a strategy deck, and it is the highest leverage hour you will spend in this book.
Related lab Map an Agent-Worthy WorkflowPractical checklist
Before you move on
What changes after this chapter
You stop picking agent projects by what looks impressive and start picking by what you can check. That one change removes most of the reasons agent projects fail before any code is written. You now have a scored, defensible first use case instead of a wish.
Next: Chapter 3, Give the Agent the Right Context.
Chapter 3
Give the Agent the Right Context
The real business problem
You give an agent a task and it hands back a confident, wrong answer. You look closer and the reason is almost always the same. It did not have the right information in front of it, or it had far too much and could not tell which part mattered.
This is a context problem, not a model problem. A strong model with the wrong context will fail. A modest model with clean context usually does the job. Most of the reliability you get out of an agent comes from one decision. What does it see, when does it see it, and what do you keep out.
After this chapter you will be able to split an agent’s information into three separate kinds, feed it knowledge on demand instead of dumping everything in, and name the things you deliberately leave out. The worked example is a research and brief agent, the kind of thing that turns a company name into a one page brief before a meeting.
The core idea
Context is not one thing. It is three things that people cram into a single prompt and then wonder why the agent gets muddled.
- Stable instructions. Who the agent is, the rules it always follows, the format it must produce. This barely changes from one run to the next.
- Task state. The specific job right now. The client name, the question, the sources found so far, the running notes. This changes every run and often every step.
- Retrieved knowledge. The facts it needs to answer well. Policy documents, past reports, product data, pricing. This is large, mostly irrelevant to any one task, and should be pulled in a few pieces at a time.
Keep these three separate in your head and in your build. When they blur together you get an agent that forgets its own rules halfway through, or drops last week’s client details into this week’s report.
A simple model
STABLE INSTRUCTIONS role, rules, output format loaded every run, never edited + TASK STATE this client, this question, changes every step notes so far + RETRIEVED KNOWLEDGE the 2 or 3 docs needed now pulled on demand, then dropped | v [ context window ] -> model -> next step
Think of the context window as a desk, and the desk is small. You do not stack the whole filing cabinet on it. You put down the standing rules, the job you are working on, and the two or three files you actually need for the step in front of you. Everything else stays in the cabinet until it is needed.
A concrete example
Take a research and brief agent. The job is simple to state. Given a company and a question, produce a one page brief a partner can read before a meeting.
- Stable instructions: you are a research analyst, you cite every claim, you never invent numbers, the brief is 300 words across three sections. Fixed for every run.
- Task state: the company is Acme Freight, the question is whether they fit our audit service, and here are the four sources found so far with short notes on each. This grows as the run goes.
- Retrieved knowledge: your own past briefs on similar firms, the fit scoring rubric, the service description. Pulled in only at the moment the agent needs them.
Now watch what happens if you paste all of that into one giant prompt on every step. The run slows down. It costs more, because you pay per token on every single step and you are re-sending the whole rubric each time. Worst of all, the agent starts bleeding the rubric wording into the brief, or quoting a past client by name because that brief was sitting in the window. Separate the three and each step stays clean and cheap.
The implementation pattern
Here is the pattern that holds up in real use. It is four moves, and none of them are exotic.
1. system_prompt = role + rules + output format # written once, loaded every run
2. task_state = { company, question, # small structured object,
sources_found[], draft{}, step } # updated each step, not free text
3. needed = agent.decide_what_to_look_up(task_state)
chunks = document_store.search(needed, top_k = 3) # retrieve, do not dump
4. window = system_prompt + task_state + chunks # assemble fresh each step
result = model(window)
A few things to hold onto.
Write the system prompt once. Role, rules, output format. Load it on every run and never edit it mid task. This is the layer that keeps the agent behaving like itself.
Hold task state as a small structured object, not a growing wall of text. A short record of the company, the question, the sources with one line notes, and the draft so far. Update it each step. Structured state is easy to trim, easy to inspect, and easy to hand to a human when something goes wrong.
Retrieve, do not dump. When the agent needs a fact, search your document store and pull the top few matching chunks, not the whole library. This is retrieval, often called RAG. The point is not the acronym. The point is that the agent reads three relevant paragraphs instead of three hundred irrelevant ones.
Trim as you go. After a step is done, drop the retrieved chunks you no longer need. Keep the task state, keep the rules, let the rest go.
What breaks
Decision rules
Related lab
The Research and Brief Agent lab is where this becomes real. You build the three layer split by hand, wire a small document store, and watch the difference between dumping everything into one prompt and retrieving three clean chunks. You will feel the cost drop and see the answers get sharper. The same pattern carries straight into a document to report agent, which is the next lab up.
Related lab Research and Brief AgentPractical checklist
Before you move on
What changes after this chapter
You stop treating the prompt as a bucket you fill to the top. You start designing the window on purpose, one layer at a time, with a clear answer to what goes in, what stays out, and what gets pulled fresh. That single shift removes a large share of the wrong answers people blame on the model.
Next: Chapter 4, giving the agent safe tools so it can act on the world, not just describe it.
Chapter 4
Give It Tools That Are Safe and Clear
The real business problem
A model on its own cannot do anything in your business. It can write a great email, but it cannot send it. It can describe the perfect invoice, but it cannot post it to your accounting system. It can summarise a contract, but only if someone hands it the contract first.
Tools are how the agent reaches out of the chat and into the real world. And this is exactly where most agent projects turn dangerous. The moment you give a model a button that sends money, deletes records or emails a customer, a wrong guess stops being a funny screenshot and starts costing you.
So the skill in this chapter is not “connect the agent to your systems.” Anyone can do that. The skill is connecting it so the agent can act usefully without creating chaos when it gets something wrong. After this chapter you will be able to write a tool contract that is clear enough for the model to use correctly and safe enough that a bad call cannot do real damage.
The core idea
A tool is a function you hand the agent, described in plain language, that it can choose to call. The model does not run your code. It reads your description of the tool, decides it is the right one, fills in the inputs and asks the system to run it. The system runs it and hands the result back.
That means the model is reading a contract, not your source code. If the contract is vague, the agent guesses. If the contract is clear, the agent behaves. Everything good about tools comes from writing that contract well, and everything bad comes from leaving it loose.
A good tool contract has six parts.
- A clear name that says what it does.
get_invoiceis good.helper2is not. - A plain description of when to use it and when not to.
- Typed inputs so the model cannot pass a date where a number belongs.
- Safe defaults so a missing field does the harmless thing, not the expensive one.
- A predictable output the model can read the same way every time.
- Useful errors that tell the agent what went wrong and what to try next.
Get those six right and the agent uses the tool the way a careful person would.
A simple model
The split that matters most is read tools versus write tools.
A read tool looks at the world. It pulls a document, fetches a balance, lists open tickets. If it runs twice, nothing bad happens. You can be generous with read tools.
A write tool changes the world. It sends an email, posts an invoice, updates a record, charges a card. If it runs twice, you have a problem. Write tools need a tighter contract, narrower permissions and a way to survive being retried.
Read tool (safe to repeat) Write tool (handle with care)
agent asks -> get_document agent asks -> post_report system reads the doc system checks the idempotency key returns the text if new: makes the change run twice -> same result if seen: returns existing result no harm done run twice -> one report, not two
A concrete example
Take a common job. Every Monday, someone on your team opens last week’s activity document for a client, reads it, and posts a short status report into your project tool. It is not hard. It is just repetitive and easy to skip.
Two tools do it. get_document pulls the client’s activity doc by id and returns its text. post_report takes a client id, a title and a body, and posts the report. The agent reads the document, decides what matters, writes the summary and posts it.
get_document is a read tool. If it runs twice, you have read the same doc twice. No harm. post_report is a write tool. If it runs twice, the client now has two identical reports and someone has to go and clean that up. Same agent, same task, but the two tools need very different care.
The implementation pattern
Here is what a clean write-tool contract looks like. The shape matters more than the language.
{
"name": "post_report",
"description": "Post a status report to a client's project. Use only after get_document. Do not call twice for the same week.",
"input_schema": {
"type": "object",
"properties": {
"client_id": { "type": "string", "description": "The client's id from the CRM. Required." },
"title": { "type": "string" },
"body": { "type": "string", "description": "Plain text, 80 to 200 words." },
"week_of": { "type": "string", "description": "Monday of the week, as YYYY-MM-DD. Used to prevent duplicates." },
"draft": { "type": "boolean", "description": "If true, save without publishing. Defaults to true." }
},
"required": ["client_id", "body", "week_of"]
}
}
Three things are doing the safety work here. The description tells the model exactly when to use the tool and warns it off double posting. The inputs are typed, so week_of cannot arrive as a number. And draft defaults to true, so the harmless outcome is the default. If the agent forgets to set it, you get a draft a human can check, not a report already sent.
Now handle the retry. Agents retry. The network drops, a run restarts, the workflow fires twice. If post_report inserts a row every time it is called, retries create duplicates. The fix is idempotency. Give each write a key that describes the exact action, here the client and the week, and make the tool refuse to do the same thing twice.
key = "report:" + client_id + ":" + week_of
if key already recorded:
return { status: "already_done", report_id: existing_id }
else:
create the report
record the key
return { status: "created", report_id: new_id }
Now a retry is safe. The second call sees the work is done and returns the existing result instead of making a new one. Idempotency is the single most important habit for any tool that spends money or contacts a customer.
The last piece is errors. When a tool fails, do not throw a raw stack trace at the model. Tell it what happened in words it can act on.
{ "status": "error", "code": "client_not_found",
"message": "No client with id C-4821. Check the id or call list_clients first." }
With that, the agent can recover. A raw “500 Internal Server Error” gives it nothing, so it either gives up or guesses. A clear error tells it the next move.
What breaks
Least privilege fixes most of this. A tool should do exactly one job and nothing more. Not “query the database” but “get this client’s last invoice.” Not “send email” but “send the weekly report to this client’s saved address.” You are not trying to make the agent weak. You are making sure that when it is wrong, and it will sometimes be wrong, the blast radius is one client and one week, not your whole customer list.
Decision rules
Related lab
The Document to Report Agent lab builds the exact two-tool pattern from this chapter. You write get_document and post_report, give the write tool an idempotency key, then trigger a retry on purpose and watch the tool do the safe thing instead of posting a second copy. It is the smallest complete example of a read tool and a write tool working together.
Practical checklist
Before you move on
What changes after this chapter
You stop thinking of tools as “connect the agent to my systems” and start thinking of them as contracts. A read tool can be generous. A write tool earns trust with typed inputs, safe defaults, idempotency and clear errors. That distinction is what lets an agent act in a real business without keeping you up at night.
Next: Chapter 5, The Workflow Control Loop, where these tools get run inside a loop that manages state, retries and stopping.
Chapter 5
Design the Workflow and Control Loop
The real business problem
You built the tool layer in the last chapter. The agent can read the sales export, query the ledger and write a note. So you point it at a real task and watch. It calls one tool, gets a messy result, calls another, forgets what it already found, tries the same thing three times, then hands you a confident paragraph that turns out to be wrong.
The model was never the problem here. What is missing is the part that runs the agent. The loop that decides what to do next, remembers what already happened, retries the flaky steps, stops before it burns your budget, and checks the answer before it calls the job done.
That runner is the workflow, and it is where reliability lives. After this chapter you can take a raw model that “kind of works” and wrap it in a control loop that carries state, knows when to stop, and proves the outcome before you trust it. That is the difference between a demo and something you can run every morning without watching it.
The core idea
An agent works in a loop. Plan the next step, act on it with a tool, observe the result, decide whether to keep going or stop. Round and round until the goal is met.
Left alone, that loop has three ways to hurt you. It forgets what it learned two steps ago. It never stops. It declares victory the moment it produces text. A control loop is the small amount of engineering that fixes all three. It holds state, it caps the work, and it refuses to call anything done until the outcome is checked.
Write the loop’s job in one line. Keep taking sensible next steps toward a goal, remember the work so far, and prove the result before you hand it over.
A simple model
GOAL | v PLAN —> ACT —> OBSERVE —> update STATE ^ | | v | done enough? | | | +--- no, under caps ------+ | yes (retry / next step) v VERIFY | | pass | | fail v v REPORT STOP + escalate
Six moving parts do the real work. Plan, Act and Observe are the visible loop. State is the memory that survives between passes. The caps are the brakes. Verify is the proof. Take away the last three and you are left with the naive loop that forgets, runs forever and lies about being finished.
A concrete example
Take a data-to-decision agent. The goal is one sentence. “Look at last month’s numbers for this client and tell me whether to raise, hold or cut their retainer, with the reason.”
A single prompt cannot do this. The numbers live in a spreadsheet export and the billing system, not in the prompt. So the agent runs the loop.
- Plan. It needs revenue, hours logged and last quarter’s baseline.
- Act. Pull the revenue export.
- Observe. The file has two months in it, not one. It writes that fact into state.
- Plan. Filter to the right month, then pull the hours.
- Act and observe again, updating state after each step so it never re-reads what it already has.
- Decide. It has enough to form a view. Raise, hold or cut, with a number and a plain reason.
Then the part most people skip. Before it answers, it verifies. It re-adds the line items and checks the total against the figure it is about to quote. If the recomputed total does not match, that is not a formatting nit. It is a wrong answer, and the loop goes back a step instead of shipping it. Only a matched total earns the recommendation.
The implementation pattern
Five things turn the raw loop into something you can run every day.
1. Carry state, do not trust the transcript. Keep a running record separate from the chat history. The goal, the facts gathered so far, what has been tried, what failed. Pass a compact summary of that record into each step, not the entire history. If the agent cannot see what it already found, it repeats work and contradicts itself two steps later.
2. Retry with backoff, and know when to give up. Tool calls fail for boring reasons. A slow API, a rate limit, a dropped connection. Retry, but wait a little longer each time, and cap the attempts.
attempt 1 -> fail -> wait 1s
attempt 2 -> fail -> wait 4s
attempt 3 -> fail -> stop, record the reason, escalate
The other half of this is telling apart a flaky failure from a real one. A timeout is worth retrying. A missing file or a rejected login is not. Retrying a real error forever just wastes money on a call that will never work.
3. Delegate the hard sub-tasks. When one step is a big open-ended job of its own, like reading a 40-page contract or reconciling two ledgers, hand it to a sub-agent with its own small loop and a narrow goal. The main loop stays simple and just receives the answer. Do not delegate the easy steps. A sub-agent for a one-line lookup only adds cost and another thing that can fail.
4. Set stopping conditions before you run it. Every loop needs hard limits. A maximum number of steps, a maximum spend or token budget, and a wall-clock timeout. When any limit trips, the agent stops and reports where it got to. This is the difference between a run that costs 20 cents and one that quietly costs 40 dollars because it got stuck on an odd input. Numbers here are illustrative, but the shape is real. Set the ceiling on purpose, do not discover it on your bill.
5. Prove completion. The loop does not end when text appears. It ends when a check passes. The check depends on the task. Recompute the total and compare it. Confirm the file was actually written. Re-read the record you claim you updated and see the new value there. If the check fails, loop again or escalate to a person. Text is a claim. The check is the evidence, and evidence is the only thing worth trusting.
What breaks
Decision rules
Related lab
Data to Decision Agent. You will build the exact loop from the example above. An agent that pulls real numbers, forms a recommendation, and then verifies its own total before it is allowed to answer. You will set the step and cost caps, watch it retry a failing pull, and see the proof step reject an answer that does not add up. It is the shortest path from reading about the control loop to owning one.
Related lab Data to Decision AgentPractical checklist
- You can state the goal and the stop condition in one sentence each.
- Your loop carries state between steps, not just the last message.
- Retries back off and give up after a fixed cap, and you tell flaky failures apart from real ones.
- There is a hard limit on steps, cost and time, set on purpose.
- The task counts as done only when a specific check passes, and you can name that check out loud.
What changes after this chapter
You stop shipping agents that produce text and start shipping agents that produce checked results. The loop is no longer a hopeful while-loop that runs until something appears. It is a controlled process with memory, limits and proof. The proof step is the whole point. It is what turns “the model wrote an answer” into “the work was done and I can show it.”
Next: Chapter 6, where the loop grows a longer memory and holds context across tasks that do not finish in a single run.
Chapter 6
Add Memory Without Creating a Mess
The real business problem
Someone tries an agent, it forgets what happened two steps ago, and the obvious fix seems to be “give it memory.” So they turn memory on for everything. The agent starts remembering. It also starts remembering things that are no longer true.
Now you have a new problem that is worse than forgetting. The agent confidently repeats a price that changed last month, greets a client by an old contact’s name, or acts on a preference the customer dropped a year ago. Stale memory is harder to catch than no memory, because the output looks complete and sounds sure of itself.
Memory is not a switch you flip on. It is three different tools that solve three different problems, and most of the mess comes from using the wrong one, or storing things you should have looked up fresh. This chapter gives you a way to use each one on purpose.
The core idea
There are three kinds of memory, and they are not interchangeable.
- Session memory is short-term. It holds the state of the task you are doing right now and disappears when the job ends.
- User or account memory is longer-term. It holds a few stable facts about a person or account that should survive between sessions.
- Knowledge retrieval is not really memory at all. It is looking something up from a store that stays the source of truth, at the moment you need it.
The single most useful distinction in this whole chapter is the last one. Memory is what the agent carries forward and writes down. Retrieval is what it fetches fresh. Anything that changes on its own, without the agent touching it, belongs in retrieval, not memory. Get that line right and most of the mess never happens.
A simple model
| Kind | Lives for | Good for | Wrong for |
|---|---|---|---|
| Session memory | One task run | The current multi-step job, what was decided so far | Anything you need next week |
| User or account memory | Across sessions | Stable preferences, standing instructions, settings | Fast-changing facts like balances or statuses |
| Knowledge retrieval | Not stored, fetched each time | Large or changing reference material, the system of record | Tiny stable facts you could just remember |
Read the table as a decision, not a menu. Start by asking whether the fact changes on its own. If it does, retrieve it. If it does not and you need it later, it is user memory. If you only need it until this job finishes, it is session memory. Most facts fit one box cleanly. The ones that do not are usually a sign you are about to store something you should look up.
A concrete example
Take an accounting firm that runs an agent to draft client correspondence. Each of the three kinds of memory has a clear job.
Session memory holds the thread the agent is working on right now. Which client, which letter, what it has drafted so far. When the letter is done, that state is gone, and that is correct.
User memory holds a small number of stable facts. The firm’s house style, that this partner signs off as “Kind regards” not “Best,” that this client prefers plain English over jargon. These change rarely, so storing them is safe and saves re-explaining every run.
Retrieval handles the numbers. The client’s current balance, their latest invoices, what they have paid. The agent pulls these from the ledger at the moment it drafts, every time.
Here is the failure that teaches the whole lesson. Imagine the agent stores “this client owes 4,200” in memory to save a lookup. That number is an example, not a real figure, and that is the point. Next month the client has paid, the balance is different, and the agent sends a letter with the wrong amount to a real customer. The fix is not better memory. The fix is that a balance is never memory. It is always a fresh lookup, because the ledger, not the agent, owns that fact.
The implementation pattern
Keep the three stores physically separate. When they blur together, you lose the ability to reason about what is safe to trust.
1. Session state lives in the run. It is part of the control loop from the last chapter, not a database. It starts empty, fills during the task, and is discarded at the end. Do not persist it “just in case.”
2. User memory is a small, keyed, timestamped store. Not a growing pile of notes. A handful of fields per account, each with what it is, when it was written, and where it came from. Something like this:
{
"account_id": "acme-legal",
"key": "correspondence_style",
"value": "plain English, no jargon",
"written_at": "2026-07-23",
"source": "client request 2026-07-23",
"expires_at": null
}
Only write an entry when it is a stable fact or an explicit correction from the user. “Draft it shorter next time” is worth storing. “The invoice total is X” is not, because X moves.
3. Expire things that have a shelf life. Give volatile entries an expires_at and drop them on read once they pass it. A standing style preference has no expiry. A note about a temporary situation should die on its own. Expiry is what keeps the store from slowly filling with facts that were true once.
4. Handle contradictions on purpose. When a new fact conflicts with an old one, take the newest by timestamp and, where it matters, surface the conflict rather than silently picking. Silent overwrites are how memory quietly drifts away from reality.
5. Retrieve against the source of truth. For anything the business already stores, the ledger, the CRM, the document system, pull it fresh through a tool. Retrieval does not go stale the way stored memory does, because you are reading the current value every time.
Memory hygiene and privacy
Three rules keep a memory store clean.
What to write: stable preferences, standing instructions, and explicit corrections. Things that will still be true next month and that save real effort by not being re-derived.
What to expire: anything time-bound. Statuses, temporary arrangements, prices, anything with a shelf life. Tag it with an expiry when you write it.
What to never store: secrets, card numbers, passwords, and full copies of sensitive customer records. Do not copy the system of record into agent memory by default. Store a pointer, an account id or a record reference, and fetch the sensitive detail on demand. A memory store is one more place data can leak from, so the safest sensitive data is the data you never put there.
This is the difference between memory and retrieval showing up as a privacy control. Retrieval reads from the system that already owns the data, under its existing access rules. Memory makes a second copy that you now have to secure, keep current, and eventually delete. Prefer the lookup.
Practical checklist
Before you move on
What changes after this chapter
You stop treating memory as a single feature to switch on and start treating it as three tools with different jobs. The question is no longer “should the agent remember this,” it is “is this a stable fact I store, a task detail I hold for one run, or a value I look up fresh.” That one habit removes most stale-fact bugs before they reach a customer, and it keeps sensitive data where it belongs.
Next: Chapter 7, where memory and retrieval feed into giving the agent the right context at the right time.
Chapter 7
Build Guardrails and Human Approval
The real business problem
An agent that can only read is safe and mostly useless. The value shows up the moment it can act, which is the moment it can also do harm. It can email the wrong client, refund the wrong customer, delete a record you needed, or send an invoice with a number that is off by a zero.
The instinct is to solve this with trust. You watch it for a week, it behaves, so you let it run. That is not a control. That is luck with a delay.
The real control is deciding, in advance, what the agent is allowed to do on its own, what it may do as long as it leaves a trail, and what it must never do without a human saying yes first. This chapter shows you how to draw those lines and how to build the approval step that enforces the top one. After this you will be able to point at any action your agent takes and say who signed off on it and why.
The core idea
Not every action carries the same risk, so not every action should get the same freedom. Sort actions onto a ladder with three rungs.
- Low risk. Reversible and internal. Reading data, drafting a summary, categorising a ticket, proposing a reply. If it gets this wrong, you delete the output and move on. The agent just does it.
- Medium risk. Reversible but it touches something real. Updating a CRM field, moving a file, posting to an internal channel, creating a draft invoice. The agent does it, but it writes a log entry so you can see what changed and undo it.
- High risk. Irreversible, outward facing, or expensive. Sending an external email, paying or refunding money, deleting records, changing a price, signing anything. The agent may prepare the action, but a human approves it before it happens.
The whole skill is putting each action on the right rung. Too low and you get harm. Too high and you get an agent that needs a human for everything, which is just a slow human.
A simple model
RISK LADDER APPROVAL LOOP (high risk only)
low -> ACT 1. PROPOSE agent writes the exact action medium -> ACT + LOG | high -> HOLD ----------> 2. HOLD action is frozen, nothing sent | 3a. APPROVE ---> 4. ACT run it, log the result 3b. REJECT ---> stop, record the reason (or timeout expires -> stop)
The approval step is a small state machine, and treating it as one is what keeps it honest. The agent does not send and then ask forgiveness. It writes down the exact action it wants to take, freezes it, and waits. A human approves or rejects. Only an approval moves it to the act state. Silence is not approval. If nobody answers by the deadline, the proposal expires and nothing happens.
A concrete example
An agent handles accounts receivable. It drafts the monthly invoice for each client and is meant to email them out.
Drafting the invoice from the timesheet data is low risk, so it just does that. Saving the draft and updating the account record is medium risk, so it does that and logs it. Emailing the invoice to the client is high risk, because it is outward facing and it is about money, so it holds.
What it holds looks like this. The recipient is priya@northwind.example. The subject is “Northwind invoice, July.” The attachment is invoice-1042.pdf, total 4,200 dollars, which is an illustrative figure. The agent presents that exact package and waits. A person reads it, notices the total should have been 2,400 dollars because half the month was on a fixed fee, rejects it with that reason, and the agent revises. Nothing left the building. The audit trail now shows the catch and the correction, which is worth as much as the fix.
The implementation pattern
Build the approval step as a record, not a pause in a script. A pause in a script dies when the process restarts. A record survives, and you can see it, query it, and audit it later.
When the agent hits a high-risk action, it does not call the tool. It writes a proposal and stops. The proposal captures everything a human needs to decide without going digging.
{
"id": "prop_8842",
"action": "send_email",
"risk": "high",
"payload": {
"to": "priya@northwind.example",
"subject": "Northwind invoice, July",
"attachment": "invoice-1042.pdf",
"amount": 4200
},
"reason": "Monthly invoice run, client on time-and-materials",
"status": "hold",
"expires_at": "2026-07-25T17:00:00Z",
"created_by": "ar-agent",
"created_at": "2026-07-23T09:12:00Z"
}
The rules that make this safe are boring on purpose.
- The action list is a whitelist, not a blacklist. The agent can only call tools you have granted it. A high-risk tool checks for an approved proposal id before it runs and refuses without one. That refusal lives in the tool, not in the prompt, because a prompt can be argued with and a code check cannot.
- Approve or reject is a separate step by a separate identity. The thing that approves is not the agent. A person clicks approve, or a second system with its own authority does. The approver’s identity gets stamped on the record.
- Rejection carries a reason, and the reason goes back to the agent so the next attempt is better, not a blind retry of the same mistake.
- Proposals expire. A held action that nobody answers should die, not linger for a week and fire when someone finally clicks. Set a deadline and let silence mean no.
Now handle the case where the agent is not confident enough to even propose. This is escalation, and it is the other half of guardrails. Give the agent explicit conditions to stop and ask rather than guess.
- It is missing information it needs, like a client with no email on file.
- It hits conflicting instructions, like two rules that both apply and disagree.
- Its own confidence in the next step is low, and you have told it that low confidence on a real action means hand it to a person.
- The action it wants is outside its allowed set entirely.
In every one of those, the recovery path is the same shape. Stop, describe the situation plainly, hand it to a named human or queue, and do not proceed until you get an answer. An agent that guesses when it is stuck is more dangerous than one that does nothing, because the guess looks like work.
The last piece is the audit trail, and it is not optional the day something goes wrong. Every action, proposed or taken, writes one line. What was done, by which agent, when, on what inputs, and on whose approval. When a client calls and asks why they got a strange invoice, you should be able to answer in one query, not one afternoon. The trail is also how you tune the ladder. If a medium-risk action keeps causing cleanups, promote it to high. If a high-risk action gets approved unread every single time, ask whether it was ever really high risk, or whether your people have stopped reading.
Decision rules
Related lab
Add Human Approval to a High-Risk Action. You will take one real action from your own workflow, most likely an outbound email or a payment, and wrap it in the propose, hold, approve or reject, then act loop. You will see the agent stop at the gate, present the exact action, and refuse to proceed until you sign off. It is the smallest complete version of everything in this chapter, and it is the pattern you will reuse for every high-risk tool after.
Related lab Add Human Approval to a High-Risk ActionPractical checklist
Before you move on
What changes after this chapter
You stop trusting the agent because it has behaved and start trusting the system because it cannot misbehave in the ways that matter. The freedom the agent has is now a decision you made on purpose, written down, and enforced in code, not a habit that grew because nothing bad happened yet. That is the difference between an agent you can defend to a board and one you are quietly hoping stays lucky.
Next: Chapter 8, Verify the Work Was Actually Done.
Chapter 8
Evaluate Before You Trust It
The problem this chapter solves
You built the agent. You tried it, it produced a clean result, and you thought “that works.” Then you handed it real work and it made a mistake you never saw coming. This is the most common way an agent project fails after launch. Not because the model is bad, but because “it looked right when I tried it” was never evidence in the first place.
One good run tells you the agent can succeed. It does not tell you how often it succeeds, on which inputs it fails, or whether the change you made last week quietly broke something that used to work. For a demo, one run is enough. For a business system, you need to know the failure rate before you trust the agent with anything that costs money or touches a customer.
This chapter gives you the discipline that closes that gap. By the end you will be able to build a set of real tasks with known correct answers, grade the agent’s output automatically, catch regressions before they ship, and decide whether the agent is actually good enough to trust. This is where a demo becomes a system.
The core idea
The thesis of this playbook is that an agent is only useful when it can see the work, do the work and prove the work was done. Evaluation is how you prove it. If you cannot verify the outcome, the task is not finished. That is true of a single run, and it is true of the agent as a whole.
Evaluation here means what it means everywhere else in engineering. You collect a set of representative tasks, you know the correct answer for each one, you run the system against all of them, and you measure how many it got right. The result is a number you can act on. “The agent categorised 46 of 50 expense lines correctly, and the four it missed were all foreign currency” is a fact you can work with. “It looked right” is not.
The shift in mindset is this. Stop asking “did it work when I tried it.” Start asking “what is its score on the tasks I care about, and did that score go up or down since the last change.”
A simple model
An evaluation harness is a loop with four parts, and one idea sitting on top of them.
Task set ──▶ Run agent ──▶ Grade output ──▶ Score + failures ▲ │ │ ▼ └────────── Regression check on every change ◀───────┘
The four parts are the task set, the run, the grader and the report. The task set is real inputs paired with the known-correct outcome for each one. The run sends every task through the agent. The grader scores each output against its expected outcome. The report is a pass rate plus the exact list of what failed and why.
The idea on top is regression. Every time you change the prompt, the model, a tool or the workflow, you run the whole set again and compare the new score to the last one. A change that fixes one thing and breaks two others shows up straight away, instead of surfacing three weeks later in front of a client.
A concrete example
Take an agent that categorises expenses for a monthly bookkeeping close. In a demo it reads one invoice, picks the right account, and looks flawless.
To evaluate it, you build a task set of 50 real expense lines pulled from past months, each already assigned to the correct account by a bookkeeper you trust. That known-correct assignment is the expected outcome. You run the agent against all 50 and compare its account choice to the human’s, line by line.
Now you have a real number. Say it gets 46 right. You look at the four it missed. Three are foreign currency transactions and one is a refund it booked as an expense. That is not a vague worry, it is a specific and fixable set of failures. You improve the prompt, run all 50 again, and check whether you fixed those four without breaking the other 46. When the score is high enough and stays there, you trust the agent with this month’s real close. Not before.
The implementation pattern
Three moves build a working harness.
1. Build the task set. Pull 30 to 100 real examples, not invented ones. Include the messy cases: the odd invoice, the ambiguous request, the input that broke it last time. For each task, record the input and the expected outcome. Store them as plain files so they live in version control next to the code.
tasks/
expense-001.json { "input": {…}, "expected": { "account": "6-1200" } }
expense-002.json { "input": {…}, "expected": { "account": "6-4000" } }
…
2. Choose a grader per task. Not every task is graded the same way. There are three main kinds, and each one has an honest limit you should know before you rely on it.
- Exact match. The output must equal the expected value. This is right for account codes, yes or no answers, and extracted figures. It is objective and cheap. The limit is that it cannot judge anything open ended, and it will wrongly fail a correct answer that is simply worded differently.
- Rule-based check. The output must satisfy a rule you write in code. “Contains a valid invoice number.” “Total equals the sum of the lines.” “No dollar figure appears that is not in the source.” This is strong for structure and hard constraints. The limit is that it only checks what you thought to write a rule for.
- LLM as judge. A second model scores the output against a rubric you give it. This is the only practical way to grade open-ended writing, such as whether a client summary is accurate and clear. The limit is real and worth stating plainly. The judge is itself a model, so it can be wrong, it can be biased toward its own style, and it must never grade using the same prompt that produced the work. Pin it with a tight rubric, use it only for genuine judgement calls, and spot-check its scores against a human now and then.
Most real harnesses mix all three. Exact match and rules for anything you can pin down, an LLM judge only for the parts that truly need judgement.
3. Run, score and gate. Wire it so one command runs every task, grades each one, and prints a pass rate plus the list of failures. Set a bar, for example “must score at least 90 percent and never regress on a task it previously passed.” Run it before you trust the agent with live work, and run it again on every change.
$ npm run eval
expenses 46/50 (92%)
summaries 18/20 (90%, LLM judge)
REGRESSION expense-014 passed last run, fails now
That last line is the whole point. The regression check is what stops a quiet break. A change that lifts the summary score but breaks an expense case that used to pass is not an improvement, and now you can see it before it ships rather than after a client does.
This is what evaluation-driven development means in practice. You write the check before you trust the work, and the check, not your gut, decides whether the agent is ready.
Decision rules
Related lab
The lab turns this chapter into a harness you can run on your own work. You will collect a real task set, write a grader for each type, wire the run-and-score command into one line, and add a regression check so a future change cannot quietly break what works today. You finish with a number you can point to instead of a feeling.
Related lab Build an Agent Evaluation HarnessPractical checklist
- You have 30 or more real tasks, including the hard and messy ones.
- Every task has a known expected outcome recorded next to it.
- Each task has a grader, and you chose the type on purpose.
- One command runs the whole set and prints a pass rate plus the failures.
- A regression check flags any task that used to pass and now fails.
- You run the eval before trusting the agent, and again on every change.
What changes after this chapter
You stop trusting the agent because it looked right once, and start trusting it because it scores well on the tasks that matter and holds that score when you change things. That is the line between a demo and a system you can put in front of a client. If you cannot verify the outcome, the task is not finished, and now you have the machinery to verify it.
Next: Chapter 9, where the same evaluation discipline moves from a pre-launch gate to a live signal you watch while the agent runs in production.
Chapter 9
Deploy, Observe and Improve
The real business problem
You passed the evaluation from Chapter 8, so you shipped. Then a run went wrong in a way you have never seen. The output looked fine, a client noticed the numbers were off, and now you are staring at a green “success” log with no idea what the agent actually did inside that run.
This is the moment most teams discover they built a black box. The agent produced text, the workflow marked it done, and nothing in between was recorded. You cannot debug what you cannot see, so you are left guessing, re-running the task by hand and hoping the failure repeats so you can catch it live.
Shipping is the start of the work, not the end. A demo runs once under your eye. A deployed agent runs every day on inputs you never tested, and it fails in ways the demo could never show. This chapter gives you the three things that turn a black box into a system you can run with confidence. Observability so you can see each step, cost control so a single bad run cannot drain a budget, and an improvement loop so every real failure makes the next version better. After it, you will be able to read a trace, name the root cause of a broken run, and feed that failure straight back into the tests from the last chapter.
The core idea
A deployed agent needs to be observable, affordable and improvable. Those are three different jobs and you need all three.
Observability means every run leaves a record of what the agent saw, what it decided, which tools it called, what came back and how it finished. Affordability means hard limits on tokens, tool calls and loops so no single run can spin forever or cost a fortune. Improvability means a loop where a real failure becomes a permanent test, so the same bug cannot come back quietly.
Skip observability and you debug by guessing. Skip cost control and one runaway loop teaches you the hard way. Skip the improvement loop and you fix the same failure over and over without ever proving it stays fixed.
A simple model
The unit of observability is the trace. One trace is one full run of the agent, from the goal that came in to the outcome that went out. Inside a trace are spans. A span is a single step, and steps nest. The top span is the whole run. Under it sit the model calls, the tool calls and the results, each with its own inputs, outputs, timing and cost.
TRACE weekly-summary run #4821 status: completed cost: 5,910 tok | +- span plan model call in: goal + context 1,020 tok +- span get_client tool call in: client_id=88 ok, 1 row +- span get_transactions tool call in: from/to dates ok, 0 rows # look here +- span decide model call in: 0 rows returned 1,400 tok +- span write_summary model call out: final report 3,490 tok | +- outcome “All figures nominal this week.” (no data was read)
The point of the tree is that it turns “it went wrong” into “it went wrong at this step, for this reason.” You stop arguing about the model and start reading the record.
A concrete example
Take an accounting firm running a weekly client summary agent. It pulls each client’s transactions, works out the movements that matter and writes a short plain-language report. It passed evaluation on twelve sample clients and shipped.
Three weeks in, a client asks why their summary says a quiet week when they had their biggest month ever. The output was confident, well written and completely wrong. Nothing in the plain log explains it. So you open the trace.
Notice what the trace did. It moved the blame off the model, which behaved as instructed, and onto the missing guard around the tool call. That is a fix you can actually make. Reject empty date ranges, make the tool return an explicit error on zero rows for a client that should have activity, and stop the run rather than narrate around a gap.
The implementation pattern
Here is the pattern I use to take an agent from “it runs” to “I can run it every day.”
- Instrument before you scale, not after. Wrap every model call and every tool call so each writes a span with its inputs, outputs, duration and token count. Most agent frameworks emit this if you turn it on. If yours does not, log it yourself. A run with no trace is a run you cannot defend.
- Give every run a trace ID and keep the traces. You want to pull up any run by ID weeks later, especially the one a client is asking about. Store enough to reconstruct the step sequence, not just the final answer.
- Set three budgets per run. A token ceiling, a maximum tool-call count and a maximum loop count. When a run hits a ceiling it stops and escalates instead of grinding on. As an illustrative starting point, you might cap a summary agent at 20,000 tokens, 15 tool calls and 8 loops, then tune from real traces. Those numbers are examples, not targets. Read your own traces to set yours.
- Add a spend alert above the budgets. Track cost per run and cost per day. Alert a human when a run costs several times the median, or when the daily total crosses a line you set. A runaway loop shows up as one trace with hundreds of spans. You want to hear about that within the hour, not at the end of the month.
- Watch a few signals, not a dashboard of fifty. Failure rate, escalation rate, median and worst-case cost, and median and worst-case latency. If those four are steady you are fine. When one moves, the traces behind it tell you why.
- Close the loop into your eval set. This is the step that makes the whole thing compound, so it gets its own section.
The improvement loop
The evaluation set from Chapter 8 is not a launch gate you pass once. It is a living record of every way this agent has been wrong. Production is where you find the cases you could not imagine at the whiteboard.
So every real failure follows the same path. Open the trace, find the root cause, then write a new test case that reproduces it and add it to the eval set. Fix the agent. Re-run the whole set. The new case now guards that bug forever, and every future change has to pass it. The empty-date-range failure above becomes a permanent test with a client who has a blank onboarding field and real transactions, asserting the run stops or errors rather than inventing a quiet week.
Do this for a few months and your eval set stops being a guess about what might break and becomes a map of what actually broke. That is the difference between an agent that drifts and an agent that gets steadily harder to fool.
What breaks
Decision rules
Related lab
The lab hands you the trace of a broken run and asks you to do the real job. You will read the span tree, follow the inputs and outputs step by step, name the exact point where it went wrong and the root cause behind it, then write the eval case that would have caught it. It is the single most useful skill in this chapter, because diagnosing a failure from its trace is what separates running an agent from babysitting one.
Related lab Trace and Diagnose a Failed RunPractical checklist
Before you move on
What changes after this chapter
You stop treating deployment as the finish line and start treating it as the point where the real feedback begins. A failed run is no longer a mystery and a source of dread. It is a trace you read, a root cause you name and a test you add. The agent gets more reliable every week instead of quietly drifting, and you can say exactly why, with the record to prove it.
Next: Chapter 10, The AI Operating Layer.
Chapter 10
Scale Into an AI Operating Layer
The real business problem
You got one agent working. It sees its work, does its work and proves the work was done. It has earned a place in the business. Now the obvious instinct kicks in. If one agent saved that much time, ten should save ten times as much. So you build a second, then a third, and somewhere around the fourth the whole thing starts to feel less like progress and more like herding.
The agents were never the hard part at this stage. Coordination is. Two agents touch the same customer record and overwrite each other. One finishes a job and nobody picks up the next step. A tool gets changed for one agent and quietly breaks three others. No single person can say what all of them did yesterday. You have not built a system. You have built a pile of bots that happen to share a login.
This chapter is about the jump from one good agent to many that work together. After it you will be able to see the coordination problems before they bite, treat your agents as one operating layer over the business instead of a heap of scripts, and know exactly where a human still belongs when the system, not a single task, is what needs watching.
The core idea
A collection of agents is only worth building if it behaves like one system with many parts, not many systems that ignore each other.
That is the whole shift. Everything from the earlier chapters still holds. Every agent still needs its Model, Context, Tools, Workflow and Verification. None of that goes away. What gets added at scale is a layer above the individual agents whose only job is to make them cooperate. Shared memory so they see the same facts. A shared set of tools so a fix in one place fixes it everywhere. Clear ownership so every job has exactly one agent responsible for it. Clean hand-offs so work moves between agents without dropping. And a human watching the system, not refereeing every task.
I call that the operating layer, because that is what it becomes. Done well, it runs the repeatable spine of the business the way an operations team does, and you supervise it. Done badly, it is a pile of bots and you spend your days untangling them.
A simple model
Picture four things sitting above the individual agents, with a person above all of it.
Human (system owner) watches the board, sets policy, takes escalations | +--------------------+---------------------+ | OPERATING LAYER | | shared context . tool registry | | ownership map . work queue | +----+---------+----------+----------+------+ | | | | Agent Agent Agent Agent intake report invoice triage | | | | +----- shared context + tools —+
- Shared context is the single source of truth every agent reads from and writes to. One customer record, not four private copies.
- A tool registry is the one place tools are defined, so every agent calls the same version and a change lands everywhere at once.
- An ownership map says which agent owns which job. No overlap, no gaps.
- A work queue is how a finished job by one agent becomes the next agent’s inbox, without a person carrying it across by hand.
Above all of it, a human owns the system. Not every task. The system.
A concrete example
Take a small accounting firm that already has one agent it trusts, the transaction categoriser from Chapter 2. It wants three more. An intake agent that sets up new clients. A reporting agent that drafts the monthly management report. An invoice follow-up agent that chases overdue payments.
Run them as four separate scripts and the seams show fast. Intake creates a client in the CRM. Reporting looks for that client in the accounting system, where it does not exist yet, and quietly produces a report for the wrong entity. Invoice follow-up emails a client the same afternoon the partner is on the phone smoothing over a complaint, because the two never shared a view of that account.
Now run them as an operating layer. Intake writes the new client once, into shared context every other agent reads. Reporting waits on a signal that the client is fully set up before it starts, and that signal lives on the work queue. Invoice follow-up checks a single shared flag, “a human is handling this account,” before it sends anything. Same four agents. The difference is entirely in the layer between them.
The implementation pattern
You do not build the operating layer up front. You grow it the first time two agents need to agree on something. Here is the order that has worked for me.
- Put shared state in one place. The moment a second agent needs a fact the first one produced, stop passing copies around. Give them one store both read and write. A database table is plenty. Private memory per agent is how you end up with four versions of the truth.
- Register tools once. Define each tool, its inputs and its guardrails, in a single registry every agent calls. When you tighten a permission, it tightens for all of them. This is the tools chapter again, applied across agents instead of inside one.
- Give every job exactly one owner. Write an ownership map, plain and boring. One agent per job. If two agents can both edit invoices, decide which one owns that and make the other one ask. Overlapping writers are the deadliest bug at this scale.
- Move work through a queue, not a handshake. When one agent finishes, it drops a task on a shared queue. The next agent picks it up when it is ready. Direct agent-to-agent calls build chains that fail in ways nobody can trace.
- Stop agents from touching the same record at once. Use a lock, a single-writer rule or a status flag so two agents never mutate the same thing at the same time. In a multi-tenant setup this is not optional. It is how you keep one customer’s agent from ever touching another customer’s data.
- Keep the human at the system level. The human stops checking individual outputs, which the verification layer now does, and starts watching the whole board. What is queued, what is stuck, what got escalated, what spend is running. Escalations from any agent land in one place a person actually looks at.
Every step is something you learned in an earlier chapter, now applied between agents instead of inside one. Context, tools, the control loop, guardrails, verification, observability. At this scale they compound. Skip any one for a single agent and you have a bad agent. Skip it across a fleet and you have a mess no dashboard can explain.
What breaks
The quieter failure is scale without observability. Ten agents, each fine alone, and no single place that shows what all ten did today. The first time one goes wrong you cannot find which one, because you never built the view. A fleet you cannot see is a fleet you cannot run.
Decision rules
And the case where you should not scale at all. If your one agent is not yet trusted to run without someone watching it, adding more does not multiply the value. It multiplies the babysitting. Earn full trust in one agent before you build the second.
Related lab
The capstone lab ties the whole book together. You build a multi-step operations agent that runs a real process end to end, then wire in the pieces this chapter describes, so a second and third agent could join it without stepping on each other. It is where context, tools, the control loop, guardrails, verification and coordination stop being separate ideas and become one working system you can point at.
Related lab Capstone: Multi-Step Operations AgentPractical checklist
Before you move on
What changes after this chapter
You stop thinking in single agents and start thinking in a system. The question is no longer “can this one agent do the job.” It is “can the whole fleet run the repeatable spine of the business without stepping on itself, with one person watching the board.” That is a different, harder and far more valuable question, and it is the one a real deployment lives or dies on.
Come back to where this book started. An agent is useful when it can see the work, do the work and prove the work was done. A fleet is useful when it can do all three together, without collisions, under one human at the system level. The demo was never the system. The system is the layer you just learned to build.
Next: the Capstone, where you build a multi-step operations agent that pulls every layer in this playbook into one working system. Start with the lab below.