@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.
- package/.env.example +41 -0
- package/api/observability/metrics/route.ts +110 -0
- package/api/observability/traces/[traceId]/route.ts +398 -0
- package/api/observability/traces/route.ts +205 -0
- package/api/sessions/route.ts +332 -0
- package/components/observability/CollapsibleJson.tsx +71 -0
- package/components/observability/CompactTimeline.tsx +75 -0
- package/components/observability/ConversationFlow.tsx +271 -0
- package/components/observability/DisabledMessage.tsx +21 -0
- package/components/observability/FiltersPanel.tsx +82 -0
- package/components/observability/ObservabilityDashboard.tsx +230 -0
- package/components/observability/SpansList.tsx +210 -0
- package/components/observability/TraceDetail.tsx +335 -0
- package/components/observability/TraceStatusBadge.tsx +39 -0
- package/components/observability/TracesTable.tsx +97 -0
- package/components/observability/index.ts +7 -0
- package/docs/01-getting-started/01-overview.md +196 -0
- package/docs/01-getting-started/02-installation.md +368 -0
- package/docs/01-getting-started/03-configuration.md +794 -0
- package/docs/02-core-concepts/01-architecture.md +566 -0
- package/docs/02-core-concepts/02-agents.md +597 -0
- package/docs/02-core-concepts/03-tools.md +689 -0
- package/docs/03-orchestration/01-graph-orchestrator.md +809 -0
- package/docs/03-orchestration/02-legacy-react.md +650 -0
- package/docs/04-advanced/01-observability.md +645 -0
- package/docs/04-advanced/02-token-tracking.md +469 -0
- package/docs/04-advanced/03-streaming.md +476 -0
- package/docs/04-advanced/04-guardrails.md +597 -0
- package/docs/05-reference/01-api-reference.md +1403 -0
- package/docs/05-reference/02-customization.md +646 -0
- package/docs/05-reference/03-examples.md +881 -0
- package/docs/index.md +85 -0
- package/hooks/observability/useMetrics.ts +31 -0
- package/hooks/observability/useTraceDetail.ts +48 -0
- package/hooks/observability/useTraces.ts +59 -0
- package/lib/agent-factory.ts +354 -0
- package/lib/agent-helpers.ts +201 -0
- package/lib/db-memory-store.ts +417 -0
- package/lib/graph/index.ts +58 -0
- package/lib/graph/nodes/combiner.ts +399 -0
- package/lib/graph/nodes/router.ts +440 -0
- package/lib/graph/orchestrator-graph.ts +386 -0
- package/lib/graph/prompts/combiner.md +131 -0
- package/lib/graph/prompts/router.md +193 -0
- package/lib/graph/types.ts +365 -0
- package/lib/guardrails.ts +230 -0
- package/lib/index.ts +44 -0
- package/lib/logger.ts +70 -0
- package/lib/memory-store.ts +168 -0
- package/lib/message-serializer.ts +110 -0
- package/lib/prompt-renderer.ts +94 -0
- package/lib/providers.ts +226 -0
- package/lib/streaming.ts +232 -0
- package/lib/token-tracker.ts +298 -0
- package/lib/tools-builder.ts +192 -0
- package/lib/tracer-callbacks.ts +342 -0
- package/lib/tracer.ts +350 -0
- package/migrations/001_langchain_memory.sql +83 -0
- package/migrations/002_token_usage.sql +127 -0
- package/migrations/003_observability.sql +257 -0
- package/package.json +28 -0
- package/plugin.config.ts +170 -0
- package/presets/lib/langchain.config.ts.preset +142 -0
- package/presets/templates/sector7/ai-observability/[traceId]/page.tsx +91 -0
- package/presets/templates/sector7/ai-observability/page.tsx +54 -0
- package/types/langchain.types.ts +274 -0
- package/types/observability.types.ts +270 -0
|
@@ -0,0 +1,566 @@
|
|
|
1
|
+
# Architecture
|
|
2
|
+
|
|
3
|
+
This section explains the technical architecture of the LangChain plugin, including core patterns, data flow, and design decisions.
|
|
4
|
+
|
|
5
|
+
## System Architecture
|
|
6
|
+
|
|
7
|
+
### Layer Model
|
|
8
|
+
|
|
9
|
+
The plugin follows a layered architecture with clear responsibilities:
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
┌─────────────────────────────────────────────────────────────────────┐
|
|
13
|
+
│ API LAYER │
|
|
14
|
+
│ Theme API endpoints (e.g., /api/v1/theme/ai/chat) │
|
|
15
|
+
├─────────────────────────────────────────────────────────────────────┤
|
|
16
|
+
│ THEME LAYER │
|
|
17
|
+
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
|
18
|
+
│ │ Config │ │ Agents │ │ Tools │ │
|
|
19
|
+
│ │ Definition │ │ (Prompts) │ │ (CRUD ops) │ │
|
|
20
|
+
│ └──────────────┘ └──────────────┘ └──────────────┘ │
|
|
21
|
+
├─────────────────────────────────────────────────────────────────────┤
|
|
22
|
+
│ PLUGIN LAYER │
|
|
23
|
+
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
|
24
|
+
│ │ Agent │ │ Memory │ │ Provider │ │
|
|
25
|
+
│ │ Factory │ │ Store │ │ Factory │ │
|
|
26
|
+
│ └──────────────┘ └──────────────┘ └──────────────┘ │
|
|
27
|
+
│ ┌──────────────┐ ┌──────────────┐ │
|
|
28
|
+
│ │ Tools │ │ Message │ │
|
|
29
|
+
│ │ Builder │ │ Serializer │ │
|
|
30
|
+
│ └──────────────┘ └──────────────┘ │
|
|
31
|
+
├─────────────────────────────────────────────────────────────────────┤
|
|
32
|
+
│ LANGCHAIN LAYER │
|
|
33
|
+
│ LangChain Core | LangGraph | Provider SDKs │
|
|
34
|
+
├─────────────────────────────────────────────────────────────────────┤
|
|
35
|
+
│ PERSISTENCE LAYER │
|
|
36
|
+
│ PostgreSQL (langchain_sessions table with RLS) │
|
|
37
|
+
└─────────────────────────────────────────────────────────────────────┘
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Core Components
|
|
41
|
+
|
|
42
|
+
### 1. Agent Factory
|
|
43
|
+
|
|
44
|
+
The `createAgent()` function is the entry point for creating AI agents:
|
|
45
|
+
|
|
46
|
+
```typescript
|
|
47
|
+
const agent = await createAgent({
|
|
48
|
+
sessionId: 'user-123-session-1',
|
|
49
|
+
systemPrompt: 'You are a helpful assistant...',
|
|
50
|
+
tools: myTools,
|
|
51
|
+
modelConfig: {
|
|
52
|
+
provider: 'openai',
|
|
53
|
+
model: 'gpt-4o',
|
|
54
|
+
temperature: 0.3
|
|
55
|
+
},
|
|
56
|
+
context: { userId, teamId }
|
|
57
|
+
})
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
**Responsibilities:**
|
|
61
|
+
- Creates the LLM instance from the provider factory
|
|
62
|
+
- Converts tool definitions to LangChain tools
|
|
63
|
+
- Sets up the ReAct agent graph with LangGraph
|
|
64
|
+
- Manages conversation memory (if context provided)
|
|
65
|
+
- Provides `chat()` and `getHistory()` methods
|
|
66
|
+
|
|
67
|
+
**Agent Lifecycle:**
|
|
68
|
+
|
|
69
|
+
```
|
|
70
|
+
createAgent()
|
|
71
|
+
│
|
|
72
|
+
├─→ getModel(config) # Get LLM instance
|
|
73
|
+
├─→ buildTools(toolDefs) # Convert to LangChain tools
|
|
74
|
+
├─→ loadHistory(context) # Load existing messages
|
|
75
|
+
├─→ createReactAgent(...) # Build LangGraph agent
|
|
76
|
+
│
|
|
77
|
+
└─→ Returns { chat, getHistory }
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### 2. Provider Factory
|
|
81
|
+
|
|
82
|
+
The provider system abstracts LLM access:
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
// Provider factory map
|
|
86
|
+
const providers = {
|
|
87
|
+
openai: createOpenAIModel,
|
|
88
|
+
anthropic: createAnthropicModel,
|
|
89
|
+
ollama: createOllamaModel
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Get model instance
|
|
93
|
+
const model = getModel({ provider: 'openai', model: 'gpt-4o' })
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
**Supported Providers:**
|
|
97
|
+
|
|
98
|
+
| Provider | SDK | Use Case |
|
|
99
|
+
|----------|-----|----------|
|
|
100
|
+
| `openai` | `@langchain/openai` | Production, high quality |
|
|
101
|
+
| `anthropic` | `@langchain/anthropic` | Production, alternative |
|
|
102
|
+
| `ollama` | `@langchain/ollama` | Development, local, free |
|
|
103
|
+
|
|
104
|
+
**OpenAI-Compatible Servers:**
|
|
105
|
+
|
|
106
|
+
The `openai` provider supports custom base URLs for compatible servers:
|
|
107
|
+
|
|
108
|
+
```env
|
|
109
|
+
# Use LM Studio locally
|
|
110
|
+
LANGCHAIN_OPENAI_BASE_URL=http://localhost:1234/v1
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### 3. Memory Store
|
|
114
|
+
|
|
115
|
+
Conversation persistence with multi-tenancy:
|
|
116
|
+
|
|
117
|
+
```typescript
|
|
118
|
+
interface DbMemoryStoreContext {
|
|
119
|
+
userId: string // User identifier
|
|
120
|
+
teamId: string // Team identifier
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const context = { userId: 'user-123', teamId: 'team-456' }
|
|
124
|
+
|
|
125
|
+
// Get messages for a session (returns LangChain BaseMessage[])
|
|
126
|
+
const messages = await memoryStore.getMessages(sessionId, context)
|
|
127
|
+
|
|
128
|
+
// Add messages to session
|
|
129
|
+
await memoryStore.addMessages(sessionId, newMessages, context)
|
|
130
|
+
|
|
131
|
+
// Session management
|
|
132
|
+
// Note: createSession auto-generates sessionId
|
|
133
|
+
const { sessionId, createdAt } = await memoryStore.createSession(context, 'My Chat')
|
|
134
|
+
await memoryStore.listSessions(context)
|
|
135
|
+
// Note: parameter order is (sessionId, value, context)
|
|
136
|
+
await memoryStore.renameSession(sessionId, 'New Name', context)
|
|
137
|
+
await memoryStore.togglePinSession(sessionId, true, context)
|
|
138
|
+
await memoryStore.clearSession(sessionId, context)
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
**Conversation Limits:**
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
const LIMITS = {
|
|
145
|
+
MAX_CONVERSATIONS: 50, // Per user per team
|
|
146
|
+
MAX_MESSAGES_PER_CONVERSATION: 50 // Sliding window
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### 4. Tools Builder
|
|
151
|
+
|
|
152
|
+
Converts simple tool definitions to LangChain-compatible tools:
|
|
153
|
+
|
|
154
|
+
```typescript
|
|
155
|
+
interface ToolDefinition<T> {
|
|
156
|
+
name: string
|
|
157
|
+
description: string
|
|
158
|
+
schema: z.ZodSchema<T>
|
|
159
|
+
func: (input: T) => Promise<string>
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Usage
|
|
163
|
+
const tools = buildTools([
|
|
164
|
+
{
|
|
165
|
+
name: 'get_weather',
|
|
166
|
+
description: 'Get current weather for a city',
|
|
167
|
+
schema: z.object({
|
|
168
|
+
city: z.string().describe('City name')
|
|
169
|
+
}),
|
|
170
|
+
func: async ({ city }) => {
|
|
171
|
+
const weather = await WeatherService.get(city)
|
|
172
|
+
return JSON.stringify(weather)
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
])
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### 5. Message Serializer
|
|
179
|
+
|
|
180
|
+
Handles LangChain message serialization for database storage:
|
|
181
|
+
|
|
182
|
+
```typescript
|
|
183
|
+
interface SerializedMessage {
|
|
184
|
+
type: 'human' | 'ai' | 'system' | 'tool'
|
|
185
|
+
content: string
|
|
186
|
+
name?: string
|
|
187
|
+
tool_call_id?: string
|
|
188
|
+
additional_kwargs?: Record<string, unknown>
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// Serialize for storage
|
|
192
|
+
const serialized = serializeMessages(langchainMessages)
|
|
193
|
+
|
|
194
|
+
// Deserialize for agent
|
|
195
|
+
const messages = deserializeMessages(serialized)
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
## Data Flow
|
|
199
|
+
|
|
200
|
+
### Single Agent Flow
|
|
201
|
+
|
|
202
|
+
```
|
|
203
|
+
┌─────────┐ ┌─────────────┐ ┌─────────────┐
|
|
204
|
+
│ User │────→│ API Route │────→│ Agent │
|
|
205
|
+
└─────────┘ └─────────────┘ └──────┬──────┘
|
|
206
|
+
│
|
|
207
|
+
┌──────────────────────┼──────────────────────┐
|
|
208
|
+
│ ▼ │
|
|
209
|
+
│ ┌─────────────┐ │
|
|
210
|
+
│ │ LLM │ │
|
|
211
|
+
│ └──────┬──────┘ │
|
|
212
|
+
│ │ │
|
|
213
|
+
│ ┌───────────┴───────────┐ │
|
|
214
|
+
│ ▼ ▼ │
|
|
215
|
+
│ ┌─────────────┐ ┌─────────────┐ │
|
|
216
|
+
│ │ Tool Call │ │ Response │ │
|
|
217
|
+
│ └──────┬──────┘ └─────────────┘ │
|
|
218
|
+
│ │ │
|
|
219
|
+
│ ▼ │
|
|
220
|
+
│ ┌─────────────┐ │
|
|
221
|
+
│ │ Service │ │
|
|
222
|
+
│ │ (RLS) │ │
|
|
223
|
+
│ └──────┬──────┘ │
|
|
224
|
+
│ │ │
|
|
225
|
+
│ ▼ │
|
|
226
|
+
│ ┌─────────────┐ │
|
|
227
|
+
│ │ Database │ │
|
|
228
|
+
│ └─────────────┘ │
|
|
229
|
+
│ │
|
|
230
|
+
│ AGENT LOOP │
|
|
231
|
+
└─────────────────────────────────────────────┘
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
### Graph-Based Orchestrator Flow (Recommended)
|
|
235
|
+
|
|
236
|
+
The graph-based orchestrator uses a **state machine** approach instead of ReAct loops:
|
|
237
|
+
|
|
238
|
+
```
|
|
239
|
+
┌─────────────────────────────────────────────────────────────────────────────┐
|
|
240
|
+
│ GRAPH ORCHESTRATOR │
|
|
241
|
+
│ │
|
|
242
|
+
│ ┌─────────┐ │
|
|
243
|
+
│ │ START │ │
|
|
244
|
+
│ └────┬────┘ │
|
|
245
|
+
│ │ │
|
|
246
|
+
│ ▼ │
|
|
247
|
+
│ ┌─────────────────────────────────────────────────────────────────────┐ │
|
|
248
|
+
│ │ ROUTER NODE │ │
|
|
249
|
+
│ │ • Structured output (Zod validation) │ │
|
|
250
|
+
│ │ • Intent classification: task, customer, page, greeting, unclear │ │
|
|
251
|
+
│ │ • Multi-provider compatible (OpenAI, Anthropic, Ollama) │ │
|
|
252
|
+
│ │ • Single LLM call with retry logic │ │
|
|
253
|
+
│ └─────────────────────────────────────────┬───────────────────────────┘ │
|
|
254
|
+
│ │ │
|
|
255
|
+
│ ┌─────────────┬──────────────────┼──────────────────┬─────────┐ │
|
|
256
|
+
│ ▼ ▼ ▼ ▼ ▼ │
|
|
257
|
+
│ ┌───────────┐ ┌───────────┐ ┌───────────┐ ┌───────────┐ ┌────┐ │
|
|
258
|
+
│ │ Task │ │ Customer │ │ Page │ │ Greeting │ │END │ │
|
|
259
|
+
│ │ Handler │ │ Handler │ │ Handler │ │ Handler │ │ │ │
|
|
260
|
+
│ │ (0 LLM) │ │ (0 LLM) │ │ (0 LLM) │ │ (0 LLM) │ │ │ │
|
|
261
|
+
│ └─────┬─────┘ └─────┬─────┘ └─────┬─────┘ └─────┬─────┘ └────┘ │
|
|
262
|
+
│ │ │ │ │ │
|
|
263
|
+
│ └──────────────┴────────┬────────┴─────────────────┘ │
|
|
264
|
+
│ │ │
|
|
265
|
+
│ ▼ │
|
|
266
|
+
│ ┌─────────────────────────────────────────────────────────────────────┐ │
|
|
267
|
+
│ │ COMBINER NODE │ │
|
|
268
|
+
│ │ • Aggregates handler results │ │
|
|
269
|
+
│ │ • Template-based for single intent (0 LLM calls) │ │
|
|
270
|
+
│ │ • LLM synthesis for multi-intent (1 LLM call) │ │
|
|
271
|
+
│ └─────────────────────────────────────────────────────────────────────┘ │
|
|
272
|
+
│ │ │
|
|
273
|
+
│ ▼ │
|
|
274
|
+
│ ┌─────────┐ │
|
|
275
|
+
│ │ END │ │
|
|
276
|
+
│ └─────────┘ │
|
|
277
|
+
└─────────────────────────────────────────────────────────────────────────────┘
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
**Key Advantages over ReAct:**
|
|
281
|
+
|
|
282
|
+
| Aspect | Graph Orchestrator | ReAct Loop |
|
|
283
|
+
|--------|-------------------|------------|
|
|
284
|
+
| **LLM Calls** | 1-2 per request | 50+ possible |
|
|
285
|
+
| **Latency** | 2-3 seconds | 10-15+ seconds |
|
|
286
|
+
| **Predictability** | Deterministic flow | Non-deterministic |
|
|
287
|
+
| **Recursion Limits** | Never hit | Frequent issue |
|
|
288
|
+
| **Cost** | ~$0.001/request | ~$0.05/request |
|
|
289
|
+
|
|
290
|
+
> **Full Documentation**: See [Graph Orchestrator](../03-orchestration/01-graph-orchestrator.md) for complete details.
|
|
291
|
+
|
|
292
|
+
### Legacy Orchestrator Flow (Deprecated)
|
|
293
|
+
|
|
294
|
+
> **Note**: This approach is deprecated. Use the graph-based orchestrator instead.
|
|
295
|
+
|
|
296
|
+
```
|
|
297
|
+
┌─────────┐ ┌─────────────────┐ ┌─────────────────┐
|
|
298
|
+
│ User │────→│ Orchestrator │────→│ Routing Tools │
|
|
299
|
+
└─────────┘ └────────┬────────┘ └────────┬────────┘
|
|
300
|
+
│ │
|
|
301
|
+
│ ┌──────────────────┘
|
|
302
|
+
│ │
|
|
303
|
+
▼ ▼
|
|
304
|
+
┌────────────────────────┐
|
|
305
|
+
│ Routing Decision │
|
|
306
|
+
│ { agent, message } │
|
|
307
|
+
└───────────┬────────────┘
|
|
308
|
+
│
|
|
309
|
+
┌────────────────┼────────────────┐
|
|
310
|
+
▼ ▼ ▼
|
|
311
|
+
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
|
312
|
+
│ Task Agent │ │ Customer │ │ Page Agent │
|
|
313
|
+
│ │ │ Agent │ │ │
|
|
314
|
+
└─────────────┘ └─────────────┘ └─────────────┘
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
## Design Patterns
|
|
318
|
+
|
|
319
|
+
### Factory Pattern
|
|
320
|
+
|
|
321
|
+
Used for creating agents and LLM instances:
|
|
322
|
+
|
|
323
|
+
```typescript
|
|
324
|
+
// Agent Factory
|
|
325
|
+
const agent = await createAgent(config)
|
|
326
|
+
|
|
327
|
+
// Provider Factory
|
|
328
|
+
const model = getModel(modelConfig)
|
|
329
|
+
|
|
330
|
+
// Helper Factory
|
|
331
|
+
const helpers = createAgentHelpers(agents, defaults)
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
### Facade Pattern
|
|
335
|
+
|
|
336
|
+
The memory store provides a simplified interface:
|
|
337
|
+
|
|
338
|
+
```typescript
|
|
339
|
+
// External interface (memoryStore)
|
|
340
|
+
memoryStore.getMessages(sessionId, context)
|
|
341
|
+
|
|
342
|
+
// Internal implementation (dbMemoryStore)
|
|
343
|
+
dbMemoryStore.getMessages(sessionId, context)
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
### Strategy Pattern
|
|
347
|
+
|
|
348
|
+
Tool factories allow themes to define custom strategies:
|
|
349
|
+
|
|
350
|
+
```typescript
|
|
351
|
+
// Each agent has its own tool strategy
|
|
352
|
+
createTools: (context) => [
|
|
353
|
+
// Theme-specific tools
|
|
354
|
+
]
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
### Template Pattern
|
|
358
|
+
|
|
359
|
+
Presets provide templates for common patterns:
|
|
360
|
+
|
|
361
|
+
```
|
|
362
|
+
presets/
|
|
363
|
+
├── lib/langchain.config.ts.preset # Configuration template
|
|
364
|
+
├── api/chat/route.ts.preset # API endpoint template
|
|
365
|
+
├── lib/tools/entity-tools.ts.preset # Tools template
|
|
366
|
+
└── agents/entity-assistant.md.preset # Prompt template
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
## Security Architecture
|
|
370
|
+
|
|
371
|
+
### Multi-Tenancy
|
|
372
|
+
|
|
373
|
+
All data is isolated by `userId` + `teamId`:
|
|
374
|
+
|
|
375
|
+
```sql
|
|
376
|
+
-- Every query includes tenant context
|
|
377
|
+
SELECT * FROM langchain_sessions
|
|
378
|
+
WHERE "userId" = $1 AND "teamId" = $2 AND "sessionId" = $3
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
### Row-Level Security
|
|
382
|
+
|
|
383
|
+
The database table has RLS policies:
|
|
384
|
+
|
|
385
|
+
```sql
|
|
386
|
+
-- Only owner can access their sessions
|
|
387
|
+
CREATE POLICY langchain_sessions_policy ON langchain_sessions
|
|
388
|
+
USING (
|
|
389
|
+
"userId" = current_setting('app.user_id')::text
|
|
390
|
+
AND "teamId" = current_setting('app.team_id')::text
|
|
391
|
+
);
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
### Tool-Level Authorization
|
|
395
|
+
|
|
396
|
+
Tools receive context for authorization:
|
|
397
|
+
|
|
398
|
+
```typescript
|
|
399
|
+
createTools: (context: ToolContext) => [
|
|
400
|
+
{
|
|
401
|
+
func: async (input) => {
|
|
402
|
+
// context.userId and context.teamId available
|
|
403
|
+
// Service calls use these for RLS
|
|
404
|
+
return TasksService.list(context.userId, input)
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
]
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
## Performance Considerations
|
|
411
|
+
|
|
412
|
+
### Message Limits
|
|
413
|
+
|
|
414
|
+
Conversations use a sliding window to control token usage:
|
|
415
|
+
|
|
416
|
+
```typescript
|
|
417
|
+
// Only last 50 messages are kept
|
|
418
|
+
if (messages.length > MAX_MESSAGES) {
|
|
419
|
+
messages = messages.slice(-MAX_MESSAGES)
|
|
420
|
+
}
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
### No Dynamic Imports
|
|
424
|
+
|
|
425
|
+
All imports are static for optimal bundling:
|
|
426
|
+
|
|
427
|
+
```typescript
|
|
428
|
+
// Good - static import
|
|
429
|
+
import { createAgent } from '@/contents/plugins/langchain/lib/agent-factory'
|
|
430
|
+
|
|
431
|
+
// Bad - dynamic import (not used)
|
|
432
|
+
const agent = await import('@/contents/plugins/langchain')
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
### Caching
|
|
436
|
+
|
|
437
|
+
Session data is cached in memory during agent lifetime:
|
|
438
|
+
|
|
439
|
+
```typescript
|
|
440
|
+
const agent = await createAgent(config)
|
|
441
|
+
// First call loads from DB
|
|
442
|
+
await agent.chat('Hello')
|
|
443
|
+
// Subsequent calls use cached history
|
|
444
|
+
await agent.chat('How are you?')
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
## Database Schema
|
|
448
|
+
|
|
449
|
+
```sql
|
|
450
|
+
CREATE TABLE public."langchain_sessions" (
|
|
451
|
+
id TEXT PRIMARY KEY,
|
|
452
|
+
|
|
453
|
+
-- Multi-tenancy keys
|
|
454
|
+
"userId" TEXT NOT NULL REFERENCES users(id),
|
|
455
|
+
"teamId" TEXT NOT NULL REFERENCES teams(id),
|
|
456
|
+
"sessionId" TEXT NOT NULL,
|
|
457
|
+
|
|
458
|
+
-- Metadata
|
|
459
|
+
name TEXT DEFAULT NULL,
|
|
460
|
+
"isPinned" BOOLEAN DEFAULT false,
|
|
461
|
+
|
|
462
|
+
-- Message storage
|
|
463
|
+
messages JSONB NOT NULL DEFAULT '[]',
|
|
464
|
+
metadata JSONB DEFAULT '{}',
|
|
465
|
+
"maxMessages" INTEGER DEFAULT 50,
|
|
466
|
+
"expiresAt" TIMESTAMPTZ DEFAULT NULL,
|
|
467
|
+
|
|
468
|
+
-- Timestamps
|
|
469
|
+
"createdAt" TIMESTAMPTZ DEFAULT now(),
|
|
470
|
+
"updatedAt" TIMESTAMPTZ DEFAULT now(),
|
|
471
|
+
|
|
472
|
+
UNIQUE ("userId", "teamId", "sessionId")
|
|
473
|
+
);
|
|
474
|
+
|
|
475
|
+
-- Performance indexes
|
|
476
|
+
CREATE INDEX idx_sessions_lookup
|
|
477
|
+
ON langchain_sessions("userId", "teamId", "sessionId");
|
|
478
|
+
CREATE INDEX idx_sessions_pinned
|
|
479
|
+
ON langchain_sessions("userId", "teamId", "isPinned");
|
|
480
|
+
CREATE INDEX idx_sessions_updated
|
|
481
|
+
ON langchain_sessions("userId", "teamId", "updatedAt" DESC);
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
## Supporting Systems
|
|
485
|
+
|
|
486
|
+
### Observability Layer
|
|
487
|
+
|
|
488
|
+
End-to-end tracing for debugging and monitoring:
|
|
489
|
+
|
|
490
|
+
```
|
|
491
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
492
|
+
│ TRACE RECORD │
|
|
493
|
+
│ traceId: abc-123 │
|
|
494
|
+
│ ├─ Span: router (llm) 1200ms │
|
|
495
|
+
│ ├─ Span: task_handler (tool) 340ms │
|
|
496
|
+
│ └─ Span: combiner (llm) 800ms │
|
|
497
|
+
│ │
|
|
498
|
+
│ Total: 2340ms | Tokens: 230 | Cost: $0.002 │
|
|
499
|
+
└─────────────────────────────────────────────────────────────┘
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
- **Traces**: Complete agent invocations
|
|
503
|
+
- **Spans**: Individual operations (LLM calls, tool calls)
|
|
504
|
+
- **Metrics**: Aggregate performance data
|
|
505
|
+
- **Dashboard**: Visual debugging at `/sector7/ai-observability`
|
|
506
|
+
|
|
507
|
+
> **Documentation**: [Observability](../04-advanced/01-observability.md)
|
|
508
|
+
|
|
509
|
+
### Token & Cost Tracking
|
|
510
|
+
|
|
511
|
+
Per-request and aggregate usage tracking:
|
|
512
|
+
|
|
513
|
+
```
|
|
514
|
+
LLM Request → Token Usage → Cost Calculation → Database → Analytics
|
|
515
|
+
↓ ↓
|
|
516
|
+
inputTokens pricing table
|
|
517
|
+
outputTokens ↓
|
|
518
|
+
totalCost (USD)
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
- Track input/output tokens per request
|
|
522
|
+
- Calculate costs based on model pricing
|
|
523
|
+
- Dashboard at `/dashboard/settings/ai-usage`
|
|
524
|
+
|
|
525
|
+
> **Documentation**: [Token Tracking](../04-advanced/02-token-tracking.md)
|
|
526
|
+
|
|
527
|
+
### Streaming (SSE)
|
|
528
|
+
|
|
529
|
+
Real-time token-by-token responses:
|
|
530
|
+
|
|
531
|
+
```
|
|
532
|
+
User Request → streamChat() → SSE Response
|
|
533
|
+
│
|
|
534
|
+
├─→ { type: 'token', content: 'Hello' }
|
|
535
|
+
├─→ { type: 'tool_start', toolName: 'list_tasks' }
|
|
536
|
+
├─→ { type: 'tool_end', result: [...] }
|
|
537
|
+
└─→ { type: 'done', fullContent: '...' }
|
|
538
|
+
```
|
|
539
|
+
|
|
540
|
+
> **Documentation**: [Streaming](../04-advanced/03-streaming.md)
|
|
541
|
+
|
|
542
|
+
### Guardrails & Security
|
|
543
|
+
|
|
544
|
+
Multi-layer protection for AI interactions:
|
|
545
|
+
|
|
546
|
+
```
|
|
547
|
+
User Input → [Injection Check] → [PII Mask] → Agent → [Content Filter] → Response
|
|
548
|
+
```
|
|
549
|
+
|
|
550
|
+
- **Prompt Injection Detection**: Block manipulation attempts
|
|
551
|
+
- **PII Masking**: Redact sensitive data (emails, phones, etc.)
|
|
552
|
+
- **Content Filtering**: Filter inappropriate outputs
|
|
553
|
+
|
|
554
|
+
> **Documentation**: [Guardrails](../04-advanced/04-guardrails.md)
|
|
555
|
+
|
|
556
|
+
---
|
|
557
|
+
|
|
558
|
+
## Next Steps
|
|
559
|
+
|
|
560
|
+
- [Installation](../01-getting-started/02-installation.md) - Set up the plugin
|
|
561
|
+
- [Configuration](../01-getting-started/03-configuration.md) - Configure agents at the theme level
|
|
562
|
+
- [Graph Orchestrator](../03-orchestration/01-graph-orchestrator.md) - Modern orchestration approach
|
|
563
|
+
- [Observability](../04-advanced/01-observability.md) - Tracing and debugging
|
|
564
|
+
- [Token Tracking](../04-advanced/02-token-tracking.md) - Usage and cost monitoring
|
|
565
|
+
- [Streaming](../04-advanced/03-streaming.md) - Real-time responses
|
|
566
|
+
- [Guardrails](../04-advanced/04-guardrails.md) - Security middleware
|