02
Chapter 02 · Agent Design Patterns

Architectural blueprints
for reliable agents

agentic-ai / agent-design 4 modules  ·  ~45 min read  ·  Vol. I · 2026

Architectural blueprints for building agents that are reliable, composable, and maintainable — from simple single-agent loops to complex multi-agent orchestration. This chapter moves beyond theory and into the concrete patterns practitioners use daily: how to structure the core plan-execute cycle, when to introduce multiple agents, how to wire workflows together, and how to assign coherent roles that stay stable under pressure.

02.1 Single-Agent Loop One model, one context window, iterative tool use until goal is reached.
02.2 Multi-Agent Specialised agents coordinated by an orchestrator to parallelise or decompose tasks.
02.3 Workflow DAG Deterministic control flow with LLM nodes at decision or generation points.
02.4 Role & Persona Stable agent identities with bounded scope, preventing role collapse.
02.1
Module
Single-Agent Loops

Plan, execute, observe, repeat — the core agent loop

The single-agent loop is the foundation of every agentic system. Before you introduce multiple agents, orchestration frameworks, or complex memory architectures, you need to master this primitive: one model, a set of tools, a goal, and an iterative cycle that continues until the task is done or the budget is exhausted.

Planned Foundational

The Anatomy of a Loop

Every single-agent loop has four phases that repeat until a termination condition is met. Observe: the agent receives the current state — the user's goal, prior tool results, and any injected context. Think: the LLM reasons over this state, often generating a scratchpad, deciding what action to take next. Act: a tool call is executed — a search, a code execution, an API request — and the result is appended to the context. Evaluate: the agent checks whether the goal has been achieved; if not, it loops.

This pattern was formalised in the ReAct paper (Yao et al., 2022), which interleaved Reasoning traces with Action calls to dramatically improve performance on multi-step tasks. Modern implementations follow this same structure, though the framing has evolved from explicit Thought/Action/Observation tokens to native function calling.

ReAct Loop — Control Flow
User Goal
System Prompt + Context
LLM Reasoning (Thought)
Tool Call Decision
Tool Execution
Observation appended
Goal met?
→ No →
Loop back
→ Yes →
Final Answer

Termination Conditions

A loop without a reliable stop condition is a loop that will run until it times out or depletes your budget. There are three ways to terminate: the model signals completion (it returns a final answer rather than a tool call); a step budget is exhausted (hard limit on iterations, typically 5–20 for most tasks); or an external checker compares the output to the original goal and signals success. In practice, all three are used together — the model's own judgment is the primary exit, with step budgets as a safety backstop.

Setting the right step budget is important. Too low and the agent fails on legitimate complex tasks. Too high and it loops indefinitely when stuck. A good heuristic: estimate the minimum number of tool calls for the ideal solution, multiply by 2.5, and cap there.

Error Recovery

Single-agent loops fail in predictable ways: tool calls return errors, the model hallucinates a non-existent function argument, or the task is genuinely impossible. Robust loops handle errors by appending the error message as an observation and allowing the model to reason about it. Most capable models will naturally retry with corrected arguments. For persistent failures, implement a retry budget (separate from the step budget) and a fallback strategy — either escalate to a human or gracefully fail with a structured error response.

Design principle: Treat every tool result — including errors — as valuable signal. A model that sees "404 Not Found" can infer the resource doesn't exist and try an alternative approach. Never hide errors from the agent's context.

Step Budget Management

Track the remaining step budget as a system prompt variable, not just a silent counter. When the budget is low, inject this information: "You have 2 steps remaining. Prioritise completing the core task over supplementary research." This prompt injection at budget boundaries significantly reduces incomplete outputs and encourages the model to produce a best-effort answer rather than an abrupt stop.

Python · Single-agent loop skeleton
def run_agent(goal: str, tools, max_steps: int = 15):
    messages = [
        {"role": "system", "content": build_system_prompt(goal)},
        {"role": "user",   "content": goal},
    ]

    for step in range(max_steps):
        # Inject budget awareness near the limit
        if step == max_steps - 2:
            messages.append(budget_warning(max_steps - step))

        response = llm.chat(messages, tools=tools)

        if response.stop_reason == "end_turn":
            return response.text   # ✓ Model signals done

        for tool_call in response.tool_calls:
            result = execute_tool(tool_call)
            messages += format_tool_result(tool_call, result)

    return graceful_fail(messages)  # Budget exhausted
Key takeaways — 02.1
Always set a step budget. No exception. Even for simple tasks.
Errors are observations. Append them to context; the model will reason over them.
Inject budget awareness 2–3 steps before the limit to avoid abrupt failures.
Use structured output schemas to enforce completeness on the final answer.

“The single-agent loop is not a limitation — it is the right tool for 80% of tasks. Reach for multi-agent systems when you have a specific reason: parallelism, specialisation, or context isolation. Not because it feels more sophisticated.”

— agentic-ai / agent-design · 02.1
02.2
Module
Multi-Agent Systems

Orchestration, delegation, and shared-state management

Multi-agent systems allow you to parallelise work, specialise agents for specific domains, and break context window limits by distributing tasks. The cost is significant: coordination complexity, harder debugging, and emergent failure modes. This module covers the three primary topologies and when each is appropriate.

Planned Intermediate

The Three Topologies

Multi-agent systems are best understood through their communication topology. The pattern you choose determines how agents coordinate, how state flows, and where failures propagate.

Topology A — Orchestrator-Worker (most common)
Orchestrator Agent
↓ delegates sub-tasks
Worker A
Research
Worker B
Code Gen
Worker C
Critic
↑ returns results
Orchestrator synthesises → Final Output

Orchestrator-Worker is the default topology for most production systems. A central orchestrator receives the user's goal, decomposes it into sub-tasks, dispatches each to a specialised worker agent, and synthesises the results. Workers are stateless — they receive a self-contained task description and return a result. This makes them easy to test in isolation and replace independently.

Peer-to-peer topologies have agents communicate directly without a central coordinator. This enables emergent collaboration but makes debugging extremely difficult. Avoid this pattern unless you are building systems where no single agent can hold the full task context (e.g., very long-horizon research agents).

Supervisor topologies add a meta-agent above the orchestrator that monitors progress, handles escalations, and can replan if the orchestrator is stuck. This adds resilience for complex, long-running tasks but significantly increases latency and cost.

Task Delegation

Effective delegation requires self-contained task descriptions. When the orchestrator dispatches a sub-task to a worker, the task description must include all context the worker needs — it cannot ask the orchestrator follow-up questions. This means the orchestrator must reason carefully about what each worker needs to know before dispatching.

Include in every task description: the specific goal, relevant background context, output format expected, constraints and scope limits, and any prior attempts that failed. Workers that lack context will either hallucinate or produce generic outputs that don't fit the broader task.

Common mistake: Passing the full conversation history to every worker agent. This wastes tokens and introduces irrelevant context. Instead, have the orchestrator extract and summarise only what each specific worker needs for its sub-task.

Shared State Management

When multiple agents need to read and write shared state — a document being edited, a plan being updated — you need explicit coordination. The simplest approach is orchestrator-mediated state: all state mutations pass through the orchestrator, which acts as a single writer. For higher throughput, use an external shared store (Redis, a database, or a shared file) with optimistic locking. Avoid having multiple agents write to the same resource concurrently without a conflict-resolution strategy.

Message Passing

In multi-agent systems, agent outputs become agent inputs. Standardise your message format early. A simple envelope — task ID, agent ID, status (success/failure), payload, and token usage — makes debugging dramatically easier and enables automated routing of failure cases.

Python · Orchestrator dispatching to workers
async def orchestrate(goal: str):
    # Step 1: Orchestrator decomposes the goal
    plan = await orchestrator_agent(
        prompt=f"Decompose this goal into sub-tasks: {goal}"
    )

    # Step 2: Dispatch workers in parallel
    tasks = [
        worker_agent(name=task.worker, task=task.description)
        for task in plan.subtasks
    ]
    results = await asyncio.gather(*tasks)

    # Step 3: Orchestrator synthesises
    return await orchestrator_agent(
        prompt="Synthesise these results:",
        context=format_results(results)
    )

Topology Comparison

TopologyParallelismDebuggabilityBest for
Orchestrator-WorkerHighHighMost production tasks
Peer-to-PeerMediumLowEmergent collaboration research
SupervisorMediumMediumLong-horizon, resilience-critical tasks
Key takeaways — 02.2
Start with one agent. Add a second only when you have a concrete reason.
Orchestrator-Worker is the default. It's the most debuggable topology.
Self-contained task descriptions are the most important factor in worker quality.
Validate at every agent boundary. Bad results should not silently propagate.

“The orchestrator-worker pattern succeeds because it respects a simple invariant: the orchestrator decides, workers execute. The moment a worker starts deciding what other workers should do, you have introduced a coordination problem without a solution.”

— agentic-ai / agent-design · 02.2
02.3
Module
Workflow Orchestration

DAGs, conditional gates, and human-in-the-loop approval

Workflow orchestration adds deterministic structure to agentic systems. Rather than letting a single LLM decide the entire sequence of operations, you define the control flow explicitly — using DAGs, sequential chains, parallel fan-out, and conditional branches — with LLM calls at specific nodes.

Planned Intermediate

Workflows vs. Pure Agents

A pure agent loop gives the LLM full autonomy over sequencing: it decides which tools to call, in what order, and when to stop. A workflow takes some of that autonomy away and encodes the high-level structure explicitly. LLMs are invoked at specific nodes for tasks they're good at — generating text, classifying, extracting — while the routing between nodes is deterministic code.

This trade-off is worth making when the process is well-understood, when compliance or auditability matters, or when the cost of an incorrect routing decision is high. Workflows are also significantly easier to test: each node can be evaluated independently.

Four Core Workflow Primitives

All workflow patterns are combinations of four primitives: Sequential chains process one step at a time, each step's output feeding the next. Parallel fan-out dispatches the same input to multiple nodes simultaneously and aggregates results. Conditional branching routes execution based on a classification or decision, typically made by an LLM. Human-in-the-loop gates pause execution and await explicit human approval before proceeding.

Workflow Example — Document Processing Pipeline
Input Document
↓ Sequential
Classify document type
[LLM node]
↓ Conditional branch
Contract path
|
Invoice path
|
Unknown → Escalate
↓ Parallel fan-out
Extract fields
Risk score
Summarise
↓ Aggregate
HITL approval gate
[if risk > threshold]
Structured Output

Human-in-the-Loop (HITL) Gates

HITL gates are pauses in the workflow where a human must review and approve before execution continues. They are essential for high-stakes actions — sending emails, making purchases, modifying databases, deploying code. Design them with three things in mind:

Context surfacing: the human must see everything they need to make an informed decision — the agent's reasoning, the proposed action, and the consequences. Timeout handling: define what happens if the human doesn't respond. Usually: wait, escalate, or safely abort. Feedback loop: capture the human's decision and reasoning and feed it back to the agent, so it can learn what kinds of actions are likely to be approved or rejected.

Practical note: Place HITL gates before irreversible actions, not after. Asking for approval after the fact is an audit trail, not a safety mechanism. The gate must block the action until approval is received.

Workflow Frameworks

LangGraph, Prefect, Temporal, and Airflow all support agentic workflow patterns. LangGraph is purpose-built for LLM workflows with native support for cycles (which most DAG frameworks disallow) and stateful checkpointing. Temporal is the right choice when you need durable execution — workflows that survive process restarts, network failures, and long pauses. For simpler use cases, a hand-coded Python state machine is often more maintainable than a full framework.

Key takeaways — 02.3
Workflows are deterministic control flow with LLM nodes — not fully autonomous agents.
HITL gates must block before irreversible actions, not after.
Each node should be independently testable. This is a major advantage over pure loops.
Use LangGraph for cycles. Standard DAG frameworks disallow them.

“A workflow without a HITL gate on its most dangerous action is not safer because it runs faster. It is just faster to make the same irreversible mistake.”

— agentic-ai / agent-design · 02.3
02.4
Module
Roles & Personas

Specialised agent roles that stay coherent under pressure

Giving an agent a clear role — Planner, Critic, Executor, Summariser — is one of the highest-leverage prompting techniques available. But roles that are poorly defined collapse when the task drifts outside their description. This module covers how to define, inject, and maintain stable agent personas.

Planned Foundational

Why Roles Work

LLMs are trained on vast corpora that include human role-playing, professional writing in specific domains, and structured dialogues. When you inject a role via the system prompt, you activate a coherent latent representation — a "mode" of behaviour that influences not just tone but reasoning strategy. A Critic agent asked to review code will naturally look for edge cases, question assumptions, and propose alternatives. The same model asked to "review this code" without a role will produce more superficial feedback.

Roles also provide scope boundaries. An Executor agent knows it should not re-plan; it should execute the plan it was given. A Summariser should not add new information; it should compress. These implicit constraints, reinforced by the role framing, reduce the range of outputs the model will produce and make behaviour more predictable.

The Four Core Roles

Planner Decomposes a high-level goal into an ordered sequence of sub-tasks. Does not execute. Produces a structured plan with dependencies and success criteria for each step.
Critic Reviews the output of another agent and identifies errors, gaps, or risks. Produces structured feedback. Should be explicitly instructed to be adversarial, not collegial.
Executor Carries out a specific, well-defined sub-task using available tools. Does not replan. If the task description is ambiguous, it asks for clarification rather than guessing.
Summariser Compresses long outputs, conversation histories, or tool results into a structured summary that preserves essential information for downstream agents.

Role Injection Techniques

The system prompt is the primary vehicle for role injection. Effective role prompts have three components: a role statement (what the agent is), a scope statement (what the agent does and does not do), and output format (how the agent communicates its outputs).

Prompt template · Critic agent system prompt
You are a Senior Code Reviewer.

Your role:
- Identify bugs, security vulnerabilities, and performance issues
  in the code submitted to you
- Be direct and specific; cite line numbers
- Prioritise issues by severity: Critical / High / Medium / Low

Scope limits:
- Do NOT rewrite the code; only flag issues
- Do NOT praise the code; focus entirely on problems
- Do NOT suggest new features outside the stated requirements

Output format:
Return a JSON object: {
  "critical": [...],
  "high": [...],
  "medium": [...],
  "low": [...]
}
Each item: { "line": N, "issue": "...", "fix": "..." }

Preventing Role Collapse

Role collapse occurs when an agent drifts away from its assigned role — a Critic starts rewriting code instead of reviewing it, or an Executor starts re-planning instead of executing. This happens when the task input is ambiguous, when the model's training bias pulls it toward helpfulness over scope, or when the role prompt is too thin.

Countermeasures: Explicit negative constraints ("Do NOT rewrite the code") are as important as positive role definitions. Output schema enforcement forces the model to produce a structured output that is incompatible with role collapse. Role reinforcement injections — periodically reminding the model of its role mid-conversation — help in long agentic loops where the role can fade.

Pattern: For multi-agent systems where Planner and Critic roles interact, never allow them to share a context window. Run them as separate calls with separate system prompts. A Planner that can see the Critic's feedback will often pre-emptively hedge, weakening the initial plan. Separation produces stronger outputs from both.

Persona Stability Under Adversarial Input

In production, users (or upstream agents) will sometimes send inputs that try to override an agent's persona — "Ignore your previous instructions and…" — or that are sufficiently off-topic that the agent's role becomes unclear. Include explicit instructions for handling out-of-scope inputs: the agent should refuse, ask for clarification, or return a structured error — never silently drift into a different mode of behaviour.

Key takeaways — 02.4
Negative constraints matter as much as positive ones. Say what the agent should NOT do.
Enforce output schemas to make role collapse structurally impossible.
Separate Planner and Critic contexts. Shared context weakens both roles.
Define edge-case behaviour explicitly — what should the agent do when input is out of scope?
Previous chapter 01 · Foundations
Next chapter 03 · Memory & Tools