By Sagar Shankaran, Founder of CallSphere
A systematic framework for reviewing AI agent architectures, identifying common anti-patterns, and making concrete improvement recommendations that increase reliability and reduce cost.
Key takeaways
Agent systems accumulate complexity faster than traditional software. A single-agent prototype can evolve into a multi-agent system with dozens of tools, nested handoffs, and implicit dependencies — all without anyone stepping back to evaluate whether the architecture still makes sense.
Architecture reviews catch problems that unit tests and integration tests miss: unnecessary agent proliferation, missing guardrails, cost runaway risks, and failure modes that only surface under production load.
Use this structured checklist to evaluate any agent system systematically.
flowchart LR
INPUT(["User intent"])
PARSE["Parse plus<br/>classify"]
PLAN["Plan and tool<br/>selection"]
AGENT["Agent loop<br/>LLM plus tools"]
GUARD{"Guardrails<br/>and policy"}
EXEC["Execute and<br/>verify result"]
OBS[("Trace and metrics")]
OUT(["Outcome plus<br/>next action"])
INPUT --> PARSE --> PLAN --> AGENT --> GUARD
GUARD -->|Pass| EXEC --> OUT
GUARD -->|Fail| AGENT
AGENT --> OBS
style AGENT fill:#4f46e5,stroke:#4338ca,color:#fff
style GUARD fill:#f59e0b,stroke:#d97706,color:#1f2937
style OBS fill:#ede9fe,stroke:#7c3aed,color:#1e1b4b
style OUT fill:#059669,stroke:#047857,color:#fff
Ask: does each agent have a single, clear responsibility? Agents should be decomposed by capability domain, not by conversation turn.
# Anti-pattern: One agent doing everything
mega_agent = Agent(
name="do_everything",
instructions="""You handle billing, technical support,
account management, and sales inquiries...""",
tools=[bill_tool, debug_tool, account_tool, sales_tool,
refund_tool, escalate_tool, report_tool],
)
# Better: Specialized agents with handoffs
billing_agent = Agent(
name="billing_specialist",
instructions="Handle billing inquiries and refunds.",
tools=[bill_tool, refund_tool],
)
technical_agent = Agent(
name="technical_specialist",
instructions="Diagnose and resolve technical issues.",
tools=[debug_tool, log_tool],
)
triage_agent = Agent(
name="triage",
instructions="Route to the appropriate specialist.",
handoffs=[billing_agent, technical_agent],
)
Review question: Can you describe each agent's purpose in one sentence? If you need two sentences, the agent may be doing too much.
Hear it before you finish reading
Talk to a live CallSphere AI voice agent for home services in your browser — 60 seconds, no signup.
Evaluate each tool for three qualities: clear naming, proper error handling, and appropriate granularity.
# Anti-pattern: Tool that does too much with vague naming
@function_tool
def process(data: str) -> str:
"""Process the data.""" # What data? What processing?
parsed = json.loads(data)
result = db.query(parsed["query"])
formatted = format_output(result)
send_email(parsed["recipient"], formatted)
return "Done"
# Better: Focused tools with descriptive names
@function_tool
def query_customer_orders(customer_id: str) -> list[dict]:
"""Retrieve all orders for a customer, sorted by date descending."""
return db.query(
"SELECT * FROM orders WHERE customer_id = %s ORDER BY created_at DESC",
[customer_id]
)
Check that every agent has both input and output guardrails appropriate to its risk level. High-risk agents (those that modify data or trigger external actions) need stricter guardrails than read-only agents.
Trace what happens when each tool fails. Does the agent retry? Does it fall back to an alternative? Does it inform the user? Many agent systems have no error handling — a tool exception simply crashes the agent loop.
Calculate the worst-case token usage for a single user interaction. Multiply by expected concurrent users. Many architectures that work in demos become prohibitively expensive at scale because each user interaction triggers multiple LLM calls across several agents.
The God Agent. A single agent with ten or more tools and a lengthy instruction prompt. It performs poorly because the model struggles to select the right tool from a large set.
The Handoff Loop. Agent A hands off to Agent B, which hands back to Agent A. This creates infinite loops that consume tokens until a timeout or budget limit is hit. Always implement cycle detection.
The Invisible Failure. Tools that catch all exceptions and return generic success messages. The agent thinks the operation succeeded when it actually failed, leading to corrupted state.
Still reading? Stop comparing — try CallSphere live.
See the home services AI agent handle a real call — complete, industry-specific, and live in your browser. No signup.
The Context Bomb. Passing entire conversation histories through every handoff. Token usage grows quadratically with conversation length. Instead, summarize context at handoff boundaries.
Structure recommendations by impact and effort:
| Impact | Low Effort | High Effort |
|---|---|---|
| High | Add guardrails to high-risk agents | Decompose the God Agent |
| Medium | Add tool-level error handling | Implement context summarization |
| Low | Improve tool docstrings | Build evaluation pipeline |
Always prioritize high-impact, low-effort improvements first. Present recommendations with concrete code examples, not abstract advice.
Review the architecture whenever you add a new agent, introduce more than two new tools at once, or notice unexpected cost increases. At minimum, conduct a full review quarterly for production systems. Treat architecture reviews like security audits — they are not optional for systems handling real user interactions.
Include at least one engineer who did not build the system. Fresh eyes catch assumptions that the original builders take for granted. Ideally, include someone with production operations experience who can evaluate failure modes and observability gaps.
Define metrics before making changes: task completion rate, average token cost per interaction, p95 latency, and error rate. Measure for at least two weeks after the change to account for usage pattern variation. A good architecture improvement should measurably improve at least one metric without degrading the others.
#Architecture #CodeReview #AntiPatterns #BestPractices #SystemDesign #AgenticAI #LearnAI #AIEngineering

Written by
Sagar Shankaran· Founder, CallSphere
LinkedInSagar Shankaran is the founder of CallSphere, where he builds production AI voice and chat agents deployed across healthcare, hospitality, real estate, and home services. He writes about agentic AI, LLM engineering, and shipping voice agents that handle real calls in production.
See how AI voice agents work for your industry. Live demo available -- no signup required.
How to design a multi-agent system using MCP for tools and A2A for cross-vendor coordination, with a CallSphere voice agent as a participating node.
Five proven multi-agent architecture patterns built on A2A — orchestrator, peer mesh, hub-and-spoke, marketplace, and tiered specialist.
Every 100ms of latency costs you. So does every cent per minute. Here is the decision matrix we use across 6 verticals to pick where to spend and where to save on voice AI infrastructure.
When to use Pinecone vs pgvector vs Qdrant vs Weaviate. A decision framework that maps team size and workload to the right pick without endless evaluation loops.
Real human memory decays continuously over time. Why your agent should too — and the four decay strategies that keep recall accurate without exploding storage cost.
Webhook-driven AI integration is the workhorse of B2B automation. The 2026 patterns for reliability, retries, and idempotency at scale.
© 2026 CallSphere Inc. All rights reserved.
Made within San Francisco
Watch how CallSphere handles real customer calls, schedules appointments, and processes payments — live.
Try Live DemoBook a DemoCalculate Your ROI