Routers
The purpose of a Network’s Router is to decide what Agent to call based off the current Network State.
What is a Router?
Section titled “What is a Router?”A router is a function that gets called after each agent runs, which decides whether to:
- Call another agent (by returning an
Agent) - Stop the network’s execution loop (by returning
undefined)
The routing function gets access to everything it needs to make this decision:
- The Network object itself, including it’s State.
- The stack of Agents to be called.
- The number of times the Network has called Agents (the number of iterations).
- The result from the previously called Agent in the Network’s execution loop.
For more information about the role of a Router in a Network, read about how Networks work.
Using a Router
Section titled “Using a Router”Providing a custom Router to your Network can be achieved using 3 different patterns:
- Writing a custom Code-based Router: Define a function that makes decisions based on the current State.
- Creating a Routing Agent: Leverages LLM calls to decide which Agents should be called next based on the current State.
- Writing a custom Hybrid Router: Mix code and agent-based routing to get the best of both worlds.
Creating a custom Router
Section titled “Creating a custom Router”Custom Routers can be provided by defining a defaultRouter function returning either an instance of an Agent object or undefined.
import { createNetwork } from "@inngest/agent-kit";
// classifier and writer Agents definition...
const network = createNetwork({ agents: [classifier, writer], router: ({ lastResult, callCount }) => { // retrieve the last message from the output const lastMessage = lastResult?.output[lastResult?.output.length - 1]; const content = lastMessage?.type === "text" ? (lastMessage?.content as string) : ""; // First call: use the classifier if (callCount === 0) { return classifier; } // Second call: if it's a question, use the writer if (callCount === 1 && content.includes("question")) { return writer; } // Otherwise, we're done! return undefined; },});The defaultRouter function receives a number of arguments:
interface RouterArgs { network: Network; // The entire network, including the state and history stack: Agent[]; // Future agents to be called callCount: number; // Number of times the Network has called agents lastResult?: InferenceResult; // The the previously called Agent's result}The available arguments can be used to build the routing patterns described below.
Routing Patterns
Section titled “Routing Patterns”- Start simple with code-based routing for predictable behavior, then add agent-based routing for flexibility.
- Remember that routers can access the network’s state
- You can return agents that weren’t in the original network
- The router runs after each agent call
- Returning
undefinedstops the network’s execution loop
That’s it! Routing is what makes networks powerful - it lets you build workflows that can be as simple or complex as you need.
Code-based Routers (supervised routing)
Section titled “Code-based Routers (supervised routing)”The simplest way to route is to write code that makes decisions. Here’s an example that routes between a classifier and a writer:
import { createNetwork } from "@inngest/agent-kit";
// classifier and writer Agents definition...
const network = createNetwork({ agents: [classifier, writer], router: ({ lastResult, callCount }) => { // retrieve the last message from the output const lastMessage = lastResult?.output[lastResult?.output.length - 1]; const content = lastMessage?.type === "text" ? (lastMessage?.content as string) : ""; // First call: use the classifier if (callCount === 0) { return classifier; } // Second call: if it's a question, use the writer if (callCount === 1 && content.includes("question")) { return writer; } // Otherwise, we're done! return undefined; },});Code-based routing is great when you want deterministic, predictable behavior. It’s also the fastest option since there’s no LLM calls involved.
Routing Agent (autonomous routing)
Section titled “Routing Agent (autonomous routing)”Without a defaultRouter defined, the network will use the “Default Routing Agent” to decide which agent to call next.
The “Default Routing Agent” is a Routing Agent provided by Agent Kit to handle the default routing logic.
You can create your own Routing Agent by using the createRoutingAgent helper function:
import { createRoutingAgent } from "@inngest/agent-kit";
const routingAgent = createRoutingAgent({ name: "Custom routing agent", description: "Selects agents based on the current state and request", lifecycle: { onRoute: ({ result, network }) => { // custom logic... }, },});
// classifier and writer Agents definition...
const network = createNetwork({ agents: [classifier, writer], router: routingAgent,});Hybrid code and agent Routers (semi-supervised routing)
Section titled “Hybrid code and agent Routers (semi-supervised routing)”And, of course, you can mix code and agent-based routing. Here’s an example that uses code for the first step, then lets an agent take over:
import { createNetwork, getDefaultRoutingAgent } from "@inngest/agent-kit";
// classifier and writer Agents definition...
const network = createNetwork({ agents: [classifier, writer], router: ({ callCount }) => { // Always start with the classifier if (callCount === 0) { return classifier; } // Then let the routing agent take over return getDefaultRoutingAgent(); },});This gives you the best of both worlds:
- Predictable first steps when you know what needs to happen
- Flexibility when the path forward isn’t clear
Using state in Routing
Section titled “Using state in Routing”The router is the brain of your network - it decides which agent to call next. You can use state to make smart routing decisions:
import { createNetwork } from '@inngest/agent-kit';
// mathAgent and contextAgent Agents definition...
const network = createNetwork({ agents: [mathAgent, contextAgent], router: ({ network, lastResult }): Agent | undefined => { // Check if we've solved the problem const solution = network.state.data.solution; if (solution) { // We're done - return undefined to stop the network return undefined; }
// retrieve the last message from the output const lastMessage = lastResult?.output[lastResult?.output.length - 1]; const content = lastMessage?.type === 'text' ? lastMessage?.content as string : '';
// Check the last result to decide what to do next if (content.includes('need more context')) { return contextAgent; }
return mathAgent; };});