The Router workflow uses an LLM to analyze incoming requests and intelligently route them to the most appropriate specialized agent. Unlike hardcoded routing logic, the router makes dynamic decisions based on request content and agent capabilities.
Router agents use structured output to provide routing confidence and reasoning, making decisions transparent and auditable.
import asynciofrom fast_agent import FastAgentfast = FastAgent("Router Workflow")@fast.agent( name="fetcher", model="haiku", instruction="You are an agent with a tool enabling you to fetch URLs.", servers=["fetch"],)@fast.agent( name="code_expert", model="haiku", instruction="""You are an expert in code analysis and software engineering. When asked about code, architecture, or development practices, you provide thorough and practical insights.""", servers=["filesystem"],)@fast.agent( name="general_assistant", model="haiku", instruction="""You are a knowledgeable assistant that provides clear, well-reasoned responses about general topics, concepts, and principles.""",)@fast.router( name="route", model="sonnet", default=True, agents=["code_expert", "general_assistant", "fetcher"],)async def main() -> None: async with fast.run() as agent: # Router intelligently selects the appropriate agent await agent.route.send("Analyze the code quality of main.py") await agent.route.send("What are the principles of effective beekeeping?") await agent.route.send("Fetch and summarize https://example.com")if __name__ == "__main__": asyncio.run(main())
The router uses structured output for transparency:
class RoutingResponse(BaseModel): agent: str # Name of selected agent confidence: str # high, medium, or low reasoning: str | None # Explanation of routing decision
Example routing decision:
{ "agent": "code_expert", "confidence": "high", "reasoning": "Request specifically asks for code analysis which is the code_expert's specialty"}
The router automatically generates routing instructions from agent cards:
ROUTING_AGENT_INSTRUCTION = """Select from the following agents to handle the request:<fastagent:agents>[ {"name": "code_expert", "description": "Expert in code analysis..."}, {"name": "general_assistant", "description": "Knowledgeable assistant..."}, {"name": "fetcher", "description": "Agent that can fetch URLs..."}]</fastagent:agents>You must respond with the 'name' of one of the agents listed above."""
Router agents can also use MCP tools directly without delegating:
# Request: "Download and summarize https://example.com"# Router can either:# 1. Use 'fetch' tool directly (if it has the server)# 2. Delegate to 'fetcher' agent@fast.router( name="smart_router", model="sonnet", agents=["specialist1", "specialist2"], servers=["fetch"], # Router has tools too!)
@fast.agent( "content_reviewer", instruction="Review content for policy compliance and safety",)@fast.agent( "spam_detector", instruction="Identify and classify spam, scams, and low-quality content",)@fast.agent( "sensitivity_checker", instruction="Check for sensitive topics requiring special handling",)@fast.router( name="moderation_router", model="sonnet", agents=["content_reviewer", "spam_detector", "sensitivity_checker"],)async def main() -> None: async with fast.run() as agent: result = await agent.moderation_router.send("Check this user submission...")
Override the default routing logic with custom instructions:
CUSTOM_ROUTING = """You are a specialized router for medical queries.Prioritization rules:1. Emergency queries ALWAYS go to emergency_handler2. Prescription questions go to pharmacist3. General health goes to general_practitioner4. If uncertain, route to general_practitionerAvailable agents:{context}"""@fast.router( name="medical_router", agents=["emergency_handler", "pharmacist", "general_practitioner"], routing_instruction=CUSTOM_ROUTING,)