Agent & workflow patterns (Building Effective Agents)¶
At a glance
Priority: P0 · Complexity: ⅗ · Est. time: 3 h · Phase: 1 · Prereqs: Prompting & structured outputs, Tool calling You're done when: given a use case you can pick the least agentic pattern that meets the quality bar, sketch it as a graph, name its failure modes and controls, and justify it with an eval rather than intuition.
Why it matters¶
"Agent" is the most overloaded word in the industry. Anthropic's Building Effective Agents (Dec 2024, still the reference in 2026) drew the line that most practitioners now use:
- Workflows: LLMs and tools orchestrated through predefined code paths.
- Agents: LLMs dynamically direct their own process and tool usage, deciding how many steps to take.
The core advice — start with the simplest thing; add agency only when it demonstrably improves outcomes — is what separates production systems from demos. Most successful "agents" in enterprises are mostly workflows with one or two agentic steps. As an architect you'll be asked to choose patterns, justify cost/latency/reliability, and explain failure modes. Every framework (LangGraph, Pydantic AI, OpenAI Agents SDK, Google ADK, MS Agent Framework) implements these same patterns with different ergonomics.
Core concepts¶
The augmented LLM¶
The building block is an LLM with retrieval, tools, and memory. Everything below composes calls to it. Get this unit right first — good tool design (tool calling) and context (context engineering) matter more than the orchestration pattern.
The five workflow patterns + the agent loop¶
flowchart LR
subgraph Chain["1. Prompt chaining"]
A1[LLM 1] --> G1{gate} --> A2[LLM 2] --> A3[LLM 3]
end
subgraph Route["2. Routing"]
R0[Router LLM] --> R1[Handler A]
R0 --> R2[Handler B]
R0 --> R3[Handler C]
end
subgraph Par["3. Parallelisation"]
P0[Input] --> P1[LLM] & P2[LLM] & P3[LLM] --> PA[Aggregate]
end
subgraph OW["4. Orchestrator-workers"]
O0[Orchestrator] -->|dynamic subtasks| W1[Worker] & W2[Worker] --> OS[Synthesise]
end
subgraph EO["5. Evaluator-optimizer"]
E1[Generator] --> E2[Evaluator] -->|feedback| E1
end
subgraph AG["6. Autonomous agent loop"]
L1[LLM decides] --> L2[Tool call] --> L3[Observe] --> L1
end
| Pattern | Use when | Cost/latency | Main failure mode | Control |
|---|---|---|---|---|
| Prompt chaining | Task decomposes into fixed steps | Sequential latency, predictable | Error propagates down the chain | Programmatic gates/validation between steps |
| Routing | Distinct input categories need different handling/models | +1 cheap call | Misroutes | Labelled eval of router; "other" → fallback/human |
| Parallelisation (sectioning / voting) | Independent subtasks, or need confidence via multiple samples | Parallel → low latency, higher cost | Aggregation conflicts | Deterministic aggregation, majority vote, thresholds |
| Orchestrator-workers | Subtasks not known up front (e.g. which services to inspect) | Variable | Over-decomposition, lost context at boundaries | Cap workers, structured worker outputs |
| Evaluator-optimizer | Clear evaluation criteria and iteration helps (drafting, code) | 2–4x calls | Endless loops, evaluator too lenient | Max iterations, calibrated evaluator |
| Agent loop | Open-ended, unpredictable number of steps, trusted environment | Unbounded without limits | Loops, drift, compounding errors, runaway cost | Step/tool/cost budgets, checkpoints, HITL, sandboxing |
The agent loop, precisely¶
# Pseudocode for every "agent" framework's core loop
messages = [system, user]
for step in range(MAX_STEPS):
resp = llm(messages, tools=TOOLS)
if resp.stop_reason != "tool_use":
return resp.final_answer
for call in resp.tool_calls: # may be parallel
result = execute(call) # authz, validation, timeouts, idempotency here
messages += [call, result]
raise StepBudgetExceeded
Everything else (ReAct, "plan-and-execute", reflection) is a variation: ReAct interleaves reasoning and actions; plan-and-execute has one call produce a plan then executes steps (cheaper, more predictable, but brittle when the plan is wrong — re-plan on failure); reflection adds a critique step.
Reliability maths: why agency is expensive¶
If each step succeeds with probability p and a task needs n dependent steps, naive success ≈ pⁿ: 0.95¹⁰ ≈ 0.60, 0.99¹⁰ ≈ 0.90. Agents recover from some errors (they observe and retry), so reality is better than pⁿ, but the direction holds: every added step is a place to fail. Workflows hard-code the steps you already know are needed, spending model judgement only where it's required.
Choosing: a decision procedure¶
- Can a single well-designed call (with retrieval + structured output) meet the bar? Stop.
- Are the steps known in advance? → chain (with gates) or route.
- Independent sub-parts or need confidence? → parallelise.
- Sub-parts depend on the input and aren't enumerable? → orchestrator-workers.
- Quality improves with critique against clear criteria? → evaluator-optimizer.
- Genuinely open-ended, environment gives ground-truth feedback (tests pass, query returns), and errors are cheap/reversible? → agent loop with budgets, checkpoints, and HITL for irreversible actions.
Multi-agent systems (several autonomous agents collaborating) are a further step with their own failure modes — see multi-agent systems.
Controls every agentic system needs¶
- Budgets: max steps, max tool calls, max tokens/cost per run, wall-clock timeout.
- Stop conditions: explicit "done" output type; detect repeated identical tool calls (loop detection).
- Checkpointing: persist state per step so you can resume, replay, and debug — see LangGraph and durable execution.
- Human-in-the-loop for irreversible or high-blast-radius actions.
- Least-privilege tools, sandboxing, and injection defences — see guardrails.
- Tracing of every step — see LLM observability.
- Evals at two levels: end-to-end task success and per-step (router accuracy, tool-call validity).
The capstone's shape¶
The Agentic Ops Copilot deliberately mixes patterns:
flowchart TB
U[Alert or engineer question] --> RT[Router: small model, enum intent]
RT -->|question about runbooks| RAG[RAG answer chain]
RT -->|investigate incident| OR[Orchestrator: reasoning model]
RT -->|other| H[Human / fallback]
OR -->|parallel| LA[Log analyst sub-agent]
OR -->|parallel| MA[Metrics sub-agent]
OR -->|parallel| RB[Runbook RAG sub-agent]
LA & MA & RB --> SYN[Synthesise hypotheses]
SYN --> EV{Evaluator: evidence cited?}
EV -->|no, max 2| OR
EV -->|yes| ACT{Proposed action?}
ACT -->|restart / rollback| HITL[Human approval interrupt]
ACT -->|none| OUT[Summary to Slack]
HITL --> OUT
Router (routing) → orchestrator-workers with parallel workers → evaluator gate → HITL. Only the orchestrator is a true agent loop.
What juniors miss¶
- Starting with a multi-agent framework for something a chain solves.
- No budgets → a stuck agent burns $200 overnight.
- Not separating deciding (LLM) from doing (code with authz and validation).
- Evaluating only the final answer, so they can't tell which step broke.
- Treating framework choice as the architecture; the pattern is the architecture.
Resources¶
| Resource | Type | Why this one | Level | Cost |
|---|---|---|---|---|
| Anthropic — Building effective agents | article | The reference taxonomy of workflows vs agents, with when-to-use guidance | intermediate | free |
| 12-Factor Agents (HumanLayer) |
article | Opinionated engineering principles: own your control flow, small focused agents, pause/resume | intermediate | free |
| Lilian Weng — LLM Powered Autonomous Agents | article | Planning, memory, tool use — conceptual foundations behind ReAct/reflection | intermediate | free |
| Simon Willison — Designing agentic loops |
article | Practical view of tools, sandboxes and goals for coding-agent loops | intermediate | free |
| Hugging Face — AI Agents Course | course | Hands-on, framework-spanning implementations of the patterns | intermediate | free |
| LangGraph docs — overview | docs | How the patterns map onto graphs, state, and checkpoints | intermediate | free |
| Chip Huyen — AI Engineering (book repo) | book | Chapter on agents: planning, failure modes, evaluation in a systems context | advanced | paid |
Hands-on lab¶
Goal: implement three patterns in plain Python (no framework) for the same task and compare them with numbers — the baseline you'll later port to LangGraph. (2 h)
Task: "Given an alert, produce a root-cause hypothesis with cited evidence." Use stub tools with canned data: get_recent_deploys(service), query_logs(service, window), get_metrics(service, metric, window), search_runbooks(query).
- Chain: fixed steps — deploys → logs → metrics → runbook → synthesise (one LLM call at the end with all results).
- Orchestrator-workers: orchestrator LLM outputs a structured plan (
list[Subtask]), workers run in parallel withasyncio.TaskGroup, synthesiser combines. - Agent loop: the loop pseudocode above with
MAX_STEPS=8, loop detection (same tool + args twice → inject a warning), and a cost counter. - Create 15 scenarios with known root causes (bad deploy, DB saturation, upstream dependency outage, config change, red herring alert).
- Score: root cause correct (exact label), evidence cited (bool), LLM calls, tokens, latency.
Expected shape:
pattern correct cited calls tokens p50_s
chain 10/15 15/15 1 9.2k 4.1
orchestrator-workers 12/15 14/15 4.3 14.8k 6.0
agent-loop 13/15 12/15 6.7 31.5k 14.2
Write down which scenarios each pattern failed and why — this is your first error analysis. Decide which pattern the capstone orchestrator uses and record it as an ADR.
Questions¶
L1 — Recall¶
Q1. What distinguishes a workflow from an agent in Anthropic's taxonomy?
Answer
A workflow orchestrates LLM calls and tools through predefined code paths — the developer decides the control flow. An agent lets the LLM decide its own process: which tools to call, in what order, and when it's done, typically in a loop with environment feedback. Workflows give predictability and lower cost; agents give flexibility for open-ended tasks at the cost of latency, cost, and compounding-error risk.
Q2. List the five workflow patterns and one use case for each.
Answer
(1) Prompt chaining — extract fields → validate → draft a customer email. (2) Routing — classify a query to billing/tracking/technical handlers or to small vs large models. (3) Parallelisation — sectioning (check guardrails in parallel with answering) or voting (3 samples to judge severity). (4) Orchestrator-workers — decide which services to investigate for an incident, then investigate each. (5) Evaluator-optimizer — generate a postmortem draft, evaluate against a rubric, refine.
Q3. What controls must wrap an autonomous agent loop in production?
Answer
Step, tool-call, token/cost and wall-clock budgets; explicit completion criteria; loop detection; per-step checkpointing for resume/replay; human approval for irreversible actions; least-privilege, validated, idempotent tools with timeouts; sandboxing for code execution; injection defences on untrusted inputs; full tracing; and evals for both end-to-end success and per-step decisions.
L2 — Apply¶
Q4. A 6-step dependent workflow has per-step accuracy of 97%. What's the naive end-to-end success and what would you do about it?
Answer
0.97⁶ ≈ 0.83. Options: add programmatic gates/validators after the steps with highest error to catch and retry failures; merge steps where one call can do two reliably; raise per-step accuracy with better context/examples or a stronger model on the weakest step (find it via per-step evals); add a final verifier. Measure per-step error rates — the fix is usually concentrated in one or two steps.
Q5. Implement loop detection for an agent that keeps calling query_logs with the same arguments.
Answer
import hashlib, json
from collections import Counter
seen: Counter[str] = Counter()
def fingerprint(name: str, args: dict) -> str:
return hashlib.sha256(f"{name}:{json.dumps(args, sort_keys=True)}".encode()).hexdigest()
def guard(name: str, args: dict) -> str | None:
fp = fingerprint(name, args)
seen[fp] += 1
if seen[fp] == 2:
return (f"You already called {name} with these exact arguments and got the result above. "
"Use that result, change the arguments, or finish.")
if seen[fp] >= 3:
raise RuntimeError("loop detected") # escalate / end run with partial result
return None
Q6. Your router misroutes 9% of queries. How do you improve it without upgrading to a bigger model first?
Answer
Do error analysis on the misroutes: are categories overlapping or ill-defined? Fix the taxonomy (merge/split), write crisp definitions with boundary examples, add 1–2 few-shots per confusable pair, add an other/uncertain class routed to a safe default, and output a short reason before the label. Evaluate on a labelled set (≥ 100 examples, stratified) with a confusion matrix. If still weak and volume is high, fine-tune a small classifier or use embeddings + kNN. Upgrade the model only after the data says the task is hard, not ill-posed.
L3 — Design & trade-offs¶
Q7. Plan-and-execute vs ReAct-style loop for incident investigation. Trade-offs?
Answer
Plan-and-execute: one planning call produces steps; execution is mostly deterministic/cheap models; fewer expensive calls, easier to show/approve the plan (good for HITL), predictable cost. Brittle when early findings should change the plan — mitigate with re-planning after each phase. ReAct: decides after each observation, adapts naturally to surprises (the log shows a DB error → pivot to DB metrics), but costs more calls, can wander, and is harder to bound. For incidents, a hybrid works: plan a first wave of parallel checks, then a bounded ReAct phase to chase the strongest hypothesis, with re-planning allowed at most twice.
Q8. When is evaluator-optimizer worth its 2–4x cost, and how can it go wrong?
Answer
Worth it when there are clear, checkable criteria and the first draft is often fixable: code (tests/linters as evaluator — best case, ground truth), structured documents against a rubric, translations with terminology checks. Failure modes: evaluator is the same model and shares blind spots (sycophantic approval); vague rubrics → random feedback; oscillation between versions; unbounded iterations. Controls: deterministic evaluators where possible, calibrated LLM judges (validated against human labels), max 2–3 iterations, stop on no-improvement.
Q9. Your team wants to build the copilot as five autonomous peer agents chatting in a group. Argue for or against.
Answer
Against as a starting point. Peer group-chat architectures multiply calls and tokens, make control flow emergent and hard to debug, and suffer from information loss and conflicting actions between agents. The copilot's sub-tasks are well-understood (logs, metrics, runbooks) and parallelisable — orchestrator-workers with structured worker outputs gives the parallelism and specialisation benefits with a single point of control, clear budgets, and simpler tracing. Revisit multi-agent only for genuinely separate ownership domains or when an eval shows gains that justify cost.
L4 — Staff-level ambiguity¶
Q10. Leadership wants 'autonomous agents' in every product line by next year. How do you shape this into something safe and valuable?
Answer
Reframe the goal from "agents" to outcomes (hours saved, resolution time, error rates). Offer a maturity ladder: assistive (suggestions) → workflow automation with human approval → bounded autonomy on reversible actions → broader autonomy with monitoring. Provide a platform: paved-road framework, tool registry with authz, tracing, eval harness, HITL primitives, budget controls. Require each team to define success metrics and an eval set before building, and to justify each increase in autonomy with data. Pick 2–3 lighthouse use cases, publish results, and create a review board for high-risk actions. This keeps momentum while preventing a portfolio of fragile demos.
Q11. A vendor pitches a 'fully autonomous SRE agent' that can restart services and roll back deploys. How do you evaluate it?
Answer
Evaluate on your incidents: replay 50–100 historical incidents in a sandbox and measure correct diagnosis, correct action, time to mitigation, and harmful actions. Examine controls: permissions model (least privilege, scoped credentials), approval workflows, audit logs, blast-radius limits, kill switch, behaviour under prompt injection via logs/tickets, observability (OTel traces), data handling. Start in shadow mode (recommend only), then approval-required, then autonomy for a narrow set of reversible actions with auto-rollback. Contractual: SLAs, liability, model change notifications. Decide with a pilot scorecard, not a demo.
Real-world use cases¶
- Customer support triage (routing + chaining): intent router → specialised handlers; refunds require an approval gate.
- Incident copilot (orchestrator-workers + HITL): parallel evidence gathering, human approves mitigations.
- Coding agents (agent loop): tests and compilers provide ground-truth feedback — the ideal agent environment.
- Document processing (parallelisation): sections of a 100-page contract analysed in parallel, then aggregated.
- Marketing copy (evaluator-optimizer): draft → brand-guideline judge → refine, max two rounds.
Pitfalls & anti-patterns¶
- Agent where a chain suffices; multi-agent where one agent suffices.
- No step/cost budgets; no loop detection.
- LLM performs irreversible actions without approval or idempotency.
- Framework-first design ("we use X, so everything is a crew of agents").
- Only end-to-end evals; no per-step visibility.
- Plans without re-planning; ReAct without bounds.
Checklist¶
- I can draw all five workflow patterns + the agent loop and give a use case for each
- I implemented chain, orchestrator-workers and agent loop in plain Python and compared them on 15 scenarios
- I wrote an ADR choosing the capstone orchestrator pattern
- I can list the controls for an agent loop from memory
- I answered all L3 questions out loud in < 3 min each