@nextsparkjs/plugin-langchain 0.1.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/.env.example +41 -0
  2. package/api/observability/metrics/route.ts +110 -0
  3. package/api/observability/traces/[traceId]/route.ts +398 -0
  4. package/api/observability/traces/route.ts +205 -0
  5. package/api/sessions/route.ts +332 -0
  6. package/components/observability/CollapsibleJson.tsx +71 -0
  7. package/components/observability/CompactTimeline.tsx +75 -0
  8. package/components/observability/ConversationFlow.tsx +271 -0
  9. package/components/observability/DisabledMessage.tsx +21 -0
  10. package/components/observability/FiltersPanel.tsx +82 -0
  11. package/components/observability/ObservabilityDashboard.tsx +230 -0
  12. package/components/observability/SpansList.tsx +210 -0
  13. package/components/observability/TraceDetail.tsx +335 -0
  14. package/components/observability/TraceStatusBadge.tsx +39 -0
  15. package/components/observability/TracesTable.tsx +97 -0
  16. package/components/observability/index.ts +7 -0
  17. package/docs/01-getting-started/01-overview.md +196 -0
  18. package/docs/01-getting-started/02-installation.md +368 -0
  19. package/docs/01-getting-started/03-configuration.md +794 -0
  20. package/docs/02-core-concepts/01-architecture.md +566 -0
  21. package/docs/02-core-concepts/02-agents.md +597 -0
  22. package/docs/02-core-concepts/03-tools.md +689 -0
  23. package/docs/03-orchestration/01-graph-orchestrator.md +809 -0
  24. package/docs/03-orchestration/02-legacy-react.md +650 -0
  25. package/docs/04-advanced/01-observability.md +645 -0
  26. package/docs/04-advanced/02-token-tracking.md +469 -0
  27. package/docs/04-advanced/03-streaming.md +476 -0
  28. package/docs/04-advanced/04-guardrails.md +597 -0
  29. package/docs/05-reference/01-api-reference.md +1403 -0
  30. package/docs/05-reference/02-customization.md +646 -0
  31. package/docs/05-reference/03-examples.md +881 -0
  32. package/docs/index.md +85 -0
  33. package/hooks/observability/useMetrics.ts +31 -0
  34. package/hooks/observability/useTraceDetail.ts +48 -0
  35. package/hooks/observability/useTraces.ts +59 -0
  36. package/lib/agent-factory.ts +354 -0
  37. package/lib/agent-helpers.ts +201 -0
  38. package/lib/db-memory-store.ts +417 -0
  39. package/lib/graph/index.ts +58 -0
  40. package/lib/graph/nodes/combiner.ts +399 -0
  41. package/lib/graph/nodes/router.ts +440 -0
  42. package/lib/graph/orchestrator-graph.ts +386 -0
  43. package/lib/graph/prompts/combiner.md +131 -0
  44. package/lib/graph/prompts/router.md +193 -0
  45. package/lib/graph/types.ts +365 -0
  46. package/lib/guardrails.ts +230 -0
  47. package/lib/index.ts +44 -0
  48. package/lib/logger.ts +70 -0
  49. package/lib/memory-store.ts +168 -0
  50. package/lib/message-serializer.ts +110 -0
  51. package/lib/prompt-renderer.ts +94 -0
  52. package/lib/providers.ts +226 -0
  53. package/lib/streaming.ts +232 -0
  54. package/lib/token-tracker.ts +298 -0
  55. package/lib/tools-builder.ts +192 -0
  56. package/lib/tracer-callbacks.ts +342 -0
  57. package/lib/tracer.ts +350 -0
  58. package/migrations/001_langchain_memory.sql +83 -0
  59. package/migrations/002_token_usage.sql +127 -0
  60. package/migrations/003_observability.sql +257 -0
  61. package/package.json +28 -0
  62. package/plugin.config.ts +170 -0
  63. package/presets/lib/langchain.config.ts.preset +142 -0
  64. package/presets/templates/sector7/ai-observability/[traceId]/page.tsx +91 -0
  65. package/presets/templates/sector7/ai-observability/page.tsx +54 -0
  66. package/types/langchain.types.ts +274 -0
  67. package/types/observability.types.ts +270 -0
@@ -0,0 +1,809 @@
1
+ # Graph-Based Orchestration
2
+
3
+ This guide covers the **LangGraph-based orchestrator**, the recommended approach for multi-agent systems. It replaces inefficient ReAct loops with an explicit state machine, achieving 25-50x faster execution with deterministic flow.
4
+
5
+ > **Note**: For the legacy ReAct-based approach, see [Legacy Orchestration](./02-legacy-react.md) (deprecated).
6
+
7
+ ## Why Graph-Based Orchestration?
8
+
9
+ The traditional ReAct (Reasoning + Acting) pattern has significant drawbacks at scale:
10
+
11
+ ### The Problem with ReAct Loops
12
+
13
+ ```
14
+ User: "Show my tasks and find StartupXYZ account number"
15
+
16
+ ┌─────────────────────────────────────────────────────────────┐
17
+ │ ORCHESTRATOR ReAct Loop (~10-20 iterations) │
18
+ │ ├─ Think → Act → Observe → Think → Act... │
19
+ │ └─ Decide: route_to_task │
20
+ │ ↓ │
21
+ │ ┌─────────────────────────────────────────────────┐ │
22
+ │ │ TASK-ASSISTANT ReAct Loop (~10-15 iterations) │ │
23
+ │ │ └─ Think → Act → Observe → Think... │ │
24
+ │ └─────────────────────────────────────────────────┘ │
25
+ │ ↓ (returns to orchestrator) │
26
+ │ ├─ Think → decide second part │
27
+ │ └─ Decide: route_to_customer │
28
+ │ ↓ │
29
+ │ ┌─────────────────────────────────────────────────┐ │
30
+ │ │ CUSTOMER-ASSISTANT ReAct Loop (~10-15 iter) │ │
31
+ │ └─────────────────────────────────────────────────┘ │
32
+ └─────────────────────────────────────────────────────────────┘
33
+
34
+ TOTAL: 50+ LLM iterations → TIMEOUT (2-5 minutes)
35
+ ```
36
+
37
+ **Issues:**
38
+ - **50+ LLM calls** for a simple multi-intent request
39
+ - **Recursion limit errors** from nested loops
40
+ - **Non-deterministic** - different paths each time
41
+ - **Expensive** - each iteration costs tokens
42
+ - **Slow** - 2-5 minute response times
43
+
44
+ ### The Solution: Explicit State Machine
45
+
46
+ ```
47
+ User: "Show my tasks and find StartupXYZ account number"
48
+
49
+ ┌─────────────────────────────────────────────────────────────┐
50
+ │ START │
51
+ │ ↓ │
52
+ │ ┌─────────────┐ │
53
+ │ │ ROUTER │ ← 1 LLM call │
54
+ │ │ (Intent) │ (structured output) │
55
+ │ └──────┬──────┘ │
56
+ │ ↓ │
57
+ │ ┌───────────────┴───────────────┐ │
58
+ │ ↓ ↓ │
59
+ │ ┌──────────────┐ ┌──────────────┐ │
60
+ │ │ TASK_HANDLER │ │ CUST_HANDLER │ │
61
+ │ │ (0 LLM) │ │ (0 LLM) │ │
62
+ │ └───────┬──────┘ └───────┬──────┘ │
63
+ │ ↓ ↓ │
64
+ │ └─────────────┬───────────────┘ │
65
+ │ ↓ │
66
+ │ ┌─────────────┐ │
67
+ │ │ COMBINER │ ← 1 LLM call │
68
+ │ │ (Response) │ (optional) │
69
+ │ └──────┬──────┘ │
70
+ │ ↓ │
71
+ │ END │
72
+ └─────────────────────────────────────────────────────────────┘
73
+
74
+ TOTAL: 2 LLM calls → 2-3 seconds
75
+ ```
76
+
77
+ **Benefits:**
78
+ - **1-2 LLM calls** instead of 50+
79
+ - **No recursion** - explicit transitions
80
+ - **Deterministic** - same input = same path
81
+ - **Cost effective** - 25-50x fewer tokens
82
+ - **Fast** - 2-10 second responses
83
+
84
+ ---
85
+
86
+ ## Theoretical Foundations
87
+
88
+ ### What is LangGraph?
89
+
90
+ LangGraph is a framework for building **stateful, multi-step AI applications** using explicit graphs. Unlike ReAct patterns where the LLM decides what to do next in a loop, LangGraph defines explicit states and transitions.
91
+
92
+ Key concepts:
93
+
94
+ | Concept | Description |
95
+ |---------|-------------|
96
+ | **State** | The data that flows through the graph |
97
+ | **Node** | A function that transforms state |
98
+ | **Edge** | Connection between nodes |
99
+ | **Conditional Edge** | Edge that chooses next node based on state |
100
+ | **Channel** | How state updates are merged |
101
+
102
+ ### State Machines vs ReAct Loops
103
+
104
+ | Aspect | ReAct Loop | State Machine |
105
+ |--------|------------|---------------|
106
+ | **Control Flow** | LLM decides | Code defines |
107
+ | **Predictability** | Variable | Deterministic |
108
+ | **LLM Calls** | O(n) per step | O(1) total |
109
+ | **Debugging** | Hard (black box) | Easy (explicit) |
110
+ | **Parallelism** | Limited | Native support |
111
+
112
+ ### Why Deterministic Flow Matters
113
+
114
+ 1. **Reproducibility**: Same input produces same execution path
115
+ 2. **Debugging**: You can trace exactly which nodes executed
116
+ 3. **Testing**: Unit test each node independently
117
+ 4. **Cost Control**: Predictable token usage
118
+ 5. **SLA Compliance**: Guaranteed response times
119
+
120
+ ---
121
+
122
+ ## Architecture
123
+
124
+ ### Graph Overview
125
+
126
+ ```
127
+ ┌──────────────────────────────────────────────────────┐
128
+ │ ORCHESTRATOR GRAPH │
129
+ │ │
130
+ User Input ──────┤ │
131
+ │ ┌─────────┐ │
132
+ │ │ START │ │
133
+ │ └────┬────┘ │
134
+ │ │ │
135
+ │ ▼ │
136
+ │ ┌──────────┐ Structured Output │
137
+ │ │ ROUTER │ ◄── (Zod Schema) │
138
+ │ │ (LLM) │ Intent Classification │
139
+ │ └────┬─────┘ │
140
+ │ │ │
141
+ │ ┌────┴────┬────────────┬─────────────┐ │
142
+ │ ▼ ▼ ▼ ▼ │
143
+ │ greeting clarify single multi │
144
+ │ │ │ intent intent │
145
+ │ │ │ │ │ │
146
+ │ │ │ ▼ ▼ │
147
+ │ │ │ ┌──────────┐ ┌──────────┐ │
148
+ │ │ │ │ HANDLER │ │ HANDLER │ ... │
149
+ │ │ │ │ (No LLM) │ │ (No LLM) │ │
150
+ │ │ │ └────┬─────┘ └────┬─────┘ │
151
+ │ │ │ │ │ │
152
+ │ │ │ └──────┬──────┘ │
153
+ │ │ │ ▼ │
154
+ │ │ │ ┌──────────┐ │
155
+ │ └─────────┴─────────►│ COMBINER │ │
156
+ │ │ (LLM) │ │
157
+ │ └────┬─────┘ │
158
+ │ │ │
159
+ │ ▼ │
160
+ │ ┌────────┐ │
161
+ Response ◄───────┤ │ END │ │
162
+ │ └────────┘ │
163
+ └──────────────────────────────────────────────────────┘
164
+ ```
165
+
166
+ ### Node Responsibilities
167
+
168
+ | Node | Purpose | LLM Calls | Input | Output |
169
+ |------|---------|-----------|-------|--------|
170
+ | **Router** | Classify user intent | 1 | User message | Intent[] |
171
+ | **Task Handler** | Execute task operations | 0 | Intent | JSON result |
172
+ | **Customer Handler** | Execute customer operations | 0 | Intent | JSON result |
173
+ | **Page Handler** | Execute page operations | 0 | Intent | JSON result |
174
+ | **Combiner** | Synthesize response | 0-1 | All results | User text |
175
+
176
+ ### Data Flow
177
+
178
+ 1. **User Input** → Raw message string
179
+ 2. **Router** → Parses to structured `Intent[]`
180
+ 3. **Handlers** → Execute operations, return JSON
181
+ 4. **Combiner** → Converts JSON to natural language
182
+ 5. **Response** → Text for user
183
+
184
+ ---
185
+
186
+ ## Nodes Reference
187
+
188
+ ### Router Node
189
+
190
+ The router is the "brain" that classifies user intent in a single LLM call.
191
+
192
+ **Location**: `lib/graph/nodes/router.ts`
193
+
194
+ **Features**:
195
+ - **Structured Output**: Uses Zod schema for reliable JSON extraction
196
+ - **Multi-Intent**: Detects multiple intents in one message
197
+ - **Retry Logic**: Handles malformed responses from local models
198
+ - **Provider Agnostic**: Works with OpenAI, Anthropic, Ollama, LM Studio
199
+
200
+ **Output Schema**:
201
+
202
+ ```typescript
203
+ const RouterOutputSchema = z.object({
204
+ intents: z.array(z.object({
205
+ type: z.enum(['task', 'customer', 'page', 'greeting', 'clarification']),
206
+ action: z.enum(['list', 'create', 'update', 'delete', 'search', 'get', 'unknown']),
207
+ parameters: z.record(z.unknown()),
208
+ originalText: z.string(),
209
+ })),
210
+ needsClarification: z.boolean(),
211
+ clarificationQuestion: z.string().nullable(),
212
+ })
213
+ ```
214
+
215
+ **Examples**:
216
+
217
+ ```
218
+ Input: "Show my tasks"
219
+ Output: {
220
+ intents: [{
221
+ type: "task",
222
+ action: "list",
223
+ parameters: {},
224
+ originalText: "Show my tasks"
225
+ }],
226
+ needsClarification: false
227
+ }
228
+
229
+ Input: "Create task 'Buy milk' high priority and find customer ABC"
230
+ Output: {
231
+ intents: [
232
+ { type: "task", action: "create", parameters: { title: "Buy milk", priority: "high" } },
233
+ { type: "customer", action: "search", parameters: { query: "ABC" } }
234
+ ],
235
+ needsClarification: false
236
+ }
237
+ ```
238
+
239
+ ### Handler Nodes
240
+
241
+ Handlers execute operations **without LLM calls** - they directly call entity services.
242
+
243
+ #### Task Handler
244
+
245
+ **Location**: `lib/graph/nodes/task-handler.ts`
246
+
247
+ **Supported Actions**:
248
+ - `list` - Get all tasks with optional filters
249
+ - `get` - Get single task by ID
250
+ - `create` - Create new task
251
+ - `update` - Update task fields
252
+ - `search` - Find tasks by query
253
+ - `delete` - Delete task
254
+
255
+ **Example**:
256
+
257
+ ```typescript
258
+ // Intent: { type: "task", action: "create", parameters: { title: "Buy milk", priority: "high" } }
259
+
260
+ // Handler calls:
261
+ await TasksService.create(userId, teamId, { title: "Buy milk", priority: "high" })
262
+
263
+ // Returns:
264
+ {
265
+ success: true,
266
+ operation: "create",
267
+ data: { id: "123", title: "Buy milk", priority: "high", status: "todo" },
268
+ message: "Created task: Buy milk"
269
+ }
270
+ ```
271
+
272
+ #### Customer Handler
273
+
274
+ **Location**: `lib/graph/nodes/customer-handler.ts`
275
+
276
+ **Supported Actions**:
277
+ - `list` - Get all customers
278
+ - `get` - Get single customer
279
+ - `create` - Create new customer
280
+ - `update` - Update customer fields
281
+ - `search` - Find customers by name, email, phone, account
282
+ - `delete` - Delete customer
283
+
284
+ #### Page Handler
285
+
286
+ **Location**: `lib/graph/nodes/page-handler.ts`
287
+
288
+ **Supported Actions**:
289
+ - `list` - Get published pages
290
+ - `get` - Get page by ID or slug
291
+ - `search` - Find pages by title
292
+
293
+ > **Note**: Create/Update/Delete for pages returns error directing to Page Builder UI.
294
+
295
+ ### Combiner Node
296
+
297
+ The combiner converts JSON handler results into natural language.
298
+
299
+ **Location**: `lib/graph/nodes/combiner.ts`
300
+
301
+ **Optimization**: For simple single-intent operations, uses **template-based responses** without LLM:
302
+
303
+ ```typescript
304
+ // Template response (no LLM needed):
305
+ // Intent: list 3 tasks
306
+ "Found 3 task(s):
307
+ • Buy milk (high) - todo
308
+ • Call client (medium) - in-progress
309
+ • Review docs (low) - done"
310
+
311
+ // LLM response (multi-intent or complex):
312
+ // Uses GPT-4o-mini to synthesize natural response
313
+ ```
314
+
315
+ **When LLM is used**:
316
+ - Multiple handler results (task + customer)
317
+ - List/search with >5 items
318
+ - Complex data requiring summarization
319
+
320
+ **When templates are used**:
321
+ - Single intent operations
322
+ - Simple list/search with <=5 items
323
+ - CRUD confirmations
324
+
325
+ ---
326
+
327
+ ## State Schema
328
+
329
+ ### OrchestratorState
330
+
331
+ The complete state that flows through the graph:
332
+
333
+ ```typescript
334
+ interface OrchestratorState {
335
+ // ---- Input (immutable) ----
336
+ input: string // User message
337
+ sessionId: string // Session identifier
338
+ context: AgentContext // userId, teamId
339
+ conversationHistory: BaseMessage[] // Recent messages (last 5)
340
+
341
+ // ---- Router Output ----
342
+ intents: Intent[] // Classified intents
343
+ needsClarification: boolean // If true, ask user
344
+ clarificationQuestion?: string // Question to ask
345
+
346
+ // ---- Handler Outputs ----
347
+ handlerResults: { // JSON from each handler
348
+ task?: TaskHandlerResult
349
+ customer?: CustomerHandlerResult
350
+ page?: PageHandlerResult
351
+ }
352
+ completedHandlers: IntentType[] // Which handlers ran
353
+
354
+ // ---- Final Output ----
355
+ finalResponse: string | null // Text for user
356
+ error: string | null // Error message
357
+
358
+ // ---- Tracing ----
359
+ traceId?: string // Observability trace
360
+ }
361
+ ```
362
+
363
+ ### Intent Type
364
+
365
+ ```typescript
366
+ interface Intent {
367
+ type: 'task' | 'customer' | 'page' | 'greeting' | 'clarification'
368
+ action: 'list' | 'create' | 'update' | 'delete' | 'search' | 'get' | 'unknown'
369
+ parameters: Record<string, unknown>
370
+ originalText: string
371
+ confidence?: number
372
+ }
373
+ ```
374
+
375
+ ### Handler Results
376
+
377
+ ```typescript
378
+ interface TaskHandlerResult {
379
+ success: boolean
380
+ operation: 'list' | 'create' | 'update' | 'delete' | 'search' | 'get'
381
+ data: TaskData[] | TaskData | null
382
+ count?: number
383
+ message: string
384
+ error?: string
385
+ }
386
+ ```
387
+
388
+ ---
389
+
390
+ ## Routing Logic
391
+
392
+ ### From Router to Handlers
393
+
394
+ The `routeByIntents` function determines execution path:
395
+
396
+ ```typescript
397
+ function routeByIntents(state: OrchestratorState): RouterRoute {
398
+ const intentTypes = state.intents.map(i => i.type)
399
+
400
+ // Handle special cases
401
+ if (state.error) return 'error'
402
+ if (state.needsClarification) return 'clarification'
403
+ if (intentTypes.length === 1 && intentTypes[0] === 'greeting') return 'greeting'
404
+
405
+ // Determine handler combination
406
+ const hasTask = intentTypes.includes('task')
407
+ const hasCustomer = intentTypes.includes('customer')
408
+ const hasPage = intentTypes.includes('page')
409
+
410
+ if (hasTask && hasCustomer && hasPage) return 'all_handlers'
411
+ if (hasTask && hasCustomer) return 'task_and_customer'
412
+ if (hasTask && hasPage) return 'task_and_page'
413
+ if (hasCustomer && hasPage) return 'customer_and_page'
414
+ if (hasTask) return 'task_only'
415
+ if (hasCustomer) return 'customer_only'
416
+ if (hasPage) return 'page_only'
417
+
418
+ return 'clarification'
419
+ }
420
+ ```
421
+
422
+ ### Handler Sequencing
423
+
424
+ For multi-intent requests, handlers execute sequentially:
425
+
426
+ ```
427
+ task_and_customer: Task Handler → Customer Handler → Combiner
428
+ task_and_page: Task Handler → Page Handler → Combiner
429
+ all_handlers: Task Handler → Customer Handler → Page Handler → Combiner
430
+ ```
431
+
432
+ Each handler's output is **merged** into `handlerResults`, preserving all results.
433
+
434
+ ### Conditional Transitions
435
+
436
+ ```typescript
437
+ // After task handler
438
+ function routeAfterTask(state): string {
439
+ if (needsCustomer && !completedCustomer) return 'customer_handler'
440
+ if (needsPage && !completedPage) return 'page_handler'
441
+ return 'combiner'
442
+ }
443
+ ```
444
+
445
+ ---
446
+
447
+ ## Multi-Model Compatibility
448
+
449
+ ### Structured Output Methods
450
+
451
+ Different LLM providers support different structured output methods:
452
+
453
+ | Provider | Method | Notes |
454
+ |----------|--------|-------|
455
+ | OpenAI API | `functionCalling` | Most reliable |
456
+ | Anthropic | `functionCalling` | Tool use |
457
+ | Ollama | `functionCalling` | Most models |
458
+ | LM Studio | `jsonSchema` | OpenAI-compatible servers |
459
+
460
+ The `getStructuredOutputMethod()` helper auto-detects the best method:
461
+
462
+ ```typescript
463
+ import { getStructuredOutputMethod } from '../../providers'
464
+
465
+ const method = getStructuredOutputMethod({ provider: 'openai' })
466
+ // Returns: 'functionCalling' for real OpenAI, 'jsonSchema' for LM Studio
467
+
468
+ const structuredModel = model.withStructuredOutput(schema, { method })
469
+ ```
470
+
471
+ ### Retry Logic with Zod Validation
472
+
473
+ Local models (LM Studio, Ollama) may produce malformed JSON. The router includes retry logic:
474
+
475
+ ```typescript
476
+ async function invokeRouterWithRetry(model, messages, method) {
477
+ for (let attempt = 1; attempt <= 3; attempt++) {
478
+ // Try 1: Structured output
479
+ const result = await tryStructuredOutput(model, messages, method)
480
+ if (result) return result
481
+
482
+ // Try 2: Manual JSON parsing (fallback)
483
+ const manual = await tryManualJsonParsing(model, messages)
484
+ if (manual) return manual
485
+
486
+ // Exponential backoff before retry
487
+ await sleep(500 * Math.pow(2, attempt - 1))
488
+ }
489
+ throw new Error('Router failed after retries')
490
+ }
491
+
492
+ function tryManualJsonParsing(model, messages) {
493
+ const result = await model.invoke(messages)
494
+ const content = result.content as string
495
+
496
+ // Extract JSON from markdown code blocks or raw text
497
+ const json = extractJsonFromResponse(content)
498
+ const parsed = JSON.parse(json)
499
+
500
+ // Validate with Zod
501
+ return RouterOutputSchema.safeParse(parsed)
502
+ }
503
+ ```
504
+
505
+ ### Provider Configuration
506
+
507
+ Configure providers in theme's `langchain.config.ts`:
508
+
509
+ ```typescript
510
+ 'orchestrator': {
511
+ provider: 'anthropic', // Claude for router
512
+ model: 'claude-3-haiku-20240307',
513
+ temperature: 0.1, // Low for consistency
514
+ },
515
+ 'task-assistant': {
516
+ provider: 'openai', // GPT-4o-mini for handlers
517
+ model: 'gpt-4o-mini',
518
+ temperature: 0.3,
519
+ }
520
+ ```
521
+
522
+ ---
523
+
524
+ ## Configuration
525
+
526
+ ### Environment Variables
527
+
528
+ ```env
529
+ # Enable graph orchestrator (recommended)
530
+ LANGCHAIN_USE_GRAPH_ORCHESTRATOR=true
531
+
532
+ # Provider settings
533
+ LANGCHAIN_DEFAULT_PROVIDER=openai
534
+
535
+ # Debug mode
536
+ LANGCHAIN_PLUGIN_DEBUG=true
537
+
538
+ # Provider-specific
539
+ OPENAI_API_KEY=sk-...
540
+ ANTHROPIC_API_KEY=sk-ant-...
541
+ ```
542
+
543
+ ### Graph Configuration
544
+
545
+ ```typescript
546
+ interface GraphConfig {
547
+ maxHistoryMessages: number // Default: 5
548
+ routerTemperature: number // Default: 0.1
549
+ combinerTemperature: number // Default: 0.3
550
+ parallelExecution: boolean // Default: true (future)
551
+ handlerTimeout: number // Default: 30000ms
552
+ }
553
+ ```
554
+
555
+ ### Usage
556
+
557
+ ```typescript
558
+ import { invokeOrchestrator } from '@/contents/plugins/langchain/lib/graph'
559
+
560
+ const result = await invokeOrchestrator(
561
+ message,
562
+ sessionId,
563
+ { userId, teamId },
564
+ conversationHistory,
565
+ {
566
+ config: {
567
+ maxHistoryMessages: 10,
568
+ routerTemperature: 0.05,
569
+ },
570
+ traceId: 'trace-123',
571
+ }
572
+ )
573
+ ```
574
+
575
+ ---
576
+
577
+ ## Performance Comparison
578
+
579
+ ### Benchmarks
580
+
581
+ | Metric | Graph Orchestrator | ReAct Loops | Improvement |
582
+ |--------|-------------------|-------------|-------------|
583
+ | **LLM Calls (single intent)** | 1 | 20-30 | 20-30x |
584
+ | **LLM Calls (multi intent)** | 2 | 50+ | 25-50x |
585
+ | **Response Time (single)** | 2-3s | 10-15s | 5x |
586
+ | **Response Time (multi)** | 3-5s | 60-120s | 20-30x |
587
+ | **Token Cost** | ~500 | ~15,000 | 30x |
588
+ | **Recursion Errors** | Never | Frequent | - |
589
+ | **Timeout Errors** | Never | Common | - |
590
+
591
+ ### Real-World Example
592
+
593
+ **Query**: "Show my tasks and find the account number for StartupXYZ"
594
+
595
+ | Metric | Graph | ReAct |
596
+ |--------|-------|-------|
597
+ | Total LLM calls | 2 | 47 |
598
+ | Router calls | 1 | - |
599
+ | Orchestrator iterations | - | 15 |
600
+ | Task agent iterations | - | 12 |
601
+ | Customer agent iterations | - | 20 |
602
+ | Response time | 4.2s | 127s (timeout) |
603
+ | Tokens used | 892 | 23,450 |
604
+ | Estimated cost | $0.002 | $0.047 |
605
+
606
+ ---
607
+
608
+ ## Examples
609
+
610
+ ### Single Intent Flow
611
+
612
+ ```typescript
613
+ // User: "List my tasks"
614
+
615
+ // 1. Router (1 LLM call)
616
+ {
617
+ intents: [{ type: "task", action: "list", parameters: {} }],
618
+ needsClarification: false
619
+ }
620
+
621
+ // 2. Route: task_only → task_handler
622
+
623
+ // 3. Task Handler (0 LLM calls)
624
+ {
625
+ handlerResults: {
626
+ task: {
627
+ success: true,
628
+ operation: "list",
629
+ data: [{ id: "1", title: "Task A" }, ...],
630
+ count: 5
631
+ }
632
+ }
633
+ }
634
+
635
+ // 4. Combiner (0 LLM calls - uses template)
636
+ {
637
+ finalResponse: "Found 5 task(s):\n• Task A\n• Task B..."
638
+ }
639
+
640
+ // TOTAL: 1 LLM call
641
+ ```
642
+
643
+ ### Multi-Intent Flow
644
+
645
+ ```typescript
646
+ // User: "Show tasks and find StartupXYZ phone number"
647
+
648
+ // 1. Router (1 LLM call)
649
+ {
650
+ intents: [
651
+ { type: "task", action: "list", parameters: {} },
652
+ { type: "customer", action: "search", parameters: { query: "StartupXYZ", fields: ["phone"] } }
653
+ ]
654
+ }
655
+
656
+ // 2. Route: task_and_customer → task_handler → customer_handler → combiner
657
+
658
+ // 3. Task Handler (0 LLM)
659
+ // 4. Customer Handler (0 LLM)
660
+ {
661
+ handlerResults: {
662
+ task: { success: true, data: [...], count: 3 },
663
+ customer: { success: true, data: [{ name: "StartupXYZ", phone: "+1-555-1234" }] }
664
+ }
665
+ }
666
+
667
+ // 5. Combiner (1 LLM call - multi-result)
668
+ {
669
+ finalResponse: "Found 3 tasks. StartupXYZ phone number is +1-555-1234."
670
+ }
671
+
672
+ // TOTAL: 2 LLM calls
673
+ ```
674
+
675
+ ### Error Handling
676
+
677
+ ```typescript
678
+ // User: "Update task 999" (non-existent)
679
+
680
+ // Task Handler returns error:
681
+ {
682
+ handlerResults: {
683
+ task: {
684
+ success: false,
685
+ operation: "update",
686
+ data: null,
687
+ error: "Task not found",
688
+ message: "Could not find task with ID 999"
689
+ }
690
+ }
691
+ }
692
+
693
+ // Combiner generates friendly error:
694
+ {
695
+ finalResponse: "I couldn't find that task. Would you like to see your task list?"
696
+ }
697
+ ```
698
+
699
+ ---
700
+
701
+ ## Debugging
702
+
703
+ ### Enable Debug Mode
704
+
705
+ ```env
706
+ LANGCHAIN_PLUGIN_DEBUG=true
707
+ ```
708
+
709
+ ### Debug Output
710
+
711
+ ```
712
+ [Router] Classifying intent for: Show my tasks
713
+ [Router] Classified intents: [{"type":"task","action":"list"}]
714
+ [Task Handler] Processing intent: list
715
+ [Task Handler] Found 5 tasks
716
+ [Combiner] Using template-based response
717
+ ```
718
+
719
+ ### Observability
720
+
721
+ Use the [Observability Dashboard](../04-advanced/01-observability.md) to trace execution:
722
+
723
+ - View trace timeline with each node
724
+ - See provider/model used per node
725
+ - Inspect input/output at each step
726
+ - Track token usage and costs
727
+
728
+ ---
729
+
730
+ ## Migration from ReAct
731
+
732
+ ### Step 1: Enable Graph Mode
733
+
734
+ ```env
735
+ LANGCHAIN_USE_GRAPH_ORCHESTRATOR=true
736
+ ```
737
+
738
+ ### Step 2: Configure Providers
739
+
740
+ Ensure providers are configured in `langchain.config.ts`:
741
+
742
+ ```typescript
743
+ 'orchestrator': {
744
+ provider: 'anthropic', // Claude for reliable classification
745
+ model: 'claude-3-haiku-20240307',
746
+ temperature: 0.1,
747
+ }
748
+ ```
749
+
750
+ ### Step 3: Test
751
+
752
+ ```bash
753
+ # Run your test suite
754
+ pnpm test
755
+
756
+ # Monitor observability dashboard
757
+ # /sector7/ai-observability
758
+ ```
759
+
760
+ ### Fallback
761
+
762
+ The system supports automatic fallback:
763
+
764
+ ```typescript
765
+ // In orchestrator.ts
766
+ if (isGraphOrchestratorEnabled()) {
767
+ return processWithGraphOrchestrator(message, context)
768
+ }
769
+ return processWithOrchestrator(message, context) // Legacy ReAct
770
+ ```
771
+
772
+ ---
773
+
774
+ ## Best Practices
775
+
776
+ ### 1. Keep Router Focused
777
+
778
+ The router should only classify intent. Keep the system prompt simple and focused on intent extraction.
779
+
780
+ ### 2. Use Low Temperature
781
+
782
+ ```typescript
783
+ routerTemperature: 0.1 // Consistent classification
784
+ combinerTemperature: 0.3 // Slightly creative responses
785
+ ```
786
+
787
+ ### 3. Handle All Intent Types
788
+
789
+ Ensure your handlers cover all possible actions for each entity type.
790
+
791
+ ### 4. Monitor Performance
792
+
793
+ Use observability to track:
794
+ - Intent classification accuracy
795
+ - Handler execution times
796
+ - Combiner usage (template vs LLM)
797
+
798
+ ### 5. Test Multi-Intent
799
+
800
+ Always test with multi-intent queries to ensure proper sequencing.
801
+
802
+ ---
803
+
804
+ ## Related Documentation
805
+
806
+ - [Observability & Tracing](../04-advanced/01-observability.md) - Debug and monitor execution
807
+ - [Token Tracking](../04-advanced/02-token-tracking.md) - Cost management
808
+ - [Configuration](../01-getting-started/03-configuration.md) - Provider setup
809
+ - [Legacy Orchestration](./02-legacy-react.md) - ReAct-based approach (deprecated)