Agentic Architectural Patterns for Building Multi-Agent Systems
This week’s Expert Insight comes from Agentic Architectural Patterns for Building Multi-Agent Systems by Dr. Ali Arsanjani and Juan Pablo Bustos. Dr. Arsanjani, long known for his work in enterprise architecture and now Director of Applied AI Engineering at Google Cloud, brings decades of large-scale systems thinking to the agentic AI conversation. In this excerpt, the authors introduce the Agent Router pattern, a practical way to map user intent to the right specialized agent without relying on brittle keyword rules or guesswork. It may look simple on the surface, but once your system grows beyond a single assistant, this pattern quickly becomes essential.
The Agent Router pattern (intent-based routing)
Agent Router is the { XE “Agent Router pattern” }foundational pattern for decoupling the user’s intent from the specific agent that executes it. In early or simple systems, developers often relied on hardcoded conditional logic (e.g., if “sales” in query: call_sales_agent). However, at an enterprise scale with dozens of specialized agents, this approach becomes brittle and unmanageable. Agent Router solves this by introducing a dedicated architectural layer that acts as a sophisticated switchboard.
This pattern combines two distinct mechanisms: semantic intent extraction (understanding the “what”) and graph-constrained routing (deciding the “who”). By separating these concerns, the system can scale to support new agents and capabilities without requiring a rewrite of the core orchestration logic. It serves as the “Hello World” of agentic coordination, the minimal viable core required for intelligent dispatch.
Context
A system possesses { XE “Agent Router pattern:context” }a suite of specialized agents, each with distinct { XE “context” }capabilities. Users interact with the system via natural language, which is often ambiguous, varying in phrasing, or containing irrelevant noise.
Problem
How can the { XE “Agent Router pattern:problem” }system accurately map an unstructured, variable { XE “problem” }natural language request to the specific agent best suited to handle it, without “hallucinating” capabilities or relying on fragile keyword matching? Forces in the problem space include the following:
Ambiguity versus precision: User { XE “Agent Router pattern:forces” }inputs are vague and { XE “forces” }unstructured, but agent execution requires precise, structured commands.
Scalability versus maintenance: Adding a new agent should not require rewriting the central routing logic. The system must accommodate growing capabilities dynamically.
Safety versus hallucination: The system must ensure that a request is never routed to an agent that cannot handle it, avoiding the risk of an agent attempting to perform a task outside its guardrails.
Solution
The Agent Router pattern implements a two-step process. First, it uses an LLM with a strict schema to { XE “Agent Router pattern:solution” }perform semantic intent extraction, translating the raw query into a structured “intent object” containing standardized actions (verbs) and resources (nouns). Second, it uses graph-constrained routing, querying a lookup table or knowledge graph to find which agent claims the capability to perform that specific action on that specific resource. If a valid path exists in the graph, the request is routed; otherwise, it is rejected as unsupported.
Example: Routing a compliance request
A user asks: “Where is { XE “Agent Router pattern:compliance request, routing” }the latest security audit for the Q3 finance project?” Here is the workflow:
Intent extraction: The router analyzes the text and extracts a structured intent: {Action: “Find”, Resource: “Document”, Params: {”type”: “audit”, “period”: “Q3”}}.
Graph lookup: The router queries its capability graph for the tuple (Find, Document).
Evaluation:
The SalesAgent is registered for (Find, SalesReport) → Mismatch.
The ComplianceAgent is registered for (Find, Document) → Match.
Dispatch: The router instantiates the ComplianceAgent and passes the parameters.
Figure 5.1 – The Agent Router pattern
Example implementation
The following { XE “Agent Router pattern:implementation, example” }Python sample implementation demonstrates the Agent Router in action. This example uses Pydantic to define a rigorous ‘vocabulary’, a set of allowed actions and resources that the system understands.
The logic is divided into two parts: first, we establish the RoutingIntent schema, which acts as the contract between the user’s request and the agent. Second, we build the AgentRouter class, which maintains a capability graph. This graph serves as the source of truth, mapping specific action-resource pairs to the specialized agent best suited for the task. In a production environment, an LLM would be used to extract these structured intents from the user’s natural language { XE “Agent Router pattern:implementation, example” }input before passing them to this routing logic.
from pydantic import BaseModel
from typing import Literal, List, Tuple
# 1. Define the “Vocabulary” of the system
ActionType = Literal[”find”, “analyze”, “create”]
ResourceType = Literal[”sales_report”, “server_log”, “document”]
class RoutingIntent(BaseModel):
action: ActionType
resource: ResourceType
parameters: dict
class AgentRouter:
def __init__(self):
# The Capability Graph: Maps (Action, Resource) -> Agent Name
self.capability_graph = {
(”find”, “sales_report”): “SalesAgent”,
(”analyze”, “sales_report”): “SalesAgent”,
(”find”, “document”): “ComplianceAgent”,
(”create”, “server_log”): “DevOpsAgent”
}
def route_request(self, intent: RoutingIntent):
# 1. Lookup the capability in the graph
key = (intent.action, intent.resource)
target_agent_name = self.capability_graph.get(key)
# 2. Safety Check: If no link exists in the graph, block the request
if not target_agent_name:
return f”Error: No agent exists that can ‘{intent.action}’ a ‘{intent.resource}’.”
# 3. Dispatch (Simplified)
return self.dispatch_to_agent(target_agent_name, intent.parameters)
def dispatch_to_agent(self, agent_name, params):
print(f”Routing to {agent_name} with params: {params}”)
# In real code, this would instantiate the agent class and call .run()
return “Success”
The Agent Router pattern is just one example from a broader collection of design blueprints focused on coordination, governance, and resilience in multi-agent systems. The book dives into the realities of building agentic AI that can scale, remain observable, and operate within clear guardrails. If you are designing enterprise-grade AI systems or planning your transition from prototypes to production, Agentic Architectural Patterns for Building Multi-Agent Systems is worth a closer look. You can explore the full framework and code-backed examples here: [BOOK LINK].


