Agents
defineAgent is Kuralle’s single agent primitive. Behavior is derived from which fields you populate — there’s no separate FlowAgent or TriageAgent type.
The tagless primitive
Section titled “The tagless primitive”A minimal agent needs only id, instructions, and model:
import { openai } from '@ai-sdk/openai';import { defineAgent } from '@kuralle-agents/core';
const agent = defineAgent({ id: 'support', instructions: 'You are a helpful support agent.', model: openai('gpt-4o-mini'),});From there, the fields you add determine the behavior:
| Add these fields | The agent becomes |
|---|---|
| tools + effectTools | A tool-calling agent |
| flows | A structured flow agent |
| routes + routing | A triage router |
| agents + handoffs | A composition wrapper |
These aren’t mutually exclusive. An agent can have tools, a flow, and route to specialists at the same time.
Fields
Section titled “Fields”defineAgent({ id: string, name?: string, instructions?: string, model?: LanguageModel, tools?: ToolSet, // AI SDK ToolSet — what the model sees and can call effectTools?: Record<string, EffectTool>, // durable executors (from defineTool) flows?: Flow[], // structured flow graphs routes?: Route[], // route entries for triage routing?: RoutingPolicy, // { mode: 'structured', default: 'agentId' } agents?: AgentConfig[], // composed sub-agents handoffs?: string[], // agent IDs this agent can hand off to})instructions
Section titled “instructions”A string describing the agent’s role and rules. Keep it focused on persona and constraints — if you’re writing more than ~20 lines of procedure here, move it to a flow.
tools and effectTools
Section titled “tools and effectTools”tools is the AI SDK ToolSet — what the model sees when deciding what to call. effectTools is the durable executor map. Pass the same tools to both using buildToolSet:
import { defineTool, buildToolSet } from '@kuralle-agents/core';
const tools = { echo, lookup };
defineAgent({ id: 'support', instructions: '...', model: openai('gpt-4o-mini'), tools: buildToolSet(tools), // model-visible effectTools: tools, // durable executor});Attach one or more Flow objects (from defineFlow) to make the agent procedure-driven. The runtime enters the flow on the first turn and tracks node state in the session.
See the Flows guide for the full node model.
routes and routing
Section titled “routes and routing”Add routes to make the agent a triage router. With routing: { mode: 'structured' }, the routing decision is schema-only and never surfaces in the user-facing response.
See Routing & Handoffs.
agents and handoffs
Section titled “agents and handoffs”agents registers sub-agents the runtime can activate during a handoff. handoffs declares which agent IDs this agent is allowed to transfer to. The combination enables tool-based handoffs where the agent explicitly decides when to transfer.
Example
Section titled “Example”import { openai } from '@ai-sdk/openai';import { defineAgent, defineTool, buildToolSet, defineFlow, reply } from '@kuralle-agents/core';import { z } from 'zod';
// Minimal: chat agent with no flows or routingconst chatAgent = defineAgent({ id: 'chat', instructions: 'You are a helpful assistant.', model: openai('gpt-4o-mini'),});
// Tool agent: model-visible tools + durable executorsconst lookup = defineTool({ name: 'lookup', description: 'Look up a product by ID', input: z.object({ id: z.string() }), execute: async ({ id }) => ({ name: `Product ${id}`, price: 49.99 }),});
const toolAgent = defineAgent({ id: 'catalog', instructions: 'Answer product questions using the lookup tool.', model: openai('gpt-4o-mini'), tools: buildToolSet({ lookup }), // model-visible effectTools: { lookup }, // durable executor — logged and replay-safe});
// Flow agent: behavior driven by the flow graph, not the instructions aloneconst done = reply({ id: 'done', instructions: 'Confirm and end the conversation.', next: () => ({ end: 'complete' }),});
const flowAgent = defineAgent({ id: 'booking', instructions: 'You guide users through a booking.', model: openai('gpt-4o-mini'), flows: [ defineFlow({ name: 'booking', description: 'Guide the user through the booking process', start: done, nodes: [done], }), ],});