AgentRouter
Organize large agents across multiple files with AgentRouter — Agentfield's FastAPI-style router for reasoners and skills.
AgentRouter
AgentRouter lets you organize reasoners and skills across multiple files, then mount them on an Agent with app.include_router(). It mirrors FastAPI's APIRouter pattern.
When to Use
Use AgentRouter when your agent has:
- More than 5–6 reasoners
- Distinct functional groups (e.g., analysis, synthesis, retrieval)
- Multiple team members working on the same agent
Import
from agentfield import AgentRouterConstructor
AgentRouter(
prefix: str = "",
tags: Optional[List[str]] = None
)| Parameter | Type | Description |
|---|---|---|
prefix | str | URL prefix for all routes (e.g., "/analysis") |
tags | List[str] | Tags inherited by all reasoners and skills in this router |
Decorators
@router.reasoner()
Registers an AI-powered reasoner. Same signature as @app.reasoner():
router.reasoner(
path: Optional[str] = None,
tags: Optional[List[str]] = None,
vc_enabled: Optional[bool] = None,
)@router.skill()
Registers a deterministic skill. Same signature as @app.skill():
router.skill(
tags: Optional[List[str]] = None,
path: Optional[str] = None,
vc_enabled: Optional[bool] = None,
)Mounting on an Agent
Use app.include_router(router) in your main.py to register all collected reasoners and skills:
app.include_router(router)All reasoners and skills from the router are registered on the agent. Direct calls between reasoners continue to work after mounting.
Complete Example
# reasoners/analysis.py
from agentfield import AgentRouter
from pydantic import BaseModel
from typing import Literal, Optional
router = AgentRouter(prefix="/analysis", tags=["analysis"])
class SentimentResult(BaseModel):
sentiment: Literal["positive", "negative", "neutral"]
confidence: float
reasoning: str
@router.reasoner()
async def analyze_sentiment(text: str) -> SentimentResult:
from main import app
return await app.ai(
system="Classify the sentiment of this text.",
user=text,
schema=SentimentResult,
temperature=0.2,
)
@router.reasoner()
async def classify_topic(text: str, model: Optional[str] = None) -> dict:
from main import app
return await app.ai(
user=f"What is the main topic? {text}",
model=model,
)# reasoners/synthesis.py
from agentfield import AgentRouter
from pydantic import BaseModel
router = AgentRouter(prefix="/synthesis", tags=["synthesis"])
class SummaryResult(BaseModel):
summary: str
key_points: list[str]
action_required: bool
@router.reasoner()
async def summarize(content: str) -> SummaryResult:
from main import app
return await app.ai(
user=f"Summarize this content: {content}",
schema=SummaryResult,
)# main.py
import os
from agentfield import Agent, AIConfig
from reasoners.analysis import router as analysis_router
from reasoners.synthesis import router as synthesis_router
import asyncio
app = Agent(
node_id="multi-module-agent",
agentfield_server=os.getenv("AGENTFIELD_SERVER", "http://localhost:8080"),
ai_config=AIConfig(model=os.getenv("SMALL_MODEL", "openai/gpt-4o-mini")),
)
app.include_router(analysis_router)
app.include_router(synthesis_router)
@app.reasoner()
async def orchestrate(query: str) -> dict:
sentiment, topic = await asyncio.gather(
analyze_sentiment(query),
classify_topic(query),
)
summary = await summarize(query)
return {
"sentiment": sentiment.dict(),
"topic": topic,
"summary": summary.dict(),
}
if __name__ == "__main__":
app.run(auto_port=True)Recommended Project Structure
my-agent/
├── main.py # Agent init + top-level orchestrators
├── models.py # Shared Pydantic schemas
├── reasoners/
│ ├── __init__.py # Optional: re-export routers
│ ├── analysis.py # Analysis group (router + reasoners)
│ └── synthesis.py # Synthesis group (router + reasoners)
└── requirements.txtImport app from main.py inside reasoner functions (not at module level) to avoid circular imports.