AgentRouter

Organize reasoners and skills with prefixes and shared tags

The AgentRouter class helps organize reasoners and skills into logical groups with shared prefixes and tags. This is useful for large agents with many capabilities.

Basic Usage

import { Agent, AgentRouter } from '@agentfield/sdk';

const authRouter = new AgentRouter({
  prefix: 'auth',
  tags: ['authentication']
});

authRouter.reasoner('login', async (ctx) => {
  const { username, password } = ctx.input;
  // Authentication logic...
  return { token: 'jwt-token' };
});

authRouter.skill('validate_token', async (ctx) => {
  const { token } = ctx.input;
  // Validation logic...
  return { valid: true };
});

const agent = new Agent({ nodeId: 'my-agent' });
agent.includeRouter(authRouter);

// Creates: auth_login (reasoner), auth_validate_token (skill)

Constructor Options

Prop

Type

Methods

router.reasoner()

Register a reasoner with the router. Returns the router for chaining.

router.reasoner('name', handler, options);

router.skill()

Register a skill with the router. Returns the router for chaining.

router.skill('name', handler, options);

Chaining

All methods return the router for fluent chaining:

const router = new AgentRouter({ prefix: 'user' })
  .reasoner('analyze', async (ctx) => { /* ... */ })
  .reasoner('summarize', async (ctx) => { /* ... */ })
  .skill('format', async (ctx) => { /* ... */ })
  .skill('validate', async (ctx) => { /* ... */ });

Examples

Domain-Driven Organization

// User management router
const userRouter = new AgentRouter({
  prefix: 'user',
  tags: ['users', 'management']
});

userRouter
  .reasoner('analyze_behavior', async (ctx) => {
    return await ctx.ai(`Analyze user behavior: ${JSON.stringify(ctx.input)}`);
  })
  .skill('get_profile', async (ctx) => {
    return await db.users.findById(ctx.input.userId);
  })
  .skill('update_settings', async (ctx) => {
    return await db.users.updateSettings(ctx.input.userId, ctx.input.settings);
  });

// Order processing router
const orderRouter = new AgentRouter({
  prefix: 'order',
  tags: ['orders', 'commerce']
});

orderRouter
  .reasoner('recommend_products', async (ctx) => {
    return await ctx.ai(`Recommend products for: ${JSON.stringify(ctx.input)}`);
  })
  .skill('create', async (ctx) => {
    return await db.orders.create(ctx.input);
  })
  .skill('get_status', async (ctx) => {
    return await db.orders.getStatus(ctx.input.orderId);
  });

// Main agent
const agent = new Agent({ nodeId: 'commerce-agent' });
agent.includeRouter(userRouter);
agent.includeRouter(orderRouter);

// Available endpoints:
// - user_analyze_behavior (reasoner)
// - user_get_profile (skill)
// - user_update_settings (skill)
// - order_recommend_products (reasoner)
// - order_create (skill)
// - order_get_status (skill)

Feature Modules

// analytics.ts
export const analyticsRouter = new AgentRouter({
  prefix: 'analytics',
  tags: ['analytics', 'reporting']
});

analyticsRouter
  .reasoner('generate_insights', async (ctx) => {
    const data = await ctx.memory.get('analytics_data');
    return await ctx.ai(`Generate insights: ${JSON.stringify(data)}`);
  })
  .skill('get_metrics', async (ctx) => {
    return await metricsService.get(ctx.input.timeRange);
  });

// notifications.ts
export const notificationsRouter = new AgentRouter({
  prefix: 'notify',
  tags: ['notifications']
});

notificationsRouter
  .skill('send_email', async (ctx) => {
    return await emailService.send(ctx.input);
  })
  .skill('send_sms', async (ctx) => {
    return await smsService.send(ctx.input);
  });

// index.ts
import { analyticsRouter } from './analytics';
import { notificationsRouter } from './notifications';

const agent = new Agent({ nodeId: 'main-agent' });
agent.includeRouter(analyticsRouter);
agent.includeRouter(notificationsRouter);

Tag-Based Discovery

// All routers share common tags
const v2Router = new AgentRouter({
  prefix: 'v2',
  tags: ['api-v2', 'stable']
});

const betaRouter = new AgentRouter({
  prefix: 'beta',
  tags: ['api-beta', 'experimental']
});

// Clients can discover by tag
const stableAPIs = await agent.discover({ tags: ['stable'] });
const betaAPIs = await agent.discover({ tags: ['experimental'] });

Nested Prefixes

// You can combine routers for nested organization
const adminUserRouter = new AgentRouter({
  prefix: 'admin_user',  // Manual nesting
  tags: ['admin', 'users']
});

// Creates: admin_user_create, admin_user_delete, etc.

Best Practices

  1. Group by domain - Keep related functionality together
  2. Use descriptive prefixes - Make endpoint names self-documenting
  3. Share tags - Enable easy discovery of related capabilities
  4. Keep routers focused - Each router should have a single responsibility

Routers are purely organizational. Once included in an agent, the reasoners and skills behave identically to those registered directly.