@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,645 @@
1
+ # Observability & Tracing
2
+
3
+ This guide covers the observability system for LangChain agents, including tracing, metrics, and the debugging dashboard.
4
+
5
+ ## Overview
6
+
7
+ The observability system provides **end-to-end visibility** into AI agent execution:
8
+
9
+ ```
10
+ User Request → Trace
11
+ ├── Router Span (LLM call)
12
+ ├── Task Handler Span (tool call)
13
+ ├── Customer Handler Span (tool call)
14
+ └── Combiner Span (LLM call)
15
+ ```
16
+
17
+ **Key Features**:
18
+ - **Traces**: Track complete agent invocations
19
+ - **Spans**: Track individual operations within traces
20
+ - **Metrics**: Aggregate performance data
21
+ - **Dashboard**: Visual debugging interface
22
+ - **PII Protection**: Mask sensitive data automatically
23
+
24
+ ---
25
+
26
+ ## Architecture
27
+
28
+ ### Tracing Flow
29
+
30
+ ```
31
+ ┌─────────────────────────────────────────────────────────────┐
32
+ │ AGENT INVOCATION │
33
+ │ │
34
+ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
35
+ │ │ LLM │ │ Tool │ │ LLM │ │
36
+ │ │ Call │───►│ Call │───►│ Call │ │
37
+ │ └──────────┘ └──────────┘ └──────────┘ │
38
+ │ │ │ │ │
39
+ │ ▼ ▼ ▼ │
40
+ │ ┌──────────────────────────────────────────────┐ │
41
+ │ │ TRACE RECORD │ │
42
+ │ │ ├─ Span: router (llm) │ │
43
+ │ │ ├─ Span: task_handler (tool) │ │
44
+ │ │ └─ Span: combiner (llm) │ │
45
+ │ └──────────────────────────────────────────────┘ │
46
+ │ │ │
47
+ │ ▼ │
48
+ │ ┌─────────────┐ │
49
+ │ │ DATABASE │ │
50
+ │ │ (RLS) │ │
51
+ │ └─────────────┘ │
52
+ └─────────────────────────────────────────────────────────────┘
53
+ ```
54
+
55
+ ### Database Schema
56
+
57
+ Two tables with full Row-Level Security:
58
+
59
+ **`langchain_traces`** - Main trace records
60
+
61
+ | Column | Type | Description |
62
+ |--------|------|-------------|
63
+ | `traceId` | TEXT | Unique identifier |
64
+ | `userId` | TEXT | User who triggered |
65
+ | `teamId` | TEXT | Team context |
66
+ | `sessionId` | TEXT | Session identifier |
67
+ | `agentName` | TEXT | Agent name |
68
+ | `input` | TEXT | User input (truncated) |
69
+ | `output` | TEXT | Agent output (truncated) |
70
+ | `status` | TEXT | running/success/error |
71
+ | `error` | TEXT | Error message |
72
+ | `durationMs` | INTEGER | Execution time |
73
+ | `inputTokens` | INTEGER | Input token count |
74
+ | `outputTokens` | INTEGER | Output token count |
75
+ | `totalCost` | DECIMAL | Cost in USD |
76
+ | `llmCalls` | INTEGER | Number of LLM calls |
77
+ | `toolCalls` | INTEGER | Number of tool calls |
78
+ | `metadata` | JSONB | Additional data |
79
+ | `tags` | TEXT[] | Filtering tags |
80
+
81
+ **`langchain_spans`** - Individual operations
82
+
83
+ | Column | Type | Description |
84
+ |--------|------|-------------|
85
+ | `spanId` | TEXT | Unique identifier |
86
+ | `traceId` | TEXT | Parent trace |
87
+ | `parentSpanId` | TEXT | Parent span (for nesting) |
88
+ | `name` | TEXT | Span name |
89
+ | `type` | TEXT | llm/tool/chain |
90
+ | `provider` | TEXT | LLM provider |
91
+ | `model` | TEXT | Model name |
92
+ | `toolName` | TEXT | Tool name (if tool) |
93
+ | `input` | JSONB | Span input |
94
+ | `output` | JSONB | Span output |
95
+ | `status` | TEXT | running/success/error |
96
+ | `durationMs` | INTEGER | Span duration |
97
+ | `depth` | INTEGER | Nesting depth |
98
+
99
+ ---
100
+
101
+ ## Configuration
102
+
103
+ Configure in `langchain.config.ts`:
104
+
105
+ ```typescript
106
+ export const langchainConfig = {
107
+ observability: {
108
+ enabled: true,
109
+
110
+ retention: {
111
+ traces: 30, // Days to keep traces
112
+ },
113
+
114
+ sampling: {
115
+ rate: 1.0, // 1.0 = 100% of requests
116
+ alwaysTraceErrors: true, // Always trace errors
117
+ },
118
+
119
+ pii: {
120
+ maskInputs: false, // Mask PII in inputs
121
+ maskOutputs: true, // Mask PII in outputs
122
+ truncateAt: 10000, // Max content length
123
+ },
124
+ },
125
+ }
126
+ ```
127
+
128
+ ### Configuration Options
129
+
130
+ | Option | Type | Default | Description |
131
+ |--------|------|---------|-------------|
132
+ | `enabled` | boolean | `true` | Enable/disable tracing |
133
+ | `retention.traces` | number | `30` | Days to keep trace data |
134
+ | `sampling.rate` | number | `1.0` | Sample rate (0.0-1.0) |
135
+ | `sampling.alwaysTraceErrors` | boolean | `true` | Always trace errors |
136
+ | `pii.maskInputs` | boolean | `false` | Mask PII in inputs |
137
+ | `pii.maskOutputs` | boolean | `true` | Mask PII in outputs |
138
+ | `pii.truncateAt` | number | `10000` | Max content length |
139
+
140
+ ### Sampling
141
+
142
+ Control how many requests are traced:
143
+
144
+ ```typescript
145
+ // Development: trace everything
146
+ sampling: { rate: 1.0, alwaysTraceErrors: true }
147
+
148
+ // Production: trace 10% + all errors
149
+ sampling: { rate: 0.1, alwaysTraceErrors: true }
150
+
151
+ // High traffic: trace 1% + errors
152
+ sampling: { rate: 0.01, alwaysTraceErrors: true }
153
+ ```
154
+
155
+ ---
156
+
157
+ ## Tracer Service
158
+
159
+ ### Basic Usage
160
+
161
+ ```typescript
162
+ import { tracer } from '@/contents/plugins/langchain/lib/tracer'
163
+
164
+ // Start a trace
165
+ const traceContext = await tracer.startTrace(
166
+ { userId, teamId },
167
+ 'orchestrator',
168
+ userMessage,
169
+ { sessionId, metadata: { source: 'chat' } }
170
+ )
171
+
172
+ try {
173
+ // Your agent logic here
174
+ const result = await processMessage(userMessage)
175
+
176
+ // End trace with success
177
+ await tracer.endTrace(
178
+ { userId, teamId },
179
+ traceContext.traceId,
180
+ {
181
+ output: result.content,
182
+ tokens: { input: 100, output: 50, total: 150 },
183
+ cost: 0.002,
184
+ llmCalls: 2,
185
+ toolCalls: 1,
186
+ }
187
+ )
188
+ } catch (error) {
189
+ // End trace with error
190
+ await tracer.endTrace(
191
+ { userId, teamId },
192
+ traceContext.traceId,
193
+ { error }
194
+ )
195
+ }
196
+ ```
197
+
198
+ ### Spans
199
+
200
+ Track individual operations within a trace:
201
+
202
+ ```typescript
203
+ // Start a span
204
+ const spanContext = await tracer.startSpan(
205
+ { userId, teamId },
206
+ traceId,
207
+ {
208
+ name: 'router',
209
+ type: 'llm',
210
+ provider: 'anthropic',
211
+ model: 'claude-3-haiku',
212
+ input: { message: userInput },
213
+ }
214
+ )
215
+
216
+ try {
217
+ const result = await routerNode(state)
218
+
219
+ // End span with success
220
+ await tracer.endSpan(
221
+ { userId, teamId },
222
+ traceId,
223
+ spanContext.spanId,
224
+ {
225
+ output: { intents: result.intents },
226
+ tokens: { input: 50, output: 20 },
227
+ }
228
+ )
229
+ } catch (error) {
230
+ await tracer.endSpan(
231
+ { userId, teamId },
232
+ traceId,
233
+ spanContext.spanId,
234
+ { error }
235
+ )
236
+ }
237
+ ```
238
+
239
+ ### Span Types
240
+
241
+ | Type | Description | Example |
242
+ |------|-------------|---------|
243
+ | `llm` | LLM call | Router, Combiner |
244
+ | `tool` | Tool invocation | TaskHandler, CustomerHandler |
245
+ | `chain` | Chain/workflow | Graph execution |
246
+ | `retriever` | RAG retrieval | Vector search |
247
+
248
+ ---
249
+
250
+ ## API Endpoints
251
+
252
+ All endpoints require **superadmin** authentication.
253
+
254
+ ### List Traces
255
+
256
+ ```
257
+ GET /api/v1/theme/default/observability/traces
258
+ ```
259
+
260
+ **Query Parameters**:
261
+ - `limit` - Results per page (default: 50)
262
+ - `offset` - Pagination offset
263
+ - `status` - Filter by status (success/error)
264
+ - `agentName` - Filter by agent
265
+ - `teamId` - Filter by team
266
+ - `from` - Start date (ISO)
267
+ - `to` - End date (ISO)
268
+
269
+ **Response**:
270
+ ```json
271
+ {
272
+ "success": true,
273
+ "data": {
274
+ "traces": [
275
+ {
276
+ "traceId": "abc-123",
277
+ "agentName": "orchestrator",
278
+ "status": "success",
279
+ "durationMs": 2340,
280
+ "inputTokens": 150,
281
+ "outputTokens": 80,
282
+ "totalCost": 0.002,
283
+ "llmCalls": 2,
284
+ "toolCalls": 1,
285
+ "startedAt": "2024-12-23T10:00:00Z"
286
+ }
287
+ ],
288
+ "total": 156,
289
+ "hasMore": true
290
+ }
291
+ }
292
+ ```
293
+
294
+ ### Get Trace Detail
295
+
296
+ ```
297
+ GET /api/v1/theme/default/observability/traces/[traceId]
298
+ ```
299
+
300
+ **Response**:
301
+ ```json
302
+ {
303
+ "success": true,
304
+ "data": {
305
+ "trace": {
306
+ "traceId": "abc-123",
307
+ "input": "Show my tasks",
308
+ "output": "Found 3 tasks...",
309
+ "status": "success",
310
+ "durationMs": 2340,
311
+ "spans": [
312
+ {
313
+ "spanId": "span-1",
314
+ "name": "router",
315
+ "type": "llm",
316
+ "provider": "anthropic",
317
+ "model": "claude-3-haiku",
318
+ "durationMs": 1200,
319
+ "status": "success"
320
+ },
321
+ {
322
+ "spanId": "span-2",
323
+ "name": "task_handler",
324
+ "type": "tool",
325
+ "durationMs": 340,
326
+ "status": "success"
327
+ }
328
+ ]
329
+ }
330
+ }
331
+ }
332
+ ```
333
+
334
+ ### Get Metrics
335
+
336
+ ```
337
+ GET /api/v1/theme/default/observability/metrics
338
+ ```
339
+
340
+ **Query Parameters**:
341
+ - `period` - Time period: `1h`, `24h`, `7d`, `30d`
342
+
343
+ **Response**:
344
+ ```json
345
+ {
346
+ "success": true,
347
+ "data": {
348
+ "summary": {
349
+ "totalTraces": 1500,
350
+ "successRate": 98.5,
351
+ "avgLatencyMs": 2340,
352
+ "totalCost": 15.23,
353
+ "totalLlmCalls": 2800,
354
+ "totalToolCalls": 1200
355
+ },
356
+ "byAgent": [
357
+ {
358
+ "agentName": "orchestrator",
359
+ "count": 1500,
360
+ "successRate": 98.5,
361
+ "avgLatencyMs": 2340
362
+ }
363
+ ],
364
+ "byStatus": {
365
+ "success": 1478,
366
+ "error": 22
367
+ }
368
+ }
369
+ }
370
+ ```
371
+
372
+ ---
373
+
374
+ ## Dashboard
375
+
376
+ The observability dashboard is available at:
377
+
378
+ ```
379
+ /sector7/ai-observability
380
+ ```
381
+
382
+ > **Note**: This is a superadmin-only page in the Sector7 protected zone.
383
+
384
+ ### Features
385
+
386
+ 1. **Traces Table**
387
+ - Paginated list of all traces
388
+ - Filter by status, agent, date range
389
+ - Click to view details
390
+
391
+ 2. **Trace Detail**
392
+ - Full trace timeline
393
+ - All spans with durations
394
+ - Input/output inspection
395
+ - Error details
396
+
397
+ 3. **Metrics Overview**
398
+ - Total traces
399
+ - Success rate
400
+ - Average latency
401
+ - Cost tracking
402
+
403
+ ### Components
404
+
405
+ | Component | Purpose |
406
+ |-----------|---------|
407
+ | `ObservabilityDashboard` | Main dashboard container |
408
+ | `TracesTable` | Paginated trace list |
409
+ | `TraceDetail` | Single trace view |
410
+ | `SpansList` | Span timeline |
411
+ | `FiltersPanel` | Filter controls |
412
+ | `TraceStatusBadge` | Status indicator |
413
+
414
+ ---
415
+
416
+ ## React Hooks
417
+
418
+ ### useTraces
419
+
420
+ Fetch paginated trace list:
421
+
422
+ ```typescript
423
+ import { useTraces } from '@/contents/plugins/langchain/hooks/observability'
424
+
425
+ function TracesList() {
426
+ const { data, isLoading, error } = useTraces({
427
+ status: 'error',
428
+ agentName: 'orchestrator',
429
+ limit: 20,
430
+ })
431
+
432
+ if (isLoading) return <Loading />
433
+ if (error) return <Error />
434
+
435
+ return (
436
+ <table>
437
+ {data.traces.map(trace => (
438
+ <TraceRow key={trace.traceId} trace={trace} />
439
+ ))}
440
+ </table>
441
+ )
442
+ }
443
+ ```
444
+
445
+ ### useTraceDetail
446
+
447
+ Fetch single trace with spans:
448
+
449
+ ```typescript
450
+ import { useTraceDetail } from '@/contents/plugins/langchain/hooks/observability'
451
+
452
+ function TraceView({ traceId }) {
453
+ const { data, isLoading } = useTraceDetail(traceId)
454
+
455
+ if (isLoading) return <Loading />
456
+
457
+ return (
458
+ <div>
459
+ <h2>{data.trace.agentName}</h2>
460
+ <pre>{data.trace.input}</pre>
461
+ <SpanTimeline spans={data.trace.spans} />
462
+ </div>
463
+ )
464
+ }
465
+ ```
466
+
467
+ ### useMetrics
468
+
469
+ Fetch aggregate metrics:
470
+
471
+ ```typescript
472
+ import { useMetrics } from '@/contents/plugins/langchain/hooks/observability'
473
+
474
+ function MetricsDashboard() {
475
+ const { data } = useMetrics({ period: '24h' })
476
+
477
+ return (
478
+ <div>
479
+ <Stat label="Total Traces" value={data.summary.totalTraces} />
480
+ <Stat label="Success Rate" value={`${data.summary.successRate}%`} />
481
+ <Stat label="Avg Latency" value={`${data.summary.avgLatencyMs}ms`} />
482
+ </div>
483
+ )
484
+ }
485
+ ```
486
+
487
+ ---
488
+
489
+ ## PII Protection
490
+
491
+ ### Automatic Masking
492
+
493
+ When enabled, the tracer masks common PII patterns:
494
+
495
+ | Pattern | Example | Masked |
496
+ |---------|---------|--------|
497
+ | Email | john@example.com | [EMAIL] |
498
+ | Phone | +1 (555) 123-4567 | [PHONE] |
499
+ | Credit Card | 1234-5678-9012-3456 | [CARD] |
500
+ | SSN | 123-45-6789 | [SSN] |
501
+
502
+ ### Configuration
503
+
504
+ ```typescript
505
+ pii: {
506
+ maskInputs: false, // Don't mask inputs (for debugging)
507
+ maskOutputs: true, // Mask PII in outputs
508
+ truncateAt: 10000, // Truncate long content
509
+ }
510
+ ```
511
+
512
+ ### Content Truncation
513
+
514
+ Long content is automatically truncated:
515
+
516
+ ```
517
+ Original: "Very long message..." (15000 chars)
518
+ Stored: "Very long message..." (10000 chars) + "[truncated]"
519
+ ```
520
+
521
+ ---
522
+
523
+ ## Integration with Graph Orchestrator
524
+
525
+ The graph orchestrator automatically tracks traces and spans:
526
+
527
+ ```typescript
528
+ // In orchestrator.ts
529
+ const traceContext = await tracer.startTrace(
530
+ { userId: context.userId, teamId: context.teamId },
531
+ 'graph-orchestrator',
532
+ message,
533
+ { sessionId }
534
+ )
535
+
536
+ const result = await invokeOrchestrator(
537
+ message,
538
+ sessionId,
539
+ context,
540
+ history,
541
+ { traceId: traceContext?.traceId }
542
+ )
543
+
544
+ // Router node creates spans automatically
545
+ // Handler nodes create spans automatically
546
+ // Combiner node creates spans automatically
547
+
548
+ await tracer.endTrace(
549
+ { userId, teamId },
550
+ traceContext.traceId,
551
+ {
552
+ output: result.finalResponse,
553
+ llmCalls: 2,
554
+ toolCalls: result.completedHandlers.length,
555
+ }
556
+ )
557
+ ```
558
+
559
+ ---
560
+
561
+ ## Best Practices
562
+
563
+ ### 1. Use Meaningful Span Names
564
+
565
+ ```typescript
566
+ // Good
567
+ { name: 'router', type: 'llm' }
568
+ { name: 'task_handler', type: 'tool' }
569
+
570
+ // Bad
571
+ { name: 'step1', type: 'llm' }
572
+ { name: 'process', type: 'tool' }
573
+ ```
574
+
575
+ ### 2. Include Provider/Model Info
576
+
577
+ ```typescript
578
+ await tracer.startSpan(context, traceId, {
579
+ name: 'router',
580
+ type: 'llm',
581
+ provider: 'anthropic', // Include this
582
+ model: 'claude-3-haiku', // Include this
583
+ })
584
+ ```
585
+
586
+ ### 3. Always End Traces
587
+
588
+ ```typescript
589
+ try {
590
+ // Logic
591
+ await tracer.endTrace(ctx, traceId, { output })
592
+ } catch (error) {
593
+ await tracer.endTrace(ctx, traceId, { error }) // Always end
594
+ throw error
595
+ }
596
+ ```
597
+
598
+ ### 4. Use Tags for Filtering
599
+
600
+ ```typescript
601
+ await tracer.startTrace(context, agent, input, {
602
+ tags: ['production', 'chat', 'high-priority'],
603
+ })
604
+ ```
605
+
606
+ ### 5. Sample in Production
607
+
608
+ ```typescript
609
+ // Production config
610
+ sampling: {
611
+ rate: 0.1, // Only trace 10%
612
+ alwaysTraceErrors: true, // But always trace errors
613
+ }
614
+ ```
615
+
616
+ ---
617
+
618
+ ## Troubleshooting
619
+
620
+ ### Traces Not Appearing
621
+
622
+ 1. Check `enabled: true` in config
623
+ 2. Verify sampling rate
624
+ 3. Check superadmin permissions
625
+ 4. Look for console errors
626
+
627
+ ### Missing Spans
628
+
629
+ 1. Ensure `startSpan` is called before `endSpan`
630
+ 2. Check traceId is passed correctly
631
+ 3. Verify RLS policies allow insert
632
+
633
+ ### High Storage Usage
634
+
635
+ 1. Reduce `retention.traces`
636
+ 2. Lower `pii.truncateAt`
637
+ 3. Reduce `sampling.rate`
638
+
639
+ ---
640
+
641
+ ## Related Documentation
642
+
643
+ - [Graph Orchestrator](../03-orchestration/01-graph-orchestrator.md) - How tracing integrates with the graph
644
+ - [Token Tracking](./02-token-tracking.md) - Cost and usage tracking
645
+ - [Configuration](../01-getting-started/03-configuration.md) - Full configuration reference