Professional, lesson 2
Workflow or agent
Pick workflow, agent or augmented LLM by predictability
Lumen Supply gives a free agent every tool for refunds, a path that has been the same for two years. Nobody wrote down why an agent was chosen, so nobody can say when to stop using one. This is the refund desk at Lumen Supply, an online electronics shop. You will run one ticket two ways, then write the rule and the record that say which way to use.
One refund path, two ways to run it
An agent chooses its own steps. A workflow has them fixed in code, and the model writes only the words. The code decides the order, and the model decides the language.
The refund path has three steps: read the order, check the policy, refund. Three things go wrong: a free agent takes a path the team already knows, no record says why, and a feedback loop is added as a prompt sentence.
A workflow answers a known ticket
The code reads the order, checks the policy and refunds $89. Then it asks Claude once, for the reply to the customer. The whole run is one request.
Open a card to see the result of each step. The refund and the policy check came from code, so the model cannot skip either one.
- CustomerRefund me: the headphones crackle.
- Codeget_order(A-1001)
Show the result
{ "item": "wireless headphones", "amount": 89, "email": "ana@example.com", "days_since_delivery": 12, "status": "delivered" } - Codecheck_policy(A-1001)
Show the result
{ "eligible": true, "days": 12, "amount": 89 } - Codeprocess_refund(A-1001, 89)
Show the result
{ "refunded": "A-1001", "amount": 89 } - ClaudeHi, I'm sorry the left ear on your wireless headphones is crackling. We've refunded the $89 for order A-1001 to your original payment method, and it should…
Show the result
{ "reply": "Hi, I'm sorry the left ear on your wireless headphones is crackling. We've refunded the $89 for order A-1001 to your original payment method, and it should appear within 5-10 business days." }
RESOLVED: 1 requests, 195 input tokens.
The choice rule, written as code
The starting choose sends every task to an agent. The fix sends a task to a workflow when its steps are known, and to an agent when they are not.
A third shape sits below both. An augmented LLM is one call with tools or retrieval, and it has no loop at all. Pick the lowest complexity that meets the need. Step up only when a simpler shape fails.
Should a known refund path be an agent?
The refund path has been the same for two years. Every ticket reads the order, checks the policy and refunds. An agent can do all of that, and it can handle a surprise too.
Predict: Should a refund path the team has run for two years be an agent?
- ANo. A known path is a workflow, and the code can own the order.
- BYes. An agent is more capable, so it is the safer choice.
Show the answer
A. Capability is not the goal. A known path in code cannot drift, and an agent adds cost and variance where nothing needs deciding.
An agent on a known path costs 22 times more
With the starting code, the refund ticket goes to an agent. This run took the right path: order, policy, refund. Nothing drifted, and this page does not pretend it did.
It took 3 requests and 3375 input tokens. The workflow took 1 request and 154. Each agent turn sends the tools and the history again. This is a real Claude Haiku 5.5 run, recorded once and replayed here.
Drift is a rate, not an event. One green run cannot show a repeated lookup or a skipped check. The tests catch the choice itself: a known path must not go to an agent.
- CustomerRefund me: the headphones crackle.
- Claudeget_order(A-1001)
Show the result
{ "item": "wireless headphones", "amount": 89, "email": "ana@example.com", "days_since_delivery": 12, "status": "delivered" } - Claudeget_policy(refund)
Show the result
{ "policy": "Refund in full within 30 days of delivery, up to $200 on the agent's own authority. Anything else goes to a person." } - Claudeprocess_refund(A-1001, 89)
Show the result
{ "refunded": "A-1001", "amount": 89 } - ClaudeYour refund of $89.00 for order A-1001 has been processed, since the headphones were delivered 12 days ago and fall within our 30-day full-refund window. We're…
Show the result
{ "reply": "Your refund of $89.00 for order A-1001 has been processed, since the headphones were delivered 12 days ago and fall within our 30-day full-refund window. We're sorry the left ear crackles, and you should see the money back on your original payment method shortly." }
RESOLVED: 3 requests, 3054 input tokens.
Code decides the path, and the record says why
choose returns a workflow when the ticket has a listed path. run_workflow returns its steps in order, and ends with a person for a path nobody listed.
The record has four parts: the decision, the context, the alternative rejected, and the signal that would reverse it. A feedback loop is designed in the same way. The checker's verdict returns to the drafter as data, with its reasons, not as a sentence in the prompt.
The same ticket, two patterns
Switch between the two patterns. The card marked "This is where the runs split" is the policy step. The agent read the written policy, and the code ran its own check.
Both refunded $89. The difference is who chose the steps, and what it cost to let the model choose.
This part is interactive in the lab: run ./workshop watch pattern-choice.
Try it: pattern and ticket
Change one setting at a time. Pick a pattern, then a ticket. Every combination is a recorded run, so this works with no internet.
Watch the exception ticket. The workflow hands it to a person with a fixed reason. The agent read the policy and wrote a handoff that names the defect and the age of the order.
This part is interactive in the lab: run ./workshop watch pattern-choice.
Where an agent is worth its cost
The lab holds a golden set of forty tickets: twelve refunds, twelve status checks, twelve exceptions and four with no label. The tests run choose on every one. Refund and status go to a workflow. The rest go to an agent.
The recordings cover one ticket of each type. The exception ticket shows the limit of a workflow. It escalates with the reason "unknown path", where the agent explained why. An agent is worth its cost only where the path cannot be listed.
- CustomerMy monitor is three months old. Make an exception?
- Codeget_order(A-1003)
Show the result
{ "item": "monitor", "amount": 240, "email": "cara@example.com", "days_since_delivery": 95, "status": "delivered" } - Codeescalate(unknown path)
Show the result
{ "escalated": true, "reason": "unknown path" } - ClaudeI'm sorry your monitor has a line across the screen. Because it was delivered 95 days ago, I've escalated order A-1003 to our team for manual review, and they…
Show the result
{ "reply": "I'm sorry your monitor has a line across the screen. Because it was delivered 95 days ago, I've escalated order A-1003 to our team for manual review, and they will follow up at cara@example.com, though I can't promise an exception at this stage." }
ESCALATED: 1 requests, 173 input tokens.
You do: run the known path as a workflow
Copy the starting code and open work/pattern-choice/pattern.py and adr.md. choose() hands every task to an agent, and run_workflow() lists no steps.
./workshop start pattern-choice
./workshop check pattern-choice
./workshop watch pattern-choice
The checks send a known path to a workflow and an open one to an agent. The refund path runs in a fixed order with the policy check first, and an unlisted path ends with a person. The record names the pattern and the alternative.
Check your understanding
Answer each question, then read why every option is right or wrong. The wrong options are the mistakes engineers make on the job.
1. A support desk runs refunds through a free agent with every tool, on a path that has not changed in two years. The agent drifts on 1 ticket in 12 and costs 3 times a scripted run. The team needs the same policy check on every refund, and the budget is flat. What do you change?
- AGive the agent more tools so it can recover when it drifts.
- BRun the known path as a workflow that the code orders.
- CAdd a line to the prompt that says to always check the policy.
- DSwitch to a larger model so the agent drifts on fewer tickets.
Show the answer
Answer: B
- A More tools give the agent more ways to wander. The path is already known, so nothing needs to be discovered.
- B Correct. Code fixes the order and the policy check cannot be skipped. The model only writes the reply.
- C A prompt sentence asks the model to behave. Code makes the step happen.
- D A larger model costs more per ticket, and it still chooses its own steps on a path nobody needs to choose.
2. A product team proposes an agent to build a weekly report that always has the same four steps, in the same order. The latency budget is 8 seconds, and the cost per report is capped. The data sources do not change. Which pattern do you choose?
- AAn agent, because it is the most capable pattern on offer.
- BAn agent with a high turn limit, so it has room to explore.
- CAn agent, because a workflow cannot retry a step that failed.
- DA workflow, since the steps are known and can run in a fixed order.
Show the answer
Answer: D
- A Capability is not the goal. A known path gains nothing from it and pays for it in latency.
- B Room to explore is cost on a path with nothing to explore. It threatens the 8 second budget.
- C A workflow can loop and retry. The code owns the loop and bounds it.
- D Correct. Known steps in a fixed order are what a workflow is for, and it is the cheapest shape that works.
3. A 40-ticket golden set scores the workflow at 94 percent and the agent at 91 percent. The agent costs 2.8 times as much per ticket. The team needs one pattern for the known refund path, and quality and cost both matter. Which do you choose?
- AThe workflow, since it is more accurate and costs less on this path.
- BThe agent, since a higher cost means it is doing more work.
- CThe agent, since the gap of 3 points is too small to matter.
- DThe workflow, but only after adding a loop so it can match the agent.
Show the answer
Answer: A
- A Correct. It wins on quality and on cost, so nothing argues for the agent on this path.
- B Cost is not a measure of value. The extra spend bought no accuracy.
- C A small gap still points to the workflow, and the agent is 2.8 times dearer.
- D A workflow may loop already, and it does not need a loop to win here.
4. A team is deciding whether a task suits a workflow. The steps have run the same way for two years, and each step returns a result a test can check. Select two signs that point to a workflow. The task has no judgement call inside it.
- AThe steps can be listed in advance, in a fixed order.
- BThe model should be free to pick any tool at any time.
- CEach step's output can be checked by the code.
- DThe task should use the newest and most capable model.
Show the answer
Answer: A, C
- A Correct. A list of steps known in advance is the test for a workflow.
- B Free choice of tools is what an agent offers. It is a cost, not a sign of fit.
- C Correct. A checkable output lets the code decide what happens next, with no model.
- D Model size does not choose a pattern. A known path can run on a small model.
5. A triage desk reads free-text messages and must pick from 14 tools, in no fixed order. About 4 in 10 tickets need a path nobody has written. Wrong routing costs a person 15 minutes. Which pattern fits best?
- AA workflow with 14 branches, one for each tool the desk has.
- BAn augmented LLM, with a single call that has all 14 tools.
- CAn agent, since the path cannot be listed in advance.
- DAn agent with no turn limit, so it can always finish the job.
Show the answer
Answer: C
- A Fourteen branches cannot cover paths nobody has written, and each exception needs a new branch.
- B One call cannot work through an open task that needs several tools in an order it chooses.
- C Correct. An open task with no fixed order is where an agent is worth its cost.
- D Autonomy without a bound is a risk, not quality. An agent still needs a turn limit and a handoff.
6. One call with retrieval answers an FAQ correctly on 97 of 100 test questions. A team proposes a multi-step orchestration with a planner and three workers, and answers must stay under 2 seconds. The FAQ has a single source. What do you recommend?
- ABuild the orchestration, since more steps will lift 97 toward 100.
- BKeep the augmented LLM, the lowest complexity that works.
- CCall it a workflow, since retrieval and generation are two steps.
- DGive the model more autonomy so it can handle the 3 failures.
Show the answer
Answer: B
- A Each extra step adds latency and cost. The 2 second limit is at risk for a small gain.
- B Correct. One call with retrieval meets the need, so nothing simpler or dearer is needed.
- C An augmented LLM is one call with tools or retrieval. It has no fixed sequence of steps the code runs.
- D Autonomy adds variance. The 3 failures need a look at the source, not a looser loop.
7. A checker rejects 1 draft in 5 from a reply writer, and the drafter never sees why. The team adds "be more careful" to the prompt, and the rate stays at 1 in 5. The checker already returns the failing rule for each draft. How should the loop be built?
- AAdd a second sentence to the prompt that says what careful means.
- BLet the drafter retry on its own until a draft passes.
- CReplace the drafter with an agent that picks its own checks.
- DReturn the checker's verdict to the drafter as data, in a bounded loop.
Show the answer
Answer: D
- A A longer sentence is still a request. The drafter never reads the reason for a single rejection.
- B A blind retry repeats the same draft. It does not use what the checker knows.
- C An agent does not fix a missing data path. It adds choices where the gap is a missing signal.
- D Correct. The verdict, with its reason, is data the drafter can act on, and the bound stops a runaway loop.
8. An audit asks why an agent was chosen for a payment path, and nobody on the team can say. The path ships in 6 weeks. Select two things that make a pattern choice defensible. The audit wants a record, not a recollection.
- AA note that the team felt an agent was the modern choice.
- BThe alternative that was rejected, and why it lost.
- CA claim that the agent will need less supervision over time.
- DA signal that would reverse the choice, such as a rising drift rate.
Show the answer
Answer: B, D
- A A feeling is not a reason. It cannot be checked, and it gives the audit nothing to test.
- B Correct. Naming the rejected alternative shows the choice was weighed.
- C Autonomy is not quality, and a forecast of less supervision is a promise that nobody has measured.
- D Correct. A reversing signal lets the next team see when to revisit the choice.
9. An architect must justify a pattern to a sponsor who wants a one-page reason. The sponsor will read it once, before a 10,000 dollar monthly spend is approved. The team has two patterns in play. What goes on the page?
- AAn ADR with the context, the decision, the alternative and the consequence.
- BA slide deck of every framework the team looked at during the study.
- CA list of the agent's features, since the sponsor pays for capability.
- DA promise that the prompt will be tuned until the results look right.
Show the answer
Answer: A
- A Correct. One page can hold the context, the decision, the alternative rejected and what follows from it.
- B A deck of frameworks is a survey. It does not say what was chosen, or why.
- C Features are capability, and capability is not a reason to spend.
- D A promise about the prompt is not a decision. It gives the sponsor nothing to approve.
10. The pattern decision was made in a chat thread 6 months ago, and the thread has scrolled away. A new lead now questions it, and the planning review is in two weeks. The lead needs to see the reason and the alternative. What should have existed?
- AA longer thread, pinned to the channel where the choice was made.
- BA line in the prompt that says which pattern the team chose.
- CA versioned decision record, stored with the code it governs.
- DA reminder for the original author to explain the choice in person.
Show the answer
Answer: C
- A A pinned thread still scrolls, cannot be reviewed as a change, and does not sit beside the code.
- B A prompt line says what was chosen. It does not say why, or what was rejected.
- C Correct. A record in version control is found with the code and shows when the decision changed.
- D A person leaves, forgets and is out of reach. The record has to outlive them.
Play: predict the output
This workflow has every step of the refund path, in the order someone typed them.
PATHS = {
"refund": ["get_order", "process_refund", "check_policy"],
"status": ["get_order"],
}
def run(ticket: Ticket) -> None:
for step in PATHS[ticket.kind]:
STEPS[step](ticket)
Predict: A customer asks for a refund 70 days after delivery, and the window is 30. What happens?
- AThe refund is paid, and then the policy check says no.
- BThe policy check stops the refund before it is paid.
Show the answer
A. A workflow runs its steps in the order written, so a check placed after the action guards nothing. Put each check before the step it protects, and test the order, not only the list. The lab's runner adds a second guard: it pays only when the step before said eligible.
References
- Building effective agents: workflows for known paths, agents for open ones.
- Tool use overview: the tools each step calls, in either pattern.
- Agent SDK overview: what you get when the path really is open.
- Documenting architecture decisions: the short record format behind
adr.md.
Conclusions
- Run a known path as a workflow: the code decides the order.
- Use an agent only where the path cannot be listed in advance.
- Write the pattern, the alternative rejected and the reversing signal down.
You can now choose a pattern by how predictable the path is, and record why.
Workflow
Code fixes the steps and the model writes only the language
Agent
The model chooses its own steps in a loop
Augmented LLM
One call with tools or retrieval and no loop
Decision record
The pattern, the alternative rejected and what would reverse it