Based on Anthropic’s “Building Effective Agents” framework.

Routing directs different types of requests to specialized handlers optimized for specific domains. A classification step determines the request type, then routes it to the appropriate specialized agent or tool. This pattern improves response quality by using domain-specific prompts and context while maintaining a single entry point for users.

Client
Router Agent
Classification
Support Handler
Sales Handler
request
classify
category
route to handler
specialized response
response

When to Use

Use routing when you have distinct request types that benefit from specialized handling, such as customer service systems with support, sales, and billing inquiries. It’s ideal when different domains require different prompts, tools, or context. Avoid routing when requests are too similar to benefit from specialization or when the classification overhead outweighs the benefits of specialized handling.

Implementation

This example demonstrates a customer service router that classifies incoming messages as Support, Sales, or Other requests, then directs them to specialized handlers optimized for each domain.

Agent Code

import { pickaxe } from "@hatchet-dev/pickaxe";
import z from "zod";
import { classificationTool } from "@tools/classification.tool";
import { supportTool, salesTool } from "@tools/calls.tool";

const RoutingAgentInput = z.object({
  message: z.string(),
});

const RoutingAgentOutput = z.object({
  message: z.string(),
  canHelp: z.boolean(),
});

export const routingAgent = pickaxe.agent({
  name: "routing-agent",
  executionTimeout: "1m",
  inputSchema: RoutingAgentInput,
  outputSchema: RoutingAgentOutput,
  description: "Routes messages to specialized handlers based on classification",
  fn: async (input, ctx) => {
    // STEP 1: Classify the incoming message
    const { classification } = await classificationTool.run({
      message: input.message,
    });

    // STEP 2: Route to specialized handler based on classification
    switch (classification) {
      case "support": {
        const { response } = await supportTool.run({
          message: input.message,
        });
        return {
          message: response,
          canHelp: true,
        };
      }
      case "sales": {
        const { response } = await salesTool.run({
          message: input.message,
        });
        return {
          message: response,
          canHelp: true,
        };
      }
      case "other": {
        return {
          message: "I'm not sure how to help with that. Could you provide more details or rephrase your question?",
          canHelp: false,
        };
      }
      default: {
        throw new Error(`Invalid classification: ${classification}`);
      }
    }
  },
});

The pattern uses a two-step process: classification determines the request type, then specialized handlers provide domain-optimized responses. Each handler uses prompts and context tailored to its specific domain, improving response quality compared to a general-purpose agent. The canHelp boolean indicates whether the system can assist with the request.

This pattern complements prompt chaining for complex multi-step workflows and can be combined with parallelization when multiple handlers need to process the same request simultaneously.