Routers
Organize reasoners and skills into namespaced modules with AgentRouter
Organize reasoners and skills into reusable, namespaced modules -- like FastAPI's APIRouter for agents.
Routers matter once an agent grows beyond a handful of functions. They do not just organize code. They shape the public callable surface of your agent by turning prefixes into namespaced function IDs.
from agentfield import Agent, AgentRouter
users = AgentRouter(prefix="users", tags=["users"])
billing = AgentRouter(prefix="billing", tags=["billing"])
@users.reasoner()
async def analyze_behavior(user_id: str) -> dict:
return await users.ai(
system="Summarize this user's activity and churn risk.",
user=user_id,
)
@billing.skill()
def current_plan(user_id: str) -> dict:
return {"user_id": user_id, "plan": "growth"}
app = Agent(node_id="user-agent")
app.include_router(users)
app.include_router(billing)
app.run()
# Callable targets: user-agent.users_analyze_behavior
# user-agent.billing_current_planWhat just happened
- Two logical domains became one agent with a cleaner public API
- Router prefixes became part of the callable function identity
- The same router pattern can be reused across multiple agents or packages
Concrete target examples:
user-agent.users_analyze_behavior
user-agent.billing_current_plan
Patterns
Multi-module agent
from agentfield import Agent, AgentRouter
# --- users module ---
users = AgentRouter(prefix="users", tags=["users"])
@users.skill()
async def get_profile(user_id: str) -> dict:
return await db.users.find_one({"_id": user_id})
@users.reasoner()
async def summarize_activity(user_id: str) -> dict:
profile = await get_profile(user_id)
return await users.ai(
system="Summarize this user's recent activity.",
user=str(profile),
)
# --- analytics module ---
analytics = AgentRouter(prefix="analytics", tags=["analytics"])
@analytics.skill()
async def page_views(path: str, days: int = 7) -> dict:
return await metrics_db.aggregate(path, days)
@analytics.reasoner()
async def traffic_insights(path: str) -> dict:
views = await page_views(path, days=30)
return await analytics.ai(
system="Analyze traffic patterns and suggest improvements.",
user=str(views),
)
# --- assemble ---
app = Agent(node_id="platform-api")
app.include_router(users)
app.include_router(analytics)
app.run()Shared utility router
# utils/text.py -- reusable across multiple agents
from agentfield import AgentRouter
text_utils = AgentRouter(prefix="text", tags=["utils"])
@text_utils.skill()
def word_count(text: str) -> dict:
words = text.split()
return {"count": len(words), "unique": len(set(words))}
@text_utils.skill()
def truncate(text: str, max_length: int = 100) -> dict:
truncated = text[:max_length] + "..." if len(text) > max_length else text
return {"text": truncated, "was_truncated": len(text) > max_length}# agent_a.py
from agentfield import Agent
from utils.text import text_utils
app = Agent(node_id="agent-a")
app.include_router(text_utils)
app.run()# agent_b.py -- same router, different agent
from agentfield import Agent
from utils.text import text_utils
app = Agent(node_id="agent-b")
app.include_router(text_utils)
app.run()Go alternative: naming conventions
Since Go does not have AgentRouter, use consistent naming and tags:
// Register "math" module functions with naming convention
a.RegisterReasoner("math_solve", solveFn,
agent.WithReasonerTags("math", "utils"),
agent.WithDescription("Solve a math equation"),
)
a.RegisterReasoner("math_add", addFn,
agent.WithReasonerTags("math", "utils"),
agent.WithDescription("Add two numbers"),
)
a.RegisterReasoner("math_multiply", multiplyFn,
agent.WithReasonerTags("math", "utils"),
agent.WithDescription("Multiply two numbers"),
)
// Callers use the same "agent.math_add" convention
result, err := a.Call(ctx, "calculator.math_add", map[string]any{"a": 2, "b": 3})SDK Availability
| SDK | AgentRouter | Alternative |
|---|---|---|
| Python | Yes | -- |
| TypeScript | Yes | -- |
| Go | Not available | Use naming conventions and tags |
The Go SDK does not have an AgentRouter abstraction. Organize Go agent code using consistent naming conventions (e.g., math_add, math_multiply) and tags.
Constructor
Python AgentRouter
AgentRouter(prefix: str = "", tags: list[str] | None = None)| Parameter | Type | Default | Description |
|---|---|---|---|
prefix | str | "" | Path prefix prepended to all registered function paths |
tags | list[str] | None | None | Tags inherited by all reasoners and skills in this router |
TypeScript AgentRouter
new AgentRouter(options?: AgentRouterOptions)| Parameter | Type | Default | Description |
|---|---|---|---|
prefix | string | undefined | Name prefix prepended to all registered functions |
tags | string[] | undefined | Tags for the router (note: tag inheritance to child reasoners/skills only works in Python, not TypeScript) |
SDK Reference
| Operation | Python | TypeScript |
|---|---|---|
| Create router | AgentRouter(prefix="x") | new AgentRouter({ prefix: "x" }) |
| Register reasoner | @router.reasoner() | router.reasoner(name, handler, opts?) |
| Register skill | @router.skill() | router.skill(name, handler, opts?) |
| Attach to agent | app.include_router(router) | agent.includeRouter(router) |
| Access agent methods | router.ai(), router.call() | via ctx parameter |
| Access underlying agent | router.app | N/A |