TechByteByByte

Agent System Design

Worked design exercises applying everything from this course to complete, from-scratch system designs — customer support, research, enterprise RAG, coding, and multi-agent systems.

#AI Agents#AI#System Design#Level 9

Begin with the problem

Agent design starts with the task and risk, then chooses the loop, tools, state, memory, approvals, budgets, evaluation, and fallback behavior.

requirements → risks → architecture → happy path + failure paths → evaluation → production decision

What you will learn

  • Turn a business goal into requirements, risks, tools, state, budgets, and success metrics.
  • Design the happy path together with failure, retry, fallback, and escalation paths.
  • Work through complete support, research, RAG, and coding-agent designs.
  • Explain architectural trade-offs clearly in a system-design discussion.

Current real-system grounding: Google’s Agents overview and OpenAI’s agent quickstart provide current examples. Product availability and API shapes can change.

These official links document available product features. They do not reveal every provider’s private implementation, hidden reasoning, default setting, or internal limit.

1. The problem this module solves

Module 25 showed how different domains combine this course’s components differently. This module gives you real practice designing a complete system from scratch — walking through the full design process for several real scenarios, exactly the format used in technical system-design interviews.


2. The Design Process

Requirements

Components (which modules' concepts are needed?)

Architecture (how do they fit together? Module 24)

Agent Loop (Module 4's specifics for THIS task)

Tools (Module 6-7)

State (Module 12)

Memory (Module 11, if needed)

RAG (Module 14, if needed)

Guardrails (Module 17)

Failure Handling (Module 19)

Observability (Module 21)

Scaling

Security (Module 18)

Trade-offs

This is the systematic checklist a well-prepared engineer walks through for any new agent system design.


3. Worked Exercise — Design a Customer Support Agent

Requirements: resolve tickets using real order/shipping data, support returning customers, handle refunds safely.

Design ElementDecision
ComponentsTools, memory, RAG, human-in-the-loop, guardrails
Toolscheck_order_status, check_shipping_carrier, process_refund, search_policy_docs
Stateorder_status, carrier_status, decision
MemoryLong-term memory of customer preferences and history, retrieved per conversation
RAGPolicy documents indexed and retrieved when a question requires them
GuardrailsInput: block prompt injection; Tool: rate-limit send_email; Output: block sensitive data leakage
Failure HandlingMax iterations for tool retries; fallback to human escalation on repeated tool failure
ObservabilityFull trace per request; cost and latency per stage
ScalingCache frequent policy lookups; rate-limit per-user requests
SecurityAccess control on customer data; human approval for refunds
Trade-offHigher latency from human approval vs. real safety for high-risk actions

4. Worked Exercise — Design a Multi-Agent Research System

Requirements: synthesize findings across many sources into a coherent, well-cited report.

flowchart TD
    S[Supervisor] --> R1[Research Agent 1<br/>source type A]
    S --> R2[Research Agent 2<br/>source type B]
    R1 --> Syn[Synthesis Agent]
    R2 --> Syn
    Syn --> Rev[Review Agent<br/>reflection, Module 10]
    Rev --> Out[Final Report]
Design ElementDecision
ComponentsMulti-agent (Module 15’s supervisor pattern), RAG (Module 14), reflection (Module 10)
Agent rolesSupervisor, parallel research specialists, synthesis agent, review agent
Failure HandlingIf one research agent’s sources are poor (Module 28 of the RAG course’s Corrective RAG), retry with a reformulated query
ObservabilityPer-agent trace, directly Module 21, Section 7’s multi-agent attribution
Trade-offParallel research agents reduce total time, but increase total cost

5. Worked Exercise — Design an Enterprise RAG Agent

Requirements: answer questions using internal documentation, with real per-user access control.

Design ElementDecision
ComponentsRAG-centric (your entire RAG course), strict guardrails, access control
RAG strategyHybrid search, reranking, real metadata-based access filtering — directly your RAG course’s Modules 15-18, 27
SecurityAccess control enforced at RETRIEVAL time (filter-then-search, your RAG course’s Module 15), not just at output
Failure HandlingAgentic RAG (Module 14) — evaluate retrieval quality, retry with reformulated queries
Trade-offStricter access filtering reduces the candidate document pool, potentially affecting answer completeness

6. A Real Developer Example — The Design Review Conversation

Engineer: "I want to build a coding agent."

Senior reviewer, applying THIS module's process:

"What's the real requirement -- autonomous code generation, or
research+implement+review as SEPARATE concerns?"
   -> If separate concerns: multi-agent (Module 15)

"Does it need to MERGE code autonomously, or propose changes for
human review?"
   -> If merging: needs human-in-the-loop (Module 16)

"How will you know if it's WORKING WELL?"
   -> Needs a real evaluation plan (Module 20) BEFORE deployment,
      not after

"What happens when a tool call FAILS mid-task?"
   -> Needs explicit failure handling (Module 19), not assumed-away

7. A Simple Agentic AI Connection

This module is the practice ground for everything agentic this course has covered — each worked exercise requires drawing on Modules 1-25 together, exactly the integrated thinking a real system design task demands.


8. How Is This Used in AI?

🤖 How Is This Used in AI?

This systematic design process — requirements through trade-offs — is how production agent systems get architected and reviewed before implementation begins, and is also the standard format for technical system-design interviews in AI engineering roles.


9. Real-World Applications

  • Technical design documents for new agent features
  • System design interviews for AI/agent engineering roles
  • Architecture review conversations before committing engineering resources to a new agent system

10. Common Mistakes

Incorrect idea: Jumping to implementation before completing the design process.

Why it is incorrect: As shown directly in Section 2 and 6, real trade-offs and failure handling need to be considered BEFORE writing code, not discovered after deployment.

Incorrect idea: Designing without explicit failure handling or observability.

Why it is incorrect: As shown directly in Section 3-5’s worked exercises, these are integral design elements, not afterthoughts.

Incorrect idea: Not explicitly naming trade-offs.

Why it is incorrect: As shown directly throughout Sections 3-5, every real design decision involves a real trade- off — naming it explicitly is part of a complete design, not an optional addition.


11. Limitations

  • These worked exercises are illustrative — real system designs require deeper, domain-specific detail than this module’s summary tables provide
  • A complete design also requires real domain expertise (Module 25’s point) alongside this course’s architectural knowledge

12. Quick Reference

flowchart LR
    Req[Requirements] --> Comp[Components]
    Comp --> Arch[Architecture]
    Arch --> Fail[Failure Handling]
    Fail --> Obs[Observability]
    Obs --> Trade[Trade-offs]

13. Code — Implementing a Reusable System Design Structure

🎯 Target of this example: implement Section 3’s complete worked exercise directly — a structured design object capturing every element from Section 2’s design process, exactly the format a real design document or interview answer would follow.

Example 1 — Simple

from dataclasses import dataclass, field

@dataclass
class SystemDesign:
    """Directly implements Section 2's complete design process as a
    structured object -- every field corresponds to one step in the
    real design checklist."""
    requirements: list = field(default_factory=list)
    components: list = field(default_factory=list)
    tools: list = field(default_factory=list)
    state_schema: dict = field(default_factory=dict)
    memory_strategy: str = ""
    rag_strategy: str = ""
    guardrails: list = field(default_factory=list)
    failure_handling: list = field(default_factory=list)
    observability_plan: list = field(default_factory=list)
    scaling_considerations: list = field(default_factory=list)
    security_considerations: list = field(default_factory=list)
    tradeoffs: list = field(default_factory=list)

def design_customer_support_agent() -> SystemDesign:
    """A real, complete worked design exercise -- exactly Section
    3's table, made into a structured, reusable object."""
    return SystemDesign(
        requirements=["Resolve tickets using real order/shipping data", "Support returning customers", "Handle refunds safely"],
        components=["tools", "memory", "RAG", "human-in-the-loop", "guardrails"],
        tools=["check_order_status", "check_shipping_carrier", "process_refund", "search_policy_docs"],
        state_schema={"order_status": "str", "carrier_status": "str", "decision": "str"},
        memory_strategy="Long-term memory of customer preferences and history, retrieved per conversation",
        rag_strategy="Policy documents indexed and retrieved when a question requires them",
        guardrails=["Input: block prompt injection", "Tool: rate-limit send_email", "Output: block sensitive data leakage"],
        failure_handling=["Max iterations for tool retries", "Fallback to human escalation on repeated tool failure"],
        observability_plan=["Full trace per request", "Cost and latency per stage"],
        scaling_considerations=["Cache frequent policy lookups", "Rate-limit per-user requests"],
        security_considerations=["Access control on customer data", "Human approval for refunds"],
        tradeoffs=["Higher latency from human approval vs. real safety for high-risk actions"],
    )

design = design_customer_support_agent()
print(f"Requirements: {len(design.requirements)}")
print(f"Components: {design.components}")
print(f"Tools: {design.tools}")
print(f"Guardrails: {design.guardrails}")
print(f"Trade-offs: {design.tradeoffs}")

Expected Output:

Requirements: 3
Components: ['tools', 'memory', 'RAG', 'human-in-the-loop',
'guardrails']
Tools: ['check_order_status', 'check_shipping_carrier',
'process_refund', 'search_policy_docs']
Guardrails: ['Input: block prompt injection', 'Tool: rate-limit
send_email', 'Output: block sensitive data leakage']
Trade-offs: ['Higher latency from human approval vs. real safety
for high-risk actions']

What we conclude from this example: the complete design from Section 3 is now captured as a structured, inspectable object — every element of the real design process (requirements through trade-offs) is explicitly represented, rather than left as an informal, unstructured description.

Example 2 — Intermediate

from dataclasses import dataclass, field

@dataclass
class DesignReviewQuestion:
    question: str
    triggers_component: str

def design_review_checklist() -> list:
    """Directly implements Section 6's REAL developer example -- the
    real review QUESTIONS a senior engineer would ask, each
    mapped to the specific architectural component it should
    trigger."""
    return [
        DesignReviewQuestion(
            "Does this involve separate concerns that could each be a specialist?",
            "multi-agent (Module 15)"),
        DesignReviewQuestion(
            "Does it need to take irreversible or high-consequence actions autonomously?",
            "human-in-the-loop (Module 16)"),
        DesignReviewQuestion(
            "How will you know if it's working well before and after deployment?",
            "evaluation plan (Module 20)"),
        DesignReviewQuestion(
            "What happens when a tool call fails mid-task?",
            "explicit failure handling (Module 19)"),
    ]

checklist = design_review_checklist()
for item in checklist:
    print(f"Q: {item.question}")
    print(f"  -> Triggers: {item.triggers_component}\n")

Expected Output:

Q: Does this involve separate concerns that could each be
a specialist?
  -> Triggers: multi-agent (Module 15)

Q: Does it need to take irreversible or high-consequence actions
autonomously?
  -> Triggers: human-in-the-loop (Module 16)

Q: How will you know if it's working well before and after
deployment?
  -> Triggers: evaluation plan (Module 20)

Q: What happens when a tool call fails mid-task?
  -> Triggers: explicit failure handling (Module 19)

What we conclude from this example: each real design review question is explicitly linked to the specific module and component it should trigger — exactly Section 6’s real developer example, made into a reusable checklist a real engineer could apply to any new agent design proposal.

Example 3 — Production Grade

from dataclasses import dataclass, field

@dataclass
class SystemDesignValidation:
    design_name: str
    missing_elements: list = field(default_factory=list)
    is_complete: bool = True

class SystemDesignValidator:
    """A production-style validator implementing Section 10's warning
    as ENFORCED logic -- checking that a proposed design includes failure handling, observability, and explicit trade-offs,
    exactly the elements Section 10 flags as commonly missing."""

    REQUIRED_ELEMENTS = ["requirements", "components", "failure_handling", "observability_plan", "tradeoffs"]

    def validate(self, design_name: str, design_dict: dict) -> SystemDesignValidation:
        missing = [elem for elem in self.REQUIRED_ELEMENTS
                   if not design_dict.get(elem)]
        return SystemDesignValidation(design_name, missing, is_complete=(len(missing) == 0))

validator = SystemDesignValidator()

complete_design = {
    "requirements": ["Resolve tickets"],
    "components": ["tools", "memory"],
    "failure_handling": ["Max iterations"],
    "observability_plan": ["Full trace"],
    "tradeoffs": ["Latency vs safety"],
}

incomplete_design = {
    "requirements": ["Handle refunds"],
    "components": ["tools"],
    # Missing failure_handling, observability_plan, tradeoffs --
    # exactly Section 10's common mistake
}

result1 = validator.validate("Customer Support Agent (complete)", complete_design)
result2 = validator.validate("Refund Agent (incomplete)", incomplete_design)

for result in [result1, result2]:
    print(f"{result.design_name}: complete={result.is_complete}")
    if result.missing_elements:
        print(f"  Missing: {result.missing_elements}")

Expected Output:

Customer Support Agent (complete): complete=True
Refund Agent (incomplete): complete=False
  Missing: ['failure_handling', 'observability_plan', 'tradeoffs']

What we conclude from this example: the validator correctly flags the incomplete design as missing three essential elements — failure handling, observability, and trade-offs — exactly Section 10’s warning turned into an automated check that could catch an incomplete design document before it moves forward to implementation, directly reinforcing that a complete design requires more than just requirements and a component list.


14. Interview Questions

Q: Walk through the complete system design process this module establishes, from requirements to trade-offs.

Ans: The process starts with real requirements, then identifies which architectural components (tools, memory, RAG, human-in-the-loop, multi-agent) the requirements actually call for. From there, it specifies the concrete agent loop, tools, and state schema for the task, followed by memory and RAG strategies if needed. Guardrails and failure handling address safety and reliability, observability ensures the system is diagnosable in production, and scaling and security considerations address production readiness. Finally, explicit trade-offs are named — every real design decision involves weighing competing concerns.

Q: Using the customer support agent worked exercise, explain why human-in-the-loop is specifically included for refund processing but not for order status lookups.

Ans: This directly applies the risk-based judgment covered earlier in this course — processing a refund is a high-risk, difficult-to-reverse action involving real money, warranting a human approval gate before execution. Checking order status is a read-only lookup with no real risk of harm if done incorrectly, so it can proceed autonomously without adding the latency and friction of a human approval step that wouldn’t provide meaningful additional safety for this specific, low-risk action.

Q: In the multi-agent research system design, why are research agents run in parallel rather than sequentially?

Ans: The research subtasks — gathering information from different source types — don’t have a real dependency on each other; one research agent’s findings aren’t needed as input for the other’s search. Running them in parallel, rather than sequentially, reduces the total time needed to complete the overall research task, though this comes with a real trade-off of increased total cost, since multiple agents are actively working (and consuming resources) simultaneously rather than one at a time.

Q: Why does a system design review process specifically ask “what happens when a tool call fails mid-task” rather than assuming tools will generally work?

Ans: Tool failures are a real, real possibility covered extensively earlier in this course — external APIs can time out, be temporarily unavailable, or return unexpected errors. A design that doesn’t explicitly address this risks the agent behaving unpredictably or looping indefinitely when a failure actually occurs in production, rather than having a deliberate, planned response like retrying with a limit, falling back to an alternative approach, or escalating to a human. Explicitly designing for this failure mode before implementation avoids discovering the gap only after a real production incident.


15. What You Should Remember

  • A complete system design follows a real, systematic process — requirements, components, architecture, failure handling, observability, and explicit trade-offs — not just a component list.
  • Worked exercises across different domains (customer support, multi-agent research, enterprise RAG) demonstrate this process applied concretely, each producing a different but internally coherent design.
  • Failure handling, observability, and trade-offs are commonly missing elements in incomplete designs — verified directly through a validator correctly flagging a design missing these essential components.

16. Quick Practice

Using Section 2’s complete design process, produce a full worked design (following Section 3-5’s table format) for an agent application of your own choosing — make sure to explicitly name at least one real trade-off in your final design.

17. Next Step

Next: Module 27 — Common Misconceptions — a dedicated, corrected list of the most common misunderstandings about AI Agents, consolidating warnings raised throughout this entire course.

Author
TechByteByByte Editorial Team
Reviewed by
TechByteByByte Admin
Published
Last reviewed