ES EN
Part II · Chapter 06b

Agentic Architecture Design Patterns

20 min read · revised August 2026

Source: Google Cloud Architecture Center — “Choose a design pattern for your agentic AI system”.

With the basic components of an agent already clear, the practical question is: which architecture pattern do you use for a specific problem? Notice something: in Agentic flows we already built a complete flow (the vacation request) with a single agent handling prompts, memory, tools, and a degree of autonomy. That, before we had even named it, is already a specific pattern — the simplest of all. We are going to start putting names on what we already built, and see when that design stops being enough.

Before you choose a pattern: define your requirements

Four guiding questions, applied to our own HR case:

  • Task characteristics: can our vacation request be solved in predefined steps, or is it open-ended? In its simple form, it is fairly structured — it does not need open-ended research-style reasoning.
  • Latency and performance: the employee is waiting live for a reply — this prioritizes speed over exhaustiveness.
  • Cost: how many model calls are we willing to pay for each request, multiplied by thousands of employees? (remember the inference trilemma in Part III).
  • Human involvement: we already established that submitting the real request requires confirmation — a non-negotiable design constraint, no matter which pattern we choose.

If your workload is predictable or can be solved with a single model call (summarize a document, translate text, classify feedback), you probably do not need an agentic architecture — for example, “summarize this vacation policy in one paragraph” would not need any of what follows.

Single-agent system

Use one model, a defined set of tools, and a comprehensive system prompt to handle a request autonomously, trusting the model’s reasoning capabilities to interpret the request, plan steps, and decide which tools to use. This is, exactly, what we assembled in Agentic flows: one agent, with one prompt, with access to three tools, deciding on its own in what order to query them.

If you are starting out in agent development, the recommendation is to begin here — it lets you refine the core logic, the prompt, and the tool definitions before adding architectural complexity.

Where this pattern starts to break: performance degrades with more tools and greater task complexity. Imagine the same HR assistant also has to handle expense reimbursements, overtime, and workplace-harassment complaints — all in the same agent, with the same giant prompt trying to cover rules from four different domains. A prompt that tries to be an expert in all four at once will be worse at each than four specialized prompts separately — and a harassment complaint needs a confidentiality and escalation handling completely different from a vacation request, mixed into the same decision flow. This is precisely the case multi-agent systems exist for.

Multi-agent systems: the specific patterns

A multi-agent system orchestrates multiple specialized agents to solve a complex problem, decomposing a large goal into sub-tasks assigned to dedicated agents. A central concept here is context engineering: managing what information each specialized agent receives — isolating context per agent, persisting information across steps, or compressing data to improve efficiency.

Sequential pattern

Scenario: process an expense receipt. An employee uploads a receipt with the note “client dinner, $85”. Processing this has a natural and fixed sequence: extract the data from the receipt → validate against the expense policy → approve and generate the payment record.

Receipt → [Extractor Agent] → structured data
              ↓
       [Validator Agent] → complies with policy?
              ↓
       [Approval Agent] → final record for payment

The sequential pattern runs specialized agents in a linear, predefined order, where the output of one is the direct input of the next — using a sequential workflow agent that operates with predefined logic, without needing to consult an AI model to orchestrate. The order is already decided in advance by human design, not by an LLM decision on every run.

Splitting into three specialized agents (instead of one doing everything) brings several concrete gains, not just “order”: (1) cost — each agent can use the model size its task actually needs (the Extractor, a simple reading task, can use a cheap model; the Validator, which reasons over policy via RAG, needs something more capable); paying an expensive model for all three tasks when only one needs it would waste money on every call. (2) accuracy — a prompt focused on a single task, without diluting attention across different domains, works better, and each step can be evaluated and improved separately (LLM judges and evals) without mixing results. (3) fewer false positives — each boundary between agents is an explicit checkpoint where an inconsistency can be caught (e.g. an $8,500 amount flagged as suspicious) before it propagates all the way to final approval.

What you do not gain is speed — in fact, you lose it: each agent is an additional call, and total latency is roughly the sum of the individual latencies, not less. Compared with a single agent doing all three things in one call, sequential is slower end to end. That speed gain is, specifically, what the next pattern solves.

The flexibility trade-off is real too: a 2,000receiptforacorporateevent,whichwouldwarrantadifferentapprovalpath,willbeforcedthroughthesameExtractor→Validator→Approverasa2,000 receipt for a corporate event, which would warrant a different approval path, will be forced through the same Extractor → Validator → Approver as a 12 receipt — the pipeline cannot skip steps or take alternative routes. That is exactly what the coordinator pattern, later on, does allow.

Parallel (concurrent) pattern

Scenario: analyze comments from an employee-climate survey. A comment arrives as free text, and you need to: detect sentiment, extract keywords, categorize by department, and detect urgency. None of these four tasks depends on the others — they all read the same original text independently.

                    Employee comment
                            │
        ┌──────────┬────────┴────────┬──────────┐
        ▼          ▼                 ▼          ▼
  [Sentiment] [Keywords] [Category] [Urgency]
        └──────────┴────────┬────────┴──────────┘
                            ▼
                    [Synthesis agent]

The parallel pattern dispatches the same input to several sub-agents that work at the same time, and their results are synthesized at the end — using, like sequential, a fixed workflow agent, without consulting an AI model to orchestrate.

Here you do gain speed, and now we can be precise about why: because the four agents run simultaneously, total latency is roughly the maximum of the four individual latencies, not the sum. With illustrative numbers: if each agent takes ~800ms, sequential would take ~3,200ms (one after another); parallel takes ~800ms in total. The cost you pay in return: four model calls instead of one, consuming more total resources, only spread in parallel instead of in series — you gain wall-clock time, not total cost.

The new complexity it introduces: the final synthesis agent has to reconcile potentially contradictory results (what happens if “category” says IT but “sentiment” detects frustration so high it also warrants attention from workplace culture?) — something that does not exist in sequential, where there are no competing parallel results.

Useful specifically when the sub-tasks are genuinely independent and total latency matters more than total compute cost.

Loop pattern

Scenario: onboarding follow-up for a new employee. An agent checks daily whether the employee completed their checklist (contract, laptop, training, bank details), and if not, sends a reminder — until everything is ready, or until a maximum number of days, in which case it escalates to a human.

Day 1 → [Check checklist] → complete? NO → [Send reminder] ─┐
Day 2 → [Check checklist] → complete? NO → [Send reminder] ─┤
Day 3 → [Check checklist] → complete? YES → [Notify HR] ─┘

The loop pattern repeatedly executes a sequence of sub-agents until an exit condition is met (maximum iterations, or a custom state) — using, again, a fixed workflow agent, with no AI orchestration. The exit condition can be evaluated at any point in the flow, not necessarily at the end.

The key difference versus sequential and parallel: total duration is unpredictable — the employee might finish everything the same day, or take a week. This fits naturally in the “throughput-sensitive world” of the inference trilemma (Part III), not the latency one — it is a background, asynchronous process, like the “nightly lead load” in the 1,500 salespeople case.

The real risk: if the exit condition is not well defined, the loop can run indefinitely — that is why it always needs, besides the success condition, a hard limit (our max_days) that guarantees the process ends one way or another.

Review-and-critique pattern (generator-critic)

Scenario: draft a disciplinary warning letter. This is a document where a mistake has real legal consequences — it has to cite the policy that was violated, keep a factual tone, and follow the progressive-discipline format.

[Generator Agent] → draft
        ↓
[Critic Agent] → meets the criteria?
        ├── YES → approved
        └── NO → specific feedback → [Generator] → new draft → ...

This pattern is an implementation of the loop pattern: a generator agent creates an initial output, and a critic agent evaluates it against predefined criteria, approving, rejecting, or sending it back with feedback for revision. The critic uses exactly the same rubric-guided evaluation technique from LLM judges and evals — the difference is not the mechanism, it is that here it lives integrated inside the live flow, with the power to force a new iteration, instead of evaluating offline after the fact.

Example of one pass: a first draft says “you have been arriving late in an irresponsible manner” — the critic rejects it for not citing the violated policy, using emotional language, and not including dates. The second draft, incorporating that specific feedback, cites “Attendance Policy §4.2”, lists exact dates, and uses neutral language — it is approved. The specific feedback (not just “rejected”) is what makes it possible to correct on the next pass, instead of retrying at random.

The cost: each review round adds an extra model call, accumulating latency and spend with every iteration — worth it for high-risk documents (like this letter), over-engineering for low-risk tasks (an informal meeting reminder).

An important clarification: who orchestrates, code or AI?

It is worth making this completely explicit, because it is one of the most common confusions when learning agentic systems: the four patterns we just saw (sequential, parallel, loop, review-critique) have no inherent ability to “organize themselves”. All of their orchestration is ordinary code, not an AI model deciding the flow.

Returning to the Generator-Critic cycle:

attempts = 0
max_attempts = 3
letter_approved = False

while not letter_approved and attempts < max_attempts:
    draft = call_llm(generator_prompt, previous_feedback)
    verdict = call_llm(critic_prompt, draft, criteria)
    if verdict.approved:
        letter_approved = True
    else:
        previous_feedback = verdict.reasons
        attempts += 1

if not letter_approved:
    escalate_to_human()

The while, the if, the attempts count — ordinary programming code, with no AI involved in deciding the flow. The only lines where an LLM intervenes are the two calls to call_llm(). The name “workflow agent” that the Google Cloud source uses for these patterns is, honestly, a bit misleading — it is not an “agent” that reasons about the flow; it is simply the control code that runs it.

This connects directly to the “degree of autonomy” in Agentic flows: the four patterns seen so far are all implementations of low autonomy at the orchestration level — even though each individual agent inside the flow does use an LLM for its specific task, the decision of which agent to call and when is not made by any model; it is already settled by human design.

The coordinator pattern, which comes next, is genuinely different: there, an LLM does analyze the incoming request and dynamically decide which agent to send it to — the orchestration itself becomes an AI decision, not fixed code. This is the exact distinction Google Cloud uses to separate “deterministic workflows” from “flows that require dynamic orchestration”.

Iterative refinement pattern

Scenario: draft the job description for a hard-to-fill technical role. Unlike the warning letter, here there is no clean binary verdict — the quality of a job description is a spectrum that improves with each polishing pass: clarity of responsibilities, language without gender bias, a realistic number of “required” requirements.

Iteration 1: [Agent] → initial draft
Iteration 2: [Agent] → improves clarity of responsibilities
Iteration 3: [Agent] → adjusts language to reduce bias
Iteration 4: [Agent] → cuts requirements from 15 to 5 real ones
             Quality threshold reached? → YES → done

Another implementation of the loop pattern, but with a design difference versus the generator-critic of the previous pattern: here, one or more agents progressively modify the same result, stored in session state — instead of two separate roles (one that generates, another that only approves/rejects). The stopping criterion is different too: it is not binary (approved/rejected against a rubric), it is progressive — a quality score, evaluated with the same 1-5 rating technique from LLM judges and evals, that keeps rising until it crosses a threshold, or until a maximum number of iterations.

Suitable for complex generation tasks that are hard to get right in a single attempt — writing and debugging code, developing a detailed plan, drafting and revising a long document — all share the characteristic of improving incrementally and measurably with each revision, rather than being resolved with a clean yes/no verdict. It inherits the same risk of not converging that any loop has, with the same solution: a hard maximum-iteration limit, and escalation to a human if it is reached without crossing the threshold.

Coordinator pattern

Scenario: a single entry point for the entire HR assistant. Remember the problem that motivated this whole chapter: a single agent breaks if it has to handle vacations, expenses, and workplace-harassment complaints with one giant prompt. The coordinator solves this without forcing the employee to know which “bot” to talk to — everything arrives at a single entry point, and the coordinator decides where to send it.

Employee message
        ↓
[Coordinator Agent] → analyzes intent with an LLM
        ├── "vacation request" → [Single agent, Ch. 6]
        ├── "expense receipt" → [Sequential pipeline]
        ├── "policy question" → [RAG only, Ch. 5]
        └── "sensitive / harassment complaint" → [Immediate human escalation]

A central agent (coordinator) analyzes and decomposes the user’s request into sub-tasks, dispatching each one to a specialized agent. Unlike all the previous patterns, the coordinator does use an AI model to orchestrate and route dynamically — the variable that decides the routing comes from an LLM call interpreting free, ambiguous language, not from a fixed rule like “if document_type == 'receipt'”.

The case that matters most — why the sensitive complaint cannot fail: if the coordinator misreads an ambiguous message and classifies a serious complaint as “policy_question”, the result is a delicate complaint answered by a bot instead of escalating immediately to a human — the same kind of risk we saw with the Finnbot case in Part III: real autonomy to decide routes, where a bad classification is not cosmetic. The mitigation is not to strip the coordinator of autonomy — it is to demand a higher confidence threshold for high-risk categories: when in doubt, lean toward escalating to one human too many, not too few.

Useful for automating processes that require adaptive routing. More flexible than rigid predefined flows, but it implies an extra call dedicated only to classifying, before even solving the real request — more cost and latency than a fixed pipeline, in exchange for each specialist keeping its prompt focused, without any of them needing to know the details of the other domains.

Hierarchical task-decomposition pattern

Scenario: design the total-compensation proposal for a new role. Unlike the coordinator (which routes to one exclusive branch), here the problem is split across several sub-tasks that all run and then have to be recombined: salary benchmarking, benefits design, and equity structure.

Request: "Design total compensation for Senior ML"
                    ↓
        [Root Agent] — decomposes the task into sub-tasks
    ┌───────────────┼───────────────┐
    ▼               ▼               ▼
[Salary         [Benefits]      [Equity]
 Benchmarking]
    └───────────────┴───────┬───────┘
                             ▼
                  [Root Agent] — synthesizes
                  the three pieces into a final proposal

An implementation of the coordinator pattern that organizes agents in a multi-level hierarchy: a root agent receives a complex task, decomposes it into more manageable sub-tasks, delegates to specialized sub-agents at lower levels, and then synthesizes their results — the same root agent usually handles both decomposing at the start and synthesizing at the end, at two different moments of the same flow. It shares with the parallel pattern the need to reconcile results from several sources, and with the coordinator the fact that an LLM actively decides how to split the problem, instead of the split being fixed in advance.

Ideal for ambiguous, open-ended problems that require multi-step reasoning — research, planning, synthesis. It can produce more comprehensive results than any previous pattern, but it adds the highest architectural complexity and cost in the entire taxonomy up to this point.

Note: when coordination needs no AI at all. It is tempting to cite the Anthropic experiment where 16 Claude agents built a complete C compiler (100,000 lines of Rust, able to compile the Linux kernel) in two weeks as an example of coordinator or hierarchical decomposition — but technically it is not. The system coordinated the work through a git-based locking mechanism that assigned distinct tasks to each agent, and verified every result against GCC as a “reference oracle” — with no LLM-agent dynamically orchestrating or synthesizing results with reasoning. It is a useful reminder that these patterns are conceptual tools for thinking about architectures, not an exhaustive list of everything that works in practice: sometimes the most robust coordination is the one that depends least on an LLM deciding the flow, and more on deterministic infrastructure and objective verification.

Swarm pattern: a collaborative all-to-all communication approach, where multiple specialized agents work together to iteratively refine a solution. A “dispatcher” agent routes the initial request, but does not orchestrate the workflow (unlike the coordinator) — each agent can communicate with any other, share findings, critique proposals, and hand the task to another agent it considers better positioned for the next step. It requires an explicit exit condition (maximum iterations, time limit, or consensus reached) to keep the process from never ending. Useful for ambiguous problems that benefit from debate and iteration (e.g. designing a new product with a market-research agent, an engineering agent, and a financial-modeling agent, debating trade-offs until they converge). It can produce exceptionally creative solutions, but it is the most complex and expensive multi-agent pattern, with a real risk of unproductive loops or failure to converge.

Additional patterns outside the multi-agent taxonomy

ReAct pattern (Reason and Act)

Scenario: “my paycheck this month came in lower than expected, I don’t know why.” Unlike everything we have seen so far, here we do not know in advance which steps are needed or in what order — it could be badly logged hours, a change in deductions, a tax adjustment, or several things at once. No fixed pipeline can anticipate this, because the investigation path depends on what is discovered at each step.

Thought: "I need to review the hours logged this month"
Action: lookup_hours_worked(employee)
Observation: normal hours, no anomaly

Thought: "hours look fine, maybe something changed in the deductions"
Action: lookup_benefit_deductions(employee)
Observation: a dental insurance deduction was added starting this month

Thought: "that explains the difference, I have enough information"
Action: [formulate the final answer, no more tools]

The model frames its thought process and actions as a sequence of natural-language interactions, operating in an iterative loop of thought → action → observation until an exit condition is met. The real difference from the sequential expenses pattern: there the order is always the same, regardless of the case; here, if the problem had been hours instead of deductions, the agent would have needed completely different tools and a different number of steps — the path is built on the fly. In terms of Agentic flows, this is high autonomy: the agent decides how many investigation rounds it needs and which tools to use in each one, not just the order among fixed tools.

Useful for dynamic tasks that require continuous planning and adaptation. A single ReAct agent can be simpler and cheaper than a complex multi-agent system, and the reasoning log helps with debugging. The cost is different from the loop pattern: there the duration was unpredictable because of an external variable (when the employee completes their checklist); here it is unpredictable because of how much internal reasoning the model needs to solve the problem in a single session — each turn adds latency, with no limit predictable in advance, so in practice you always define a maximum number of turns before escalating to a human.

Human-in-the-loop pattern

We have already used this pattern several times without naming it formally: in MCP, the vacation agent asked before submitting the real request; in the expenses pipeline, a $2,000 receipt was routed to manual approval. All of those are instances of the same pattern — which does not compete with the others, but can be added to any of them.

Additional scenario: process an employee’s termination. An agent could draft all the documentation — calculate the severance via RAG, generate the termination letter with the same generator-critic pattern as the warning letter, assemble the exit checklist. But executing that (sending the official notification, processing the final payment) is exactly the kind of irreversible, high-impact action from the Finnbot case (Part III): it should never be automated without a human with authority confirming explicitly first.

The agent integrates human intervention points directly into its flow: at a predefined checkpoint, it pauses execution and waits for review before continuing. It is worth naming it as its own pattern, and not leaving it implicit, because it forces an explicit design question — at which exact points in this flow do I need a human checkpoint, and by what criterion? — instead of solving it by instinct, case by case.

Custom logic pattern

Scenario: the expenses pipeline, taken to the complexity of a real company. We had already noted the limitation of the pure sequential pattern: a 12receiptanda12 receipt and a 2,000 one should not be treated the same. Let’s solve it by combining patterns:

def process_expense(receipt):
    data = extractor_agent(receipt)

    if data.amount < 100:
        # small expense: simple sequential pipeline
        verdict = validator_agent(data)
        return approver_agent(verdict)

    else:
        # large expense: parallel approval from two distinct parties
        manager_approval = manager_approval_agent(data)
        finance_approval = finance_approval_agent(data)

        if manager_approval.approved and finance_approval.approved:
            return approver_agent(data)
        elif manager_approval.approved != finance_approval.approved:
            return escalate_to_human(data, reason="disagreement between manager and finance")
        else:
            return reject(data)

Here we combine, inside a single flow: sequential (small expenses), parallel (the two simultaneous approvals for large expenses), and human-in-the-loop (when there is disagreement) — all decided by explicit business rules (amount < 100), not by an LLM reasoning about which path to take as in the coordinator.

Maximum flexibility, with the most honest trade-off of all the patterns: surgical control over every case, but you are responsible for designing, implementing, and debugging every branch of the decision tree — every possible path has to be contemplated explicitly in the code, unlike the coordinator, where the LLM decides dynamically without you having to anticipate every combination. It is the pattern that most resembles traditional software programming, because in essence that is what it is: the agents are pieces inside a control logic that you are still writing by hand.

Decision table: choosing the right pattern

Workload characteristicRecommended patternOur example
Rigid, multi-step, predefined flow, no need for model orchestrationSequentialProcess an expense receipt: extract → validate → approve
Independent tasks executable at the same timeParallelAnalyze a survey comment: sentiment + keywords + category + urgency, all at once
Requires progressive improvement of the output over several cyclesIterative refinementPolish the job description for a hard-to-fill technical role
Structured tasks that require external tools, fast prototype developmentSingle agentThe vacation assistant from Agentic flows, in its original form
Dynamic routing to specialized sub-agents based on varied inputCoordinatorThe single entry point of the HR assistant, routing among vacations/expenses/policy/complaints
Ambiguous, open-ended tasks that require multi-level orchestrationHierarchical decompositionDesign total compensation for a role: benchmarking + benefits + equity
Collaborative debate and iterative refinement among specialistsSwarmDesign a new product with market, engineering, and finance agents debating trade-offs
Continuous reasoning and adaptation for dynamic tasksReActInvestigate why an employee’s paycheck came in lower than expected
Repeated monitoring or polling until an exit condition is metLoopDaily follow-up of a new employee’s onboarding checklist
Requires a distinct validation step before completingReview and critiqueDraft a disciplinary warning letter, with legal verification before approving
Mandatory human oversight for risk, safety, or complianceHuman-in-the-loopConfirm before submitting a vacation request, or before executing a termination
Unique business logic, complex branchingCustom logicThe full expenses pipeline, with different routes depending on the amount

Decision metrics, at a glance

Beyond “which pattern fits which kind of task” (the previous table), it sometimes helps to compare the patterns directly on the dimensions that matter most when designing a real system:

PatternRelative latencyCost per requestMaintainabilityFlexibilityMain risk
SequentialSum of each stepLowHighLowRigidity in the face of unanticipated cases
ParallelThe maximum of the steps, not the sumMedium (N simultaneous calls)MediumLowReconciling contradictory results
LoopUnpredictable (depends on when the condition is met)VariableMediumLowInfinite loop without a hard limit
Review and critiqueOne round + one per rejectionMedium-highMediumMediumCost if there are many rejection rounds
Iterative refinementOne round per incremental improvementMedium-highMediumMediumSame risk as the loop: without a limit, it may not converge
CoordinatorClassification + the chosen sub-taskMediumMedium-lowHighBad classification in high-risk cases
Hierarchical decompositionDecomposition + parallel sub-tasks + synthesisHighLowVery highThe hardest of all to debug
SwarmVery high (multiple rounds of debate)Very highVery lowVery highNo convergence, unproductive loops
ReActFrom 1 to several turns × the latency of each oneVariable (depends on how many turns)LowVery highDrift — getting lost in unproductive investigations

How to use this table, with caution: these are relative and qualitative comparisons, useful for reasoning about trade-offs — not measured figures or universal thresholds. For example, it is reasonable to think “if my application needs near-instant answers, a pattern with multiple rounds (Swarm, ReAct with many turns) probably does not fit” — but the exact point where that stops being true depends entirely on your specific case, your model, and your infrastructure (remembering the inference trilemma in Part III). The only reliable way to know whether a pattern meets your latency or cost requirements is to measure it with your own real workload, not to apply a generic threshold read from a table.

Found an error? Suggest a correction