Routing & Handoffs
When a conversation can go to multiple specialists, you need a router. Kuralle’s routes + routing setup handles the decision and the handoff without surfacing triage logic to the user.
Defining a router
Section titled “Defining a router”Add routes and routing to defineAgent:
import { openai } from '@ai-sdk/openai';import { defineAgent } from '@kuralle-agents/core';
const triage = defineAgent({ id: 'triage', instructions: 'Route the user to the right specialist.', model: openai('gpt-4o-mini'), routes: [ { agent: 'billing', when: 'billing question or payment issue' }, { agent: 'support', when: 'product support request' }, ], routing: { mode: 'structured', default: 'support' },});Each routes entry has an agent (the destination agent’s id) and a when description. The model uses these descriptions to select the right route.
Structured routing
Section titled “Structured routing”mode: 'structured' routes via schema — the model outputs a structured decision object, not a user-facing message. The routing choice never appears in the user’s conversation.
default is the fallback agent when no route matches closely enough.
Handoffs
Section titled “Handoffs”A handoff moves the conversation to another agent and carries full session context. The receiving agent picks up with the complete message history.
For tool-based handoffs — where the agent decides explicitly when to transfer — declare which agent IDs the agent can hand off to with handoffs, and wire a handoff tool:
const transferToSpanish = defineTool({ name: 'transfer_to_spanish', description: 'Transfer to a Spanish-speaking agent when the user requests Spanish.', input: z.object({ reason: z.string() }), execute: async ({ reason }) => ({ __handoff: true, targetAgentId: 'spanish-agent', reason, }),});
const englishAgent = defineAgent({ id: 'english', instructions: 'Friendly assistant. If the user speaks Spanish, use transfer_to_spanish.', model: openai('gpt-4o-mini'), handoffs: ['spanish-agent'], agents: [spanishAgent], tools: buildToolSet({ transfer_to_spanish: transferToSpanish }), effectTools: { transfer_to_spanish: transferToSpanish },});The runtime intercepts { __handoff: true, targetAgentId } in the tool result and routes the session to the target agent.
Example: triage router
Section titled “Example: triage router”import { openai } from '@ai-sdk/openai';import { defineAgent, createRuntime } from '@kuralle-agents/core';
const billingAgent = defineAgent({ id: 'billing', instructions: 'You handle billing questions and payment issues.', model: openai('gpt-4o-mini'),});
const supportAgent = defineAgent({ id: 'support', instructions: 'You handle product support requests.', model: openai('gpt-4o-mini'),});
// mode: 'structured' routes via schema — the routing decision never surfaces to the userconst triage = defineAgent({ id: 'triage', instructions: 'Route the user to the right specialist.', model: openai('gpt-4o-mini'), routes: [ { agent: 'billing', when: 'billing question or payment issue' }, { agent: 'support', when: 'product support request' }, ], routing: { mode: 'structured', default: 'support' },});
const runtime = createRuntime({ agents: [triage, billingAgent, supportAgent], defaultAgentId: 'triage',});