Prebuilt Agent Helpers
Though we recommend developers writing nodes manually, sometimes it’s useful to have helpers to quickly set up nodes for common cases and repetitive tasks like calling LLMs, converting to CanonicalMessage, etc.
cascaide-ts/helpers comes with helpers to set up:
- ReAct agents
- Supervisor agents
- Recursive ReAct agents
- Recursive Supervisor agents
It also includes utility functions for common LLM-related needs like callLLM, toProviderHistory, buildToolResultMessage, and more.
API Inventory
Agent factories
createReactAgentcreateRecursiveReactAgentcreateSupervisorAgentcreateRecursiveSupervisorAgent
LLM utilities
callLLMtoProviderHistorybuildToolsextractToolCallsbuildToolResultMessagebuildErrorToolResultMessageparseCompletedResponse
Core types
CanonicalMessageCanonicalToolCallCanonicalToolResultToolParamToolDefinitionSubAgentDescriptorLLMProviderReactAgentBundle
Agent Factories
All four factories return a ReactAgentBundle — a pair of wired nodes ready to spread directly into your cascade graph.
interface ReactAgentBundle {
agentNode: { prep: any; exec: any; post: any };
toolNode: { prep: any; exec: any; post: any };
nodes: Record<string, any>;
}createReactAgent
A standard ReAct loop. The agent calls tools and loops until it has a final answer. No delegation.
function createReactAgent(
name: string,
config: ReactAgentConfig
): ReactAgentBundleinterface ReactAgentConfig {
provider: LLMProvider;
model: string;
systemPrompt: string;
tools?: ToolDefinition[];
isStreaming?: boolean; // default: true
env?: 'server' | 'client'; // default: 'server'
}Example
const { nodes } = createReactAgent('search', {
provider: 'openai-responses',
model: 'gpt-4o-mini',
systemPrompt: 'You are a helpful research assistant.',
tools: [webSearchTool],
});createRecursiveReactAgent
A ReAct agent that can spawn parallel instances of itself to handle independent subtasks concurrently.
The delegate_to_<name> tool is automatically added.
function createRecursiveReactAgent(
name: string,
config: RecursiveReactAgentConfig
): ReactAgentBundleinterface RecursiveReactAgentConfig extends ReactAgentConfig {
maxDepth?: number; // default: 2
}Example
const { nodes } = createRecursiveReactAgent('researcher', {
provider: 'anthropic',
model: 'claude-opus-4-5',
systemPrompt: 'Break large research tasks into parallel subtasks.',
tools: [webSearchTool, scrapePageTool],
maxDepth: 2,
});createSupervisorAgent
An agent that delegates to a fixed set of named sub-agents.
Each sub-agent becomes a delegate_to_<subAgentName> tool.
function createSupervisorAgent(
name: string,
config: SupervisorAgentConfig
): ReactAgentBundleinterface SupervisorAgentConfig extends ReactAgentConfig {
subAgents: SubAgentDescriptor[];
}
interface SubAgentDescriptor {
name: string;
description: string;
}Example
const { nodes } = createSupervisorAgent('orchestrator', {
provider: 'openai-responses',
model: 'gpt-4o',
systemPrompt: 'Coordinate the search and writer agents.',
subAgents: [
{ name: 'searchAgentNode', description: 'Searches the web.' },
{ name: 'writerAgentNode', description: 'Writes polished content.' },
],
});createRecursiveSupervisorAgent
Combines both delegation modes:
- Can spawn parallel instances of itself
- Can delegate to sub-agents
function createRecursiveSupervisorAgent(
name: string,
config: RecursiveSupervisorAgentConfig
): ReactAgentBundleinterface RecursiveSupervisorAgentConfig extends ReactAgentConfig {
subAgents: SubAgentDescriptor[];
maxDepth?: number;
}Example
const { nodes } = createRecursiveSupervisorAgent('planner', {
provider: 'anthropic',
model: 'claude-opus-4-5',
systemPrompt: 'Plan and delegate.',
subAgents: [
{ name: 'searchAgentNode', description: 'Searches the web.' },
{ name: 'codeAgentNode', description: 'Writes code.' },
],
maxDepth: 3,
});Using the returned nodes
const { nodes: searchNodes } = createReactAgent('search', { ... });
const { nodes: writerNodes } = createReactAgent('writer', { ... });
const { nodes: orchNodes } = createSupervisorAgent('orchestrator', { ... });
const graph = {
...searchNodes,
...writerNodes,
...orchNodes,
};Node names follow:
<name>AgentNode
<name>ToolNodeLLM Utilities
callLLM
Dispatches a request to the correct provider SDK.
// Streaming
async function callLLM(
provider: LLMProvider,
model: string,
systemPrompt: string,
history: any[],
nativeTools: any,
isStreaming: true
): Promise<{ stream: any; provider: LLMProvider }>
// Non-streaming
async function callLLM(
provider: LLMProvider,
model: string,
systemPrompt: string,
history: any[],
nativeTools: any,
isStreaming: false
): Promise<{ response: any; provider: LLMProvider }>Uses env vars:
ANTHROPIC_API_KEYOPENAI_API_KEYGEMINI_API_KEY
toProviderHistory
function toProviderHistory(
provider: LLMProvider,
history: CanonicalMessage[]
): any[]buildTools
function buildTools(
provider: LLMProvider,
tools: ToolParam[]
): anyextractToolCalls
function extractToolCalls(
provider: LLMProvider,
assistantMessage: CanonicalMessage
): CanonicalToolCall[]buildToolResultMessage
function buildToolResultMessage(
provider: LLMProvider,
toolCall: CanonicalToolCall,
resultData: any
): CanonicalMessagebuildErrorToolResultMessage
function buildErrorToolResultMessage(
provider: LLMProvider,
toolCall: CanonicalToolCall,
errorMessage: string
): CanonicalMessageparseCompletedResponse
function parseCompletedResponse(
provider: LLMProvider,
response: any
): CanonicalMessageCore Types
CanonicalMessage
interface CanonicalMessage {
role: 'user' | 'assistant' | 'tool';
content?: string;
thinking?: string;
tool_calls?: CanonicalToolCall[];
tool_result?: CanonicalToolResult;
extensions?: Record<string, any>;
}CanonicalToolCall
interface CanonicalToolCall {
id: string;
name: string;
args: Record<string, any>;
}CanonicalToolResult
interface CanonicalToolResult {
tool_call_id: string;
name?: string;
content: string;
}ToolDefinition
interface ToolDefinition extends ToolParam {
execute: (
args: Record<string, any>,
controller?: CascadeController
) => Promise<any>;
}LLMProvider
type LLMProvider =
| 'anthropic'
| 'openai'
| 'openai-responses'
| 'gemini-genai';