Graph Workflows
Build complex conditional workflows with branching logic.
Graph workflows allow you to create sophisticated processing pipelines with conditions, parallel execution, and dynamic routing based on LLM classification.
Orka — GRAPH WORKFLOW ARCHITECTURE
START
actionNode
'classify'
LLM classifies input into categories
conditionNode
'router'
"technical"
retrieveNode
'faq', topK: 3
llmNode
'tech-answer'
Expert + RAG
"billing"
llmNode
'billing-answer'
Billing expert
"general"
llmNode
'general-answer'
General support
END
GraphResult
output:string
path:string[]
metadata:object
Entry / Exit
LLM Node
Retrieve (RAG)
Condition Router
1. Available Node Types
Orka provides several built-in node types for common operations:
node-types.ts
import { startNode, // Graph entry point endNode, // Graph exit point actionNode, // Custom logic (async function) conditionNode, // Conditional routing (returns edge name) llmNode, // LLM generation with options retrieveNode, // RAG search in knowledge base edge // Connection between nodes} from 'orkajs'; // startNode: Initialize contextstartNode('start') // endNode: Terminate executionendNode('end') // actionNode: Custom logicactionNode('process', async (ctx) => { ctx.output = await someAsyncOperation(ctx.input); ctx.metadata.processed = true; return ctx;}) // conditionNode: Dynamic routingconditionNode('router', (ctx) => { if (ctx.metadata.score > 0.8) return 'high-quality'; if (ctx.metadata.score > 0.5) return 'medium'; return 'low';}) // llmNode: LLM generationllmNode('generate', { systemPrompt: 'You are an expert assistant.', temperature: 0.3, promptTemplate: 'Context: {{context}}\n\nQuestion: {{input}}'}) // retrieveNode: RAGretrieveNode('search', 'knowledge-base-name', { topK: 5 })2. Complete Smart Support Example
graph-workflow.ts
import { createOrka, OpenAIAdapter, MemoryVectorAdapter, startNode, endNode, actionNode, conditionNode, llmNode, retrieveNode, edge} from 'orkajs'; async function main() { const orka = createOrka({ llm: new OpenAIAdapter({ apiKey: process.env.OPENAI_API_KEY! }), vectorDB: new MemoryVectorAdapter(), }); // Create FAQ knowledge base await orka.knowledge.create({ name: 'faq', source: [ { text: 'Pour réinitialiser votre mot de passe, allez dans Paramètres > Sécurité.', metadata: { topic: 'password' } }, { text: 'Les remboursements sont traités sous 5 jours ouvrés.', metadata: { topic: 'refund' } }, { text: 'Contactez-nous à support@example.com pour toute question.', metadata: { topic: 'contact' } }, ], }); // Define the graph const graph = orka.graph({ name: 'smart-support', nodes: [ startNode('start'), // Classify question with LLM actionNode('classify', async (ctx) => { const result = await ctx.llm.generate( `Classify this question into one category: "technical", "billing", or "general".Question: ${ctx.input}Respond with ONLY the category.`, { temperature: 0, maxTokens: 10 } ); ctx.output = result.content.trim().toLowerCase(); ctx.metadata.category = ctx.output; return ctx; }), // Conditional router based on classification conditionNode('router', (ctx) => { const category = (ctx.metadata.category as string) ?? 'general'; if (category.includes('technical')) return 'technical'; if (category.includes('billing')) return 'billing'; return 'general'; }), // Technical branch: RAG + LLM retrieveNode('tech-retrieve', 'faq', { topK: 3 }), llmNode('tech-answer', { systemPrompt: 'You are a technical expert. Answer based on the context.', temperature: 0.3, promptTemplate: 'Context:\n{{context}}\n\nTechnical question: {{input}}', }), // Billing branch: Direct LLM llmNode('billing-answer', { systemPrompt: 'You are a billing expert. Be precise and professional.', temperature: 0.3, }), // General branch llmNode('general-answer', { systemPrompt: 'You are a general support assistant. Be helpful and concise.', temperature: 0.5, }), endNode('end'), ], edges: [ edge('start', 'classify'), edge('classify', 'router'), // Edges conditionnels avec label edge('router', 'tech-retrieve', 'technical'), edge('router', 'billing-answer', 'billing'), edge('router', 'general-answer', 'general'), // Convergence vers end edge('tech-retrieve', 'tech-answer'), edge('tech-answer', 'end'), edge('billing-answer', 'end'), edge('general-answer', 'end'), ], onNodeComplete: (nodeId, ctx) => { console.log(`✅ Node "${nodeId}" completed`); }, }); // Run the graph const result = await graph.run('How do I reset my password?'); console.log(`Output: ${result.output}`); console.log(`Path: ${result.path.join(' → ')}`); console.log(`Latency: ${result.totalLatencyMs}ms`); console.log(`Category: ${result.metadata.category}`);}3. Mermaid Diagram Export
Visualize your graph structure with automatic Mermaid diagram generation:
mermaid-export.ts
// Generate the Mermaid diagramconst mermaidCode = graph.toMermaid();console.log(mermaidCode); // Output:// graph TD// start([Start])// classify[classify]// router{router}// tech-retrieve[tech-retrieve]// tech-answer[tech-answer]// billing-answer[billing-answer]// general-answer[general-answer]// end([End])// start --> classify// classify --> router// router -->|technical| tech-retrieve// router -->|billing| billing-answer// router -->|general| general-answer// tech-retrieve --> tech-answer// tech-answer --> end// billing-answer --> end// general-answer --> end4. GraphResult Structure
graph-result.ts
interface GraphResult { output: string; // Final output of the graph path: string[]; // Path taken: ['start', 'classify', 'router', 'tech-answer', 'end'] metadata: Record<string, unknown>; // Accumulated metadata totalLatencyMs: number; // Total execution time nodeResults: Map<string, NodeResult>; // Results by node} // Example usageconst result = await graph.run('Ma question...'); // Analyze the path takenif (result.path.includes('tech-answer')) { console.log('Technical question detected');} // Access metadataconsole.log('Category:', result.metadata.category); // Time per nodefor (const [nodeId, nodeResult] of result.nodeResults) { console.log(`${nodeId}: ${nodeResult.latencyMs}ms`);}Common Use Cases
🎯 Intent Classification
Route queries to specialized handlers based on LLM classification
📚 Conditional RAG
Only retrieve context when needed, skip for simple queries
🔄 Multi-Stage Processing
Chain multiple LLM calls with intermediate processing
⚡ Quality Gates
Verify output quality and retry or escalate if needed