@falai/agent 0.9.0-alpha-1 → 0.9.0
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/README.md +34 -22
- package/dist/cjs/src/core/Agent.d.ts +77 -59
- package/dist/cjs/src/core/Agent.d.ts.map +1 -1
- package/dist/cjs/src/core/Agent.js +284 -1060
- package/dist/cjs/src/core/Agent.js.map +1 -1
- package/dist/cjs/src/core/PersistenceManager.d.ts.map +1 -1
- package/dist/cjs/src/core/PersistenceManager.js +48 -25
- package/dist/cjs/src/core/PersistenceManager.js.map +1 -1
- package/dist/cjs/src/core/PromptComposer.d.ts +1 -1
- package/dist/cjs/src/core/PromptComposer.d.ts.map +1 -1
- package/dist/cjs/src/core/PromptComposer.js.map +1 -1
- package/dist/cjs/src/core/ResponseEngine.d.ts +13 -12
- package/dist/cjs/src/core/ResponseEngine.d.ts.map +1 -1
- package/dist/cjs/src/core/ResponseEngine.js +4 -4
- package/dist/cjs/src/core/ResponseEngine.js.map +1 -1
- package/dist/cjs/src/core/ResponseModal.d.ts +205 -0
- package/dist/cjs/src/core/ResponseModal.d.ts.map +1 -0
- package/dist/cjs/src/core/ResponseModal.js +1328 -0
- package/dist/cjs/src/core/ResponseModal.js.map +1 -0
- package/dist/cjs/src/core/ResponsePipeline.d.ts +66 -38
- package/dist/cjs/src/core/ResponsePipeline.d.ts.map +1 -1
- package/dist/cjs/src/core/ResponsePipeline.js +72 -4
- package/dist/cjs/src/core/ResponsePipeline.js.map +1 -1
- package/dist/cjs/src/core/Route.d.ts +24 -5
- package/dist/cjs/src/core/Route.d.ts.map +1 -1
- package/dist/cjs/src/core/Route.js +45 -1
- package/dist/cjs/src/core/Route.js.map +1 -1
- package/dist/cjs/src/core/RoutingEngine.d.ts +31 -6
- package/dist/cjs/src/core/RoutingEngine.d.ts.map +1 -1
- package/dist/cjs/src/core/RoutingEngine.js +113 -9
- package/dist/cjs/src/core/RoutingEngine.js.map +1 -1
- package/dist/cjs/src/core/SessionManager.d.ts +14 -4
- package/dist/cjs/src/core/SessionManager.d.ts.map +1 -1
- package/dist/cjs/src/core/SessionManager.js +25 -5
- package/dist/cjs/src/core/SessionManager.js.map +1 -1
- package/dist/cjs/src/core/Step.d.ts +10 -10
- package/dist/cjs/src/core/Step.d.ts.map +1 -1
- package/dist/cjs/src/core/Step.js.map +1 -1
- package/dist/cjs/src/core/ToolExecutor.d.ts +4 -2
- package/dist/cjs/src/core/ToolExecutor.d.ts.map +1 -1
- package/dist/cjs/src/core/ToolExecutor.js +13 -3
- package/dist/cjs/src/core/ToolExecutor.js.map +1 -1
- package/dist/cjs/src/index.d.ts +3 -1
- package/dist/cjs/src/index.d.ts.map +1 -1
- package/dist/cjs/src/index.js +7 -1
- package/dist/cjs/src/index.js.map +1 -1
- package/dist/cjs/src/types/agent.d.ts +42 -21
- package/dist/cjs/src/types/agent.d.ts.map +1 -1
- package/dist/cjs/src/types/agent.js.map +1 -1
- package/dist/cjs/src/types/ai.d.ts +1 -1
- package/dist/cjs/src/types/ai.d.ts.map +1 -1
- package/dist/cjs/src/types/index.d.ts +1 -1
- package/dist/cjs/src/types/index.d.ts.map +1 -1
- package/dist/cjs/src/types/index.js.map +1 -1
- package/dist/cjs/src/types/persistence.d.ts +0 -1
- package/dist/cjs/src/types/persistence.d.ts.map +1 -1
- package/dist/cjs/src/types/route.d.ts +22 -16
- package/dist/cjs/src/types/route.d.ts.map +1 -1
- package/dist/cjs/src/types/session.d.ts +6 -11
- package/dist/cjs/src/types/session.d.ts.map +1 -1
- package/dist/cjs/src/types/tool.d.ts +12 -6
- package/dist/cjs/src/types/tool.d.ts.map +1 -1
- package/dist/cjs/src/utils/clone.d.ts.map +1 -1
- package/dist/cjs/src/utils/clone.js +0 -4
- package/dist/cjs/src/utils/clone.js.map +1 -1
- package/dist/cjs/src/utils/history.d.ts +30 -1
- package/dist/cjs/src/utils/history.d.ts.map +1 -1
- package/dist/cjs/src/utils/history.js +169 -23
- package/dist/cjs/src/utils/history.js.map +1 -1
- package/dist/cjs/src/utils/index.d.ts +1 -1
- package/dist/cjs/src/utils/index.d.ts.map +1 -1
- package/dist/cjs/src/utils/index.js +5 -1
- package/dist/cjs/src/utils/index.js.map +1 -1
- package/dist/cjs/src/utils/session.d.ts +2 -2
- package/dist/cjs/src/utils/session.d.ts.map +1 -1
- package/dist/cjs/src/utils/session.js +6 -26
- package/dist/cjs/src/utils/session.js.map +1 -1
- package/dist/src/core/Agent.d.ts +77 -59
- package/dist/src/core/Agent.d.ts.map +1 -1
- package/dist/src/core/Agent.js +285 -1061
- package/dist/src/core/Agent.js.map +1 -1
- package/dist/src/core/PersistenceManager.d.ts.map +1 -1
- package/dist/src/core/PersistenceManager.js +48 -25
- package/dist/src/core/PersistenceManager.js.map +1 -1
- package/dist/src/core/PromptComposer.d.ts +1 -1
- package/dist/src/core/PromptComposer.d.ts.map +1 -1
- package/dist/src/core/PromptComposer.js.map +1 -1
- package/dist/src/core/ResponseEngine.d.ts +13 -12
- package/dist/src/core/ResponseEngine.d.ts.map +1 -1
- package/dist/src/core/ResponseEngine.js +4 -4
- package/dist/src/core/ResponseEngine.js.map +1 -1
- package/dist/src/core/ResponseModal.d.ts +205 -0
- package/dist/src/core/ResponseModal.d.ts.map +1 -0
- package/dist/src/core/ResponseModal.js +1323 -0
- package/dist/src/core/ResponseModal.js.map +1 -0
- package/dist/src/core/ResponsePipeline.d.ts +66 -38
- package/dist/src/core/ResponsePipeline.d.ts.map +1 -1
- package/dist/src/core/ResponsePipeline.js +72 -4
- package/dist/src/core/ResponsePipeline.js.map +1 -1
- package/dist/src/core/Route.d.ts +24 -5
- package/dist/src/core/Route.d.ts.map +1 -1
- package/dist/src/core/Route.js +45 -1
- package/dist/src/core/Route.js.map +1 -1
- package/dist/src/core/RoutingEngine.d.ts +31 -6
- package/dist/src/core/RoutingEngine.d.ts.map +1 -1
- package/dist/src/core/RoutingEngine.js +113 -9
- package/dist/src/core/RoutingEngine.js.map +1 -1
- package/dist/src/core/SessionManager.d.ts +14 -4
- package/dist/src/core/SessionManager.d.ts.map +1 -1
- package/dist/src/core/SessionManager.js +25 -5
- package/dist/src/core/SessionManager.js.map +1 -1
- package/dist/src/core/Step.d.ts +10 -10
- package/dist/src/core/Step.d.ts.map +1 -1
- package/dist/src/core/Step.js.map +1 -1
- package/dist/src/core/ToolExecutor.d.ts +4 -2
- package/dist/src/core/ToolExecutor.d.ts.map +1 -1
- package/dist/src/core/ToolExecutor.js +13 -3
- package/dist/src/core/ToolExecutor.js.map +1 -1
- package/dist/src/index.d.ts +3 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +2 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/types/agent.d.ts +42 -21
- package/dist/src/types/agent.d.ts.map +1 -1
- package/dist/src/types/agent.js.map +1 -1
- package/dist/src/types/ai.d.ts +1 -1
- package/dist/src/types/ai.d.ts.map +1 -1
- package/dist/src/types/index.d.ts +1 -1
- package/dist/src/types/index.d.ts.map +1 -1
- package/dist/src/types/index.js.map +1 -1
- package/dist/src/types/persistence.d.ts +0 -1
- package/dist/src/types/persistence.d.ts.map +1 -1
- package/dist/src/types/route.d.ts +22 -16
- package/dist/src/types/route.d.ts.map +1 -1
- package/dist/src/types/session.d.ts +6 -11
- package/dist/src/types/session.d.ts.map +1 -1
- package/dist/src/types/tool.d.ts +12 -6
- package/dist/src/types/tool.d.ts.map +1 -1
- package/dist/src/utils/clone.d.ts.map +1 -1
- package/dist/src/utils/clone.js +0 -4
- package/dist/src/utils/clone.js.map +1 -1
- package/dist/src/utils/history.d.ts +30 -1
- package/dist/src/utils/history.d.ts.map +1 -1
- package/dist/src/utils/history.js +165 -23
- package/dist/src/utils/history.js.map +1 -1
- package/dist/src/utils/index.d.ts +1 -1
- package/dist/src/utils/index.d.ts.map +1 -1
- package/dist/src/utils/index.js +1 -1
- package/dist/src/utils/index.js.map +1 -1
- package/dist/src/utils/session.d.ts +2 -2
- package/dist/src/utils/session.d.ts.map +1 -1
- package/dist/src/utils/session.js +6 -26
- package/dist/src/utils/session.js.map +1 -1
- package/docs/README.md +5 -4
- package/docs/api/README.md +195 -4
- package/docs/api/overview.md +232 -13
- package/docs/core/agent/README.md +162 -17
- package/docs/core/agent/context-management.md +39 -15
- package/docs/core/agent/session-management.md +49 -16
- package/docs/core/ai-integration/prompt-composition.md +38 -14
- package/docs/core/ai-integration/response-processing.md +28 -17
- package/docs/core/conversation-flows/data-collection.md +103 -25
- package/docs/core/conversation-flows/route-dsl.md +45 -22
- package/docs/core/conversation-flows/routes.md +74 -18
- package/docs/core/conversation-flows/step-transitions.md +3 -3
- package/docs/core/conversation-flows/steps.md +39 -15
- package/docs/core/routing/intelligent-routing.md +18 -9
- package/docs/core/tools/tool-definition.md +8 -8
- package/docs/core/tools/tool-execution.md +26 -26
- package/docs/core/tools/tool-scoping.md +5 -5
- package/docs/guides/getting-started/README.md +54 -32
- package/docs/guides/migration/README.md +72 -0
- package/docs/guides/migration/response-modal-refactor.md +518 -0
- package/examples/advanced-patterns/knowledge-based-agent.ts +37 -28
- package/examples/advanced-patterns/persistent-onboarding.ts +70 -41
- package/examples/advanced-patterns/route-lifecycle-hooks.ts +28 -2
- package/examples/advanced-patterns/streaming-responses.ts +197 -119
- package/examples/ai-providers/anthropic-integration.ts +40 -33
- package/examples/ai-providers/openai-integration.ts +25 -25
- package/examples/conversation-flows/completion-transitions.ts +36 -32
- package/examples/core-concepts/basic-agent.ts +76 -78
- package/examples/core-concepts/modern-streaming-api.ts +309 -0
- package/examples/core-concepts/schema-driven-extraction.ts +20 -16
- package/examples/core-concepts/session-management.ts +65 -53
- package/examples/integrations/database-integration.ts +49 -34
- package/examples/integrations/healthcare-integration.ts +96 -91
- package/examples/integrations/search-integration.ts +79 -82
- package/examples/integrations/server-session-management.ts +25 -17
- package/examples/persistence/database-persistence.ts +61 -45
- package/examples/persistence/memory-sessions.ts +52 -63
- package/examples/persistence/redis-persistence.ts +81 -95
- package/examples/tools/basic-tools.ts +73 -62
- package/examples/tools/data-enrichment-tools.ts +52 -44
- package/package.json +1 -1
- package/src/core/Agent.ts +396 -1499
- package/src/core/PersistenceManager.ts +51 -27
- package/src/core/PromptComposer.ts +1 -1
- package/src/core/ResponseEngine.ts +21 -19
- package/src/core/ResponseModal.ts +1722 -0
- package/src/core/ResponsePipeline.ts +175 -60
- package/src/core/Route.ts +58 -6
- package/src/core/RoutingEngine.ts +174 -27
- package/src/core/SessionManager.ts +32 -8
- package/src/core/Step.ts +20 -12
- package/src/core/ToolExecutor.ts +19 -5
- package/src/index.ts +11 -0
- package/src/types/agent.ts +47 -23
- package/src/types/ai.ts +1 -1
- package/src/types/index.ts +2 -0
- package/src/types/persistence.ts +0 -1
- package/src/types/route.ts +22 -16
- package/src/types/session.ts +6 -12
- package/src/types/tool.ts +15 -9
- package/src/utils/clone.ts +6 -8
- package/src/utils/history.ts +190 -27
- package/src/utils/index.ts +4 -0
- package/src/utils/session.ts +6 -31
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## Overview
|
|
4
4
|
|
|
5
|
-
The `Agent<TContext>` class is the central orchestrator of @falai/agent, providing a strongly-typed, context-aware AI agent framework with intelligent routing and schema-driven data collection.
|
|
5
|
+
The `Agent<TContext, TData>` class is the central orchestrator of @falai/agent, providing a strongly-typed, context-aware AI agent framework with intelligent routing and agent-level schema-driven data collection.
|
|
6
6
|
|
|
7
7
|
## Core Responsibilities
|
|
8
8
|
|
|
@@ -11,7 +11,7 @@ The `Agent<TContext>` class is the central orchestrator of @falai/agent, providi
|
|
|
11
11
|
- **Context Lifecycle**: Dynamic context management with provider functions and lifecycle hooks
|
|
12
12
|
- **Session Management**: Conversation state persistence and multi-turn dialogue support
|
|
13
13
|
- **Tool Orchestration**: Hierarchical tool execution (agent → route → step level)
|
|
14
|
-
- **Data Collection**:
|
|
14
|
+
- **Agent-Level Data Collection**: Centralized schema-driven information extraction shared across all routes
|
|
15
15
|
|
|
16
16
|
## Agent Configuration
|
|
17
17
|
|
|
@@ -43,7 +43,18 @@ interface CustomerContext {
|
|
|
43
43
|
};
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
|
|
46
|
+
interface CustomerData {
|
|
47
|
+
customerName?: string;
|
|
48
|
+
email?: string;
|
|
49
|
+
phone?: string;
|
|
50
|
+
issueType?: 'booking' | 'billing' | 'technical' | 'other';
|
|
51
|
+
issueDescription?: string;
|
|
52
|
+
priority?: 'low' | 'medium' | 'high';
|
|
53
|
+
rating?: number;
|
|
54
|
+
comments?: string;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const agent = new Agent<CustomerContext, CustomerData>({
|
|
47
58
|
// Identity
|
|
48
59
|
name: "Premium Support Assistant",
|
|
49
60
|
description: "24/7 AI support for premium customers",
|
|
@@ -56,6 +67,21 @@ const agent = new Agent<CustomerContext>({
|
|
|
56
67
|
backupModels: ["gpt-4"],
|
|
57
68
|
}),
|
|
58
69
|
|
|
70
|
+
// Agent-level data schema (NEW)
|
|
71
|
+
schema: {
|
|
72
|
+
type: "object",
|
|
73
|
+
properties: {
|
|
74
|
+
customerName: { type: "string" },
|
|
75
|
+
email: { type: "string", format: "email" },
|
|
76
|
+
phone: { type: "string" },
|
|
77
|
+
issueType: { type: "string", enum: ["booking", "billing", "technical", "other"] },
|
|
78
|
+
issueDescription: { type: "string" },
|
|
79
|
+
priority: { type: "string", enum: ["low", "medium", "high"] },
|
|
80
|
+
rating: { type: "number", minimum: 1, maximum: 5 },
|
|
81
|
+
comments: { type: "string" }
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
|
|
59
85
|
// Static context (can be overridden by contextProvider)
|
|
60
86
|
context: {
|
|
61
87
|
userId: "anonymous",
|
|
@@ -102,16 +128,21 @@ const agent = new Agent<CustomerContext>({
|
|
|
102
128
|
}
|
|
103
129
|
},
|
|
104
130
|
|
|
105
|
-
// Validate and enrich collected data
|
|
131
|
+
// Validate and enrich collected data (NEW: Agent-level data hooks)
|
|
106
132
|
onDataUpdate: async (data, previousData) => {
|
|
107
|
-
// Data validation
|
|
133
|
+
// Data validation against agent schema
|
|
108
134
|
if (data.email && !isValidEmail(data.email)) {
|
|
109
135
|
throw new Error("Invalid email format");
|
|
110
136
|
}
|
|
111
137
|
|
|
112
|
-
// Data enrichment
|
|
113
|
-
if (data.
|
|
114
|
-
data.
|
|
138
|
+
// Data enrichment using agent-level data
|
|
139
|
+
if (data.customerName && !data.customerId) {
|
|
140
|
+
data.customerId = await lookupCustomerId(data.customerName);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Auto-set priority based on issue type
|
|
144
|
+
if (data.issueType === 'billing' && !data.priority) {
|
|
145
|
+
data.priority = 'high';
|
|
115
146
|
}
|
|
116
147
|
|
|
117
148
|
return data;
|
|
@@ -327,26 +358,33 @@ agent.session.clearHistory();
|
|
|
327
358
|
### Declarative Route Creation
|
|
328
359
|
|
|
329
360
|
```typescript
|
|
330
|
-
const agent = new Agent({
|
|
361
|
+
const agent = new Agent<CustomerContext, CustomerData>({
|
|
362
|
+
// Agent-level schema defines all possible data fields
|
|
363
|
+
schema: { /* comprehensive schema */ },
|
|
364
|
+
|
|
331
365
|
routes: [
|
|
332
366
|
{
|
|
333
367
|
title: "Technical Support",
|
|
334
368
|
description: "Help with technical issues",
|
|
335
369
|
conditions: ["user reports technical problem"],
|
|
370
|
+
// NEW: Routes specify required fields instead of schemas
|
|
371
|
+
requiredFields: ["customerName", "email", "issueType", "issueDescription"],
|
|
372
|
+
optionalFields: ["phone", "priority"],
|
|
336
373
|
initialStep: {
|
|
337
374
|
prompt:
|
|
338
375
|
"I understand you're having a technical issue. Can you describe what's happening?",
|
|
339
|
-
collect: ["
|
|
376
|
+
collect: ["issueType", "issueDescription"], // Collects into agent-level data
|
|
340
377
|
},
|
|
341
378
|
},
|
|
342
379
|
{
|
|
343
|
-
title: "Billing Inquiry",
|
|
380
|
+
title: "Billing Inquiry",
|
|
344
381
|
description: "Handle billing and payment questions",
|
|
345
382
|
conditions: ["user asks about billing or payment"],
|
|
383
|
+
requiredFields: ["customerName", "email", "issueType"],
|
|
346
384
|
initialStep: {
|
|
347
385
|
prompt:
|
|
348
386
|
"I'd be happy to help with your billing question. What can I assist with?",
|
|
349
|
-
collect: ["
|
|
387
|
+
collect: ["issueType"], // Maps to agent schema field
|
|
350
388
|
},
|
|
351
389
|
},
|
|
352
390
|
],
|
|
@@ -356,18 +394,21 @@ const agent = new Agent({
|
|
|
356
394
|
### Programmatic Route Creation
|
|
357
395
|
|
|
358
396
|
```typescript
|
|
359
|
-
// Create routes dynamically
|
|
397
|
+
// Create routes dynamically with required fields
|
|
360
398
|
const supportRoute = agent
|
|
361
399
|
.createRoute({
|
|
362
400
|
title: "Customer Support",
|
|
401
|
+
requiredFields: ["customerName", "email", "issueType"], // NEW: Required fields
|
|
402
|
+
optionalFields: ["phone"], // NEW: Optional fields
|
|
363
403
|
initialStep: {
|
|
364
404
|
prompt: "How can I help you today?",
|
|
365
|
-
collect: ["
|
|
405
|
+
collect: ["customerName", "email"], // Collects into agent-level data
|
|
366
406
|
},
|
|
367
407
|
})
|
|
368
408
|
.nextStep({
|
|
369
|
-
prompt: "I understand you need help
|
|
370
|
-
|
|
409
|
+
prompt: "I understand you need help, {{customerName}}. What type of issue are you experiencing?",
|
|
410
|
+
collect: ["issueType"],
|
|
411
|
+
requires: ["customerName", "email"], // Prerequisites from agent data
|
|
371
412
|
});
|
|
372
413
|
|
|
373
414
|
// Access created routes
|
|
@@ -404,6 +445,110 @@ const route = agent.createRoute({
|
|
|
404
445
|
2. **Route-level tools**
|
|
405
446
|
3. **Agent-level tools** (lowest priority)
|
|
406
447
|
|
|
448
|
+
## Agent-Level Data Collection
|
|
449
|
+
|
|
450
|
+
### Centralized Data Schema
|
|
451
|
+
|
|
452
|
+
The new architecture centralizes data collection at the agent level, allowing all routes to work with the same data structure:
|
|
453
|
+
|
|
454
|
+
```typescript
|
|
455
|
+
interface ComprehensiveData {
|
|
456
|
+
// Customer identification
|
|
457
|
+
customerId?: string;
|
|
458
|
+
customerName?: string;
|
|
459
|
+
email?: string;
|
|
460
|
+
phone?: string;
|
|
461
|
+
|
|
462
|
+
// Issue tracking
|
|
463
|
+
issueType?: 'booking' | 'billing' | 'technical' | 'other';
|
|
464
|
+
issueDescription?: string;
|
|
465
|
+
priority?: 'low' | 'medium' | 'high';
|
|
466
|
+
|
|
467
|
+
// Feedback
|
|
468
|
+
rating?: number;
|
|
469
|
+
comments?: string;
|
|
470
|
+
recommendToFriend?: boolean;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
const agent = new Agent<Context, ComprehensiveData>({
|
|
474
|
+
name: "Customer Service Agent",
|
|
475
|
+
schema: {
|
|
476
|
+
type: "object",
|
|
477
|
+
properties: {
|
|
478
|
+
customerId: { type: "string" },
|
|
479
|
+
customerName: { type: "string" },
|
|
480
|
+
email: { type: "string", format: "email" },
|
|
481
|
+
phone: { type: "string" },
|
|
482
|
+
issueType: { type: "string", enum: ["booking", "billing", "technical", "other"] },
|
|
483
|
+
issueDescription: { type: "string" },
|
|
484
|
+
priority: { type: "string", enum: ["low", "medium", "high"] },
|
|
485
|
+
rating: { type: "number", minimum: 1, maximum: 5 },
|
|
486
|
+
comments: { type: "string" },
|
|
487
|
+
recommendToFriend: { type: "boolean" }
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
});
|
|
491
|
+
```
|
|
492
|
+
|
|
493
|
+
### Route Completion Based on Required Fields
|
|
494
|
+
|
|
495
|
+
Routes now specify which fields they need to complete, enabling cross-route data sharing:
|
|
496
|
+
|
|
497
|
+
```typescript
|
|
498
|
+
// Support route needs basic info + issue details
|
|
499
|
+
const supportRoute = agent.createRoute({
|
|
500
|
+
title: "Customer Support",
|
|
501
|
+
requiredFields: ["customerName", "email", "issueType", "issueDescription"],
|
|
502
|
+
optionalFields: ["phone", "priority"]
|
|
503
|
+
});
|
|
504
|
+
|
|
505
|
+
// Feedback route needs basic info + rating
|
|
506
|
+
const feedbackRoute = agent.createRoute({
|
|
507
|
+
title: "Feedback Collection",
|
|
508
|
+
requiredFields: ["customerName", "email", "rating"],
|
|
509
|
+
optionalFields: ["comments", "recommendToFriend"]
|
|
510
|
+
});
|
|
511
|
+
|
|
512
|
+
// Routes can complete when their required data is available,
|
|
513
|
+
// regardless of which route collected it
|
|
514
|
+
```
|
|
515
|
+
|
|
516
|
+
### Cross-Route Data Sharing
|
|
517
|
+
|
|
518
|
+
Data collected by any route is available to all other routes:
|
|
519
|
+
|
|
520
|
+
```typescript
|
|
521
|
+
// User starts with support, provides name and email
|
|
522
|
+
const response1 = await agent.respond("I need help, my name is John Doe, email john@example.com");
|
|
523
|
+
// Agent data now contains: { customerName: "John Doe", email: "john@example.com" }
|
|
524
|
+
|
|
525
|
+
// User switches to feedback - already has 2/3 required fields
|
|
526
|
+
const response2 = await agent.respond("Actually, I want to leave feedback. I'd rate you 5 stars.");
|
|
527
|
+
// Feedback route completes immediately with: { customerName: "John Doe", email: "john@example.com", rating: 5 }
|
|
528
|
+
```
|
|
529
|
+
|
|
530
|
+
### Agent Data Management Methods
|
|
531
|
+
|
|
532
|
+
Access and update agent-level data programmatically:
|
|
533
|
+
|
|
534
|
+
```typescript
|
|
535
|
+
// Get current collected data
|
|
536
|
+
const currentData = agent.getCollectedData();
|
|
537
|
+
console.log(currentData); // { customerName: "John", email: "john@example.com" }
|
|
538
|
+
|
|
539
|
+
// Update data programmatically
|
|
540
|
+
await agent.updateCollectedData({
|
|
541
|
+
customerId: "CUST-12345",
|
|
542
|
+
priority: "high"
|
|
543
|
+
});
|
|
544
|
+
|
|
545
|
+
// Validate data against schema
|
|
546
|
+
const validation = agent.validateData({ email: "invalid-email" });
|
|
547
|
+
if (!validation.valid) {
|
|
548
|
+
console.log(validation.errors); // Detailed validation errors
|
|
549
|
+
}
|
|
550
|
+
```
|
|
551
|
+
|
|
407
552
|
## Response Generation
|
|
408
553
|
|
|
409
554
|
### Simple Response API
|
|
@@ -412,7 +557,7 @@ const route = agent.createRoute({
|
|
|
412
557
|
// Simple message-based API (recommended)
|
|
413
558
|
const response = await agent.respond("How do I reset my password?");
|
|
414
559
|
console.log(response.message);
|
|
415
|
-
console.log(agent.session.getData()); //
|
|
560
|
+
console.log(agent.session.getData<CustomerData>()); // Agent-level collected data
|
|
416
561
|
console.log(response.toolCalls); // Any tool calls made
|
|
417
562
|
console.log(response.isRouteComplete); // Whether route finished
|
|
418
563
|
|
|
@@ -8,28 +8,45 @@ The `@falai/agent` framework provides **automatic session management** through t
|
|
|
8
8
|
|
|
9
9
|
## 🎯 Automatic Session Management
|
|
10
10
|
|
|
11
|
-
The `SessionManager` automatically tracks
|
|
11
|
+
The `SessionManager` automatically tracks four key aspects of a conversation:
|
|
12
12
|
|
|
13
13
|
1. **Current Route** - Which conversation flow the user is in
|
|
14
14
|
2. **Current Step** - Where in the flow they currently are
|
|
15
|
-
3. **
|
|
15
|
+
3. **Agent-Level Data** - Centralized structured data collected across all routes
|
|
16
16
|
4. **Conversation History** - Complete message history within the session
|
|
17
17
|
|
|
18
18
|
```typescript
|
|
19
|
-
// Define your data extraction type
|
|
20
|
-
interface
|
|
19
|
+
// Define your agent-level data extraction type
|
|
20
|
+
interface TravelData {
|
|
21
21
|
destination: string;
|
|
22
22
|
departureDate: string;
|
|
23
23
|
passengers: number;
|
|
24
24
|
cabinClass: "economy" | "business" | "first";
|
|
25
|
+
hotelPreference?: string;
|
|
26
|
+
budgetRange?: string;
|
|
27
|
+
specialRequests?: string;
|
|
25
28
|
}
|
|
26
29
|
|
|
27
|
-
// Agent with automatic session management
|
|
28
|
-
const agent = new Agent({
|
|
30
|
+
// Agent with automatic session management and agent-level schema
|
|
31
|
+
const agent = new Agent<{}, TravelData>({
|
|
29
32
|
name: "Travel Agent",
|
|
30
33
|
provider: new OpenAIProvider({ apiKey: process.env.OPENAI_API_KEY }),
|
|
31
34
|
persistence: { adapter: new PrismaAdapter({ prisma }) },
|
|
32
|
-
sessionId: "user-123" // Automatically loads or creates session
|
|
35
|
+
sessionId: "user-123", // Automatically loads or creates session
|
|
36
|
+
|
|
37
|
+
// Agent-level schema for all data collection
|
|
38
|
+
schema: {
|
|
39
|
+
type: "object",
|
|
40
|
+
properties: {
|
|
41
|
+
destination: { type: "string" },
|
|
42
|
+
departureDate: { type: "string", format: "date" },
|
|
43
|
+
passengers: { type: "number", minimum: 1, maximum: 9 },
|
|
44
|
+
cabinClass: { type: "string", enum: ["economy", "business", "first"] },
|
|
45
|
+
hotelPreference: { type: "string" },
|
|
46
|
+
budgetRange: { type: "string" },
|
|
47
|
+
specialRequests: { type: "string" }
|
|
48
|
+
}
|
|
49
|
+
}
|
|
33
50
|
});
|
|
34
51
|
|
|
35
52
|
// Simple conversation - session managed automatically
|
|
@@ -37,7 +54,7 @@ const response = await agent.respond("I want to book a flight to Paris");
|
|
|
37
54
|
|
|
38
55
|
// Access session information
|
|
39
56
|
console.log(agent.session.id); // "user-123"
|
|
40
|
-
console.log(agent.session.getData<
|
|
57
|
+
console.log(agent.session.getData<TravelData>()); // { destination: "Paris", ... }
|
|
41
58
|
console.log(agent.session.getHistory()); // Conversation history
|
|
42
59
|
```
|
|
43
60
|
|
|
@@ -64,12 +81,13 @@ const sessionManager = agent.session;
|
|
|
64
81
|
await sessionManager.getOrCreate("user-123");
|
|
65
82
|
await sessionManager.getOrCreate(); // Auto-generates ID
|
|
66
83
|
|
|
67
|
-
//
|
|
68
|
-
const data = sessionManager.getData<
|
|
84
|
+
// Agent-level data management
|
|
85
|
+
const data = sessionManager.getData<TravelData>();
|
|
69
86
|
await sessionManager.setData({
|
|
70
87
|
destination: "Paris",
|
|
71
88
|
departureDate: "2025-10-15",
|
|
72
89
|
passengers: 2,
|
|
90
|
+
cabinClass: "economy"
|
|
73
91
|
});
|
|
74
92
|
|
|
75
93
|
// History management
|
|
@@ -128,19 +146,25 @@ const agent = new Agent({
|
|
|
128
146
|
await saveUserData(newContext.userId, newContext);
|
|
129
147
|
},
|
|
130
148
|
|
|
131
|
-
//
|
|
149
|
+
// Agent-level data validation and enrichment
|
|
132
150
|
onDataUpdate: async (data, previousData) => {
|
|
133
151
|
// Normalize passenger count
|
|
134
152
|
if (data.passengers < 1) data.passengers = 1;
|
|
135
153
|
if (data.passengers > 9) data.passengers = 9;
|
|
136
154
|
|
|
137
|
-
// Enrich with computed fields
|
|
138
|
-
if (data.destination) {
|
|
155
|
+
// Enrich with computed fields using agent-level data
|
|
156
|
+
if (data.destination && !data.destinationCode) {
|
|
139
157
|
data.destinationCode = await lookupAirportCode(data.destination);
|
|
140
158
|
}
|
|
141
159
|
|
|
142
|
-
// Auto-
|
|
143
|
-
if (
|
|
160
|
+
// Auto-set budget range based on cabin class
|
|
161
|
+
if (data.cabinClass && !data.budgetRange) {
|
|
162
|
+
data.budgetRange = data.cabinClass === 'first' ? 'premium' :
|
|
163
|
+
data.cabinClass === 'business' ? 'high' : 'standard';
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Auto-trigger actions when we have complete booking data
|
|
167
|
+
if (data.destination && data.departureDate && data.passengers) {
|
|
144
168
|
data.shouldSearchFlights = true;
|
|
145
169
|
}
|
|
146
170
|
|
|
@@ -6,22 +6,28 @@ The `@falai/agent` framework provides **automatic session management** through t
|
|
|
6
6
|
|
|
7
7
|
## Core Design Principles
|
|
8
8
|
|
|
9
|
-
### 1. 🎯 Schema-First Data Extraction
|
|
9
|
+
### 1. 🎯 Agent-Level Schema-First Data Extraction
|
|
10
10
|
|
|
11
|
-
Define what data to collect upfront using JSON Schema, then extract it reliably:
|
|
11
|
+
Define what data to collect upfront using JSON Schema at the agent level, then extract it reliably across all routes:
|
|
12
12
|
|
|
13
13
|
```typescript
|
|
14
|
-
// Define your data contract
|
|
15
|
-
interface
|
|
14
|
+
// Define your agent-level data contract
|
|
15
|
+
interface TravelData {
|
|
16
16
|
destination: string;
|
|
17
17
|
departureDate: string;
|
|
18
18
|
passengers: number;
|
|
19
19
|
cabinClass: "economy" | "business" | "first";
|
|
20
|
+
hotelPreference?: string;
|
|
21
|
+
budgetRange?: string;
|
|
22
|
+
specialRequests?: string;
|
|
20
23
|
}
|
|
21
24
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
+
// Agent with centralized schema
|
|
26
|
+
const agent = new Agent<{}, TravelData>({
|
|
27
|
+
name: "Travel Agent",
|
|
28
|
+
provider: new OpenAIProvider({ apiKey: process.env.OPENAI_API_KEY }),
|
|
29
|
+
|
|
30
|
+
// Agent-level schema defines all possible data fields
|
|
25
31
|
schema: {
|
|
26
32
|
type: "object",
|
|
27
33
|
properties: {
|
|
@@ -33,40 +39,67 @@ const route = agent.createRoute<FlightData>({
|
|
|
33
39
|
enum: ["economy", "business", "first"],
|
|
34
40
|
default: "economy",
|
|
35
41
|
},
|
|
42
|
+
hotelPreference: { type: "string" },
|
|
43
|
+
budgetRange: { type: "string" },
|
|
44
|
+
specialRequests: { type: "string" }
|
|
36
45
|
},
|
|
37
46
|
required: ["destination", "departureDate", "passengers"],
|
|
38
|
-
}
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
// Routes specify required fields instead of schemas
|
|
51
|
+
const flightRoute = agent.createRoute({
|
|
52
|
+
title: "Book Flight",
|
|
53
|
+
description: "Help user book a flight",
|
|
54
|
+
requiredFields: ["destination", "departureDate", "passengers", "cabinClass"],
|
|
55
|
+
optionalFields: ["specialRequests"]
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
const hotelRoute = agent.createRoute({
|
|
59
|
+
title: "Book Hotel",
|
|
60
|
+
description: "Help user book accommodation",
|
|
61
|
+
requiredFields: ["destination", "departureDate", "hotelPreference"],
|
|
62
|
+
optionalFields: ["budgetRange", "specialRequests"]
|
|
39
63
|
});
|
|
40
64
|
```
|
|
41
65
|
|
|
42
|
-
**Why?**
|
|
66
|
+
**Why?** Agent-level schema-first extraction provides:
|
|
43
67
|
|
|
44
|
-
- **Type Safety** - Full TypeScript types from definition to extraction
|
|
68
|
+
- **Type Safety** - Full TypeScript types from definition to extraction across all routes
|
|
45
69
|
- **Reliability** - Provider-enforced schemas, not prompt-based parsing
|
|
46
|
-
- **Predictability** - Same data structure every time
|
|
70
|
+
- **Predictability** - Same data structure every time, shared across routes
|
|
47
71
|
- **Efficiency** - Extract multiple fields in one LLM call
|
|
72
|
+
- **Cross-Route Data Sharing** - Data collected by any route is available to all routes
|
|
73
|
+
- **Route Completion** - Routes complete when their required fields are satisfied
|
|
48
74
|
|
|
49
75
|
### 2. 🤖 Automatic Session Management
|
|
50
76
|
|
|
51
77
|
Sessions are automatically managed through the `SessionManager` class integrated into every `Agent`:
|
|
52
78
|
|
|
53
79
|
```typescript
|
|
54
|
-
// Server-side: Agent with automatic session management
|
|
55
|
-
const agent = new Agent({
|
|
80
|
+
// Server-side: Agent with automatic session management and agent-level data
|
|
81
|
+
const agent = new Agent<{}, TravelData>({
|
|
56
82
|
name: "Travel Agent",
|
|
57
83
|
provider: new OpenAIProvider({ apiKey: process.env.OPENAI_API_KEY }),
|
|
58
84
|
persistence: { adapter: new PrismaAdapter({ prisma }) },
|
|
59
|
-
sessionId: "user-123" // Automatically loads or creates this session
|
|
85
|
+
sessionId: "user-123", // Automatically loads or creates this session
|
|
86
|
+
|
|
87
|
+
// Agent-level schema
|
|
88
|
+
schema: { /* comprehensive travel data schema */ }
|
|
60
89
|
});
|
|
61
90
|
|
|
62
91
|
// Simple conversation - no manual session management
|
|
63
92
|
const response1 = await agent.respond("I want to book a flight to Paris");
|
|
64
93
|
console.log(agent.session.id); // Session ID
|
|
65
|
-
console.log(agent.session.getData()); //
|
|
94
|
+
console.log(agent.session.getData<TravelData>()); // Agent-level collected data
|
|
66
95
|
|
|
67
96
|
// Continue conversation - session automatically maintained
|
|
68
97
|
const response2 = await agent.respond("Make that Tokyo instead");
|
|
69
|
-
// Session automatically updated with new data
|
|
98
|
+
// Session automatically updated with new data in agent-level structure
|
|
99
|
+
|
|
100
|
+
// Switch to hotel booking - data is shared
|
|
101
|
+
const response3 = await agent.respond("Also book me a hotel in Tokyo");
|
|
102
|
+
// Hotel route can access destination data collected by flight route
|
|
70
103
|
```
|
|
71
104
|
|
|
72
105
|
**SessionManager API:**
|
|
@@ -103,35 +103,59 @@ Assistant: Great! Let me check flights for next week. Could you tell me which ai
|
|
|
103
103
|
Current session information including:
|
|
104
104
|
|
|
105
105
|
- Active route and step
|
|
106
|
-
-
|
|
106
|
+
- Agent-level collected data (with privacy filtering)
|
|
107
107
|
- Route progress and completion status
|
|
108
|
+
- Cross-route data availability
|
|
109
|
+
|
|
110
|
+
```
|
|
111
|
+
Current Session:
|
|
112
|
+
- Route: Flight Booking (2/3 required fields collected)
|
|
113
|
+
- Step: ask_passengers
|
|
114
|
+
- Agent Data: { destination: "Paris", departureDate: "2025-01-15" }
|
|
115
|
+
- Missing Required: passengers
|
|
116
|
+
- Available from other routes: { hotelPreference: "luxury" }
|
|
117
|
+
```
|
|
108
118
|
|
|
109
119
|
## Dynamic Schema Generation
|
|
110
120
|
|
|
111
|
-
For data collection steps, the prompt includes JSON schemas:
|
|
121
|
+
For data collection steps, the prompt includes agent-level JSON schemas:
|
|
112
122
|
|
|
113
123
|
```typescript
|
|
114
|
-
//
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
}
|
|
124
|
+
// Agent-level schema
|
|
125
|
+
const agent = new Agent<{}, TravelData>({
|
|
126
|
+
schema: {
|
|
127
|
+
type: "object",
|
|
128
|
+
properties: {
|
|
129
|
+
destination: { type: "string" },
|
|
130
|
+
departureDate: { type: "string", format: "date" },
|
|
131
|
+
passengers: { type: "number", minimum: 1 },
|
|
132
|
+
hotelPreference: { type: "string" },
|
|
133
|
+
budgetRange: { type: "string" }
|
|
134
|
+
},
|
|
135
|
+
required: ["destination", "departureDate"]
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
// Route specifies which fields to collect
|
|
140
|
+
const flightRoute = agent.createRoute({
|
|
141
|
+
title: "Flight Booking",
|
|
142
|
+
requiredFields: ["destination", "departureDate", "passengers"],
|
|
143
|
+
optionalFields: ["budgetRange"]
|
|
144
|
+
});
|
|
124
145
|
```
|
|
125
146
|
|
|
126
147
|
Generates:
|
|
127
148
|
|
|
128
149
|
```
|
|
129
|
-
Extract the following information from the user's response:
|
|
150
|
+
Extract the following information from the user's response based on the agent schema:
|
|
130
151
|
- destination: string - Where the user wants to fly
|
|
131
152
|
- departureDate: string (date format) - When they want to depart
|
|
132
153
|
- passengers: number (minimum 1) - How many people are traveling
|
|
154
|
+
- budgetRange: string (optional) - Budget preference for the trip
|
|
133
155
|
|
|
134
|
-
Return extracted data as valid JSON matching
|
|
156
|
+
Return extracted data as valid JSON matching the agent schema.
|
|
157
|
+
Current route requires: destination, departureDate, passengers
|
|
158
|
+
Route completion: 2/3 required fields collected
|
|
135
159
|
```
|
|
136
160
|
|
|
137
161
|
## Tool Integration
|
|
@@ -20,26 +20,33 @@ AI responses are parsed to extract:
|
|
|
20
20
|
3. **Tool Calls** - Instructions to execute tools
|
|
21
21
|
4. **Routing Decisions** - Route or step transitions
|
|
22
22
|
|
|
23
|
-
## Schema-Driven Extraction
|
|
23
|
+
## Agent-Level Schema-Driven Extraction
|
|
24
24
|
|
|
25
|
-
When steps specify `collect` fields, the AI response is validated against JSON
|
|
25
|
+
When steps specify `collect` fields, the AI response is validated against the agent-level JSON schema:
|
|
26
26
|
|
|
27
27
|
```typescript
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
collect: ["name", "email"],
|
|
28
|
+
// Agent defines comprehensive schema
|
|
29
|
+
const agent = new Agent<{}, UserData>({
|
|
31
30
|
schema: {
|
|
32
31
|
type: "object",
|
|
33
32
|
properties: {
|
|
34
33
|
name: { type: "string" },
|
|
35
34
|
email: { type: "string", format: "email" },
|
|
35
|
+
phone: { type: "string" },
|
|
36
|
+
preferences: { type: "object" }
|
|
36
37
|
},
|
|
37
|
-
required: ["name", "email"]
|
|
38
|
-
}
|
|
38
|
+
required: ["name", "email"]
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// Steps collect into agent schema
|
|
43
|
+
const step = route.initialStep.nextStep({
|
|
44
|
+
prompt: "What's your name and email?",
|
|
45
|
+
collect: ["name", "email"], // Maps to agent schema fields
|
|
39
46
|
});
|
|
40
47
|
```
|
|
41
48
|
|
|
42
|
-
The AI receives instructions to return structured data
|
|
49
|
+
The AI receives instructions to return structured data that matches the agent-level schema, enabling cross-route data sharing.
|
|
43
50
|
|
|
44
51
|
## Tool Execution Pipeline
|
|
45
52
|
|
|
@@ -65,26 +72,30 @@ When tools are called, the response engine:
|
|
|
65
72
|
|
|
66
73
|
## Data Validation
|
|
67
74
|
|
|
68
|
-
Extracted data is validated against
|
|
75
|
+
Extracted data is validated against the agent-level schema:
|
|
69
76
|
|
|
70
|
-
- **Type checking** - Ensures correct data types
|
|
71
|
-
- **Required fields** - Validates mandatory data presence
|
|
72
|
-
- **Format validation** - Email, dates, custom formats
|
|
73
|
-
- **Business rules** - Custom validation logic
|
|
77
|
+
- **Type checking** - Ensures correct data types against agent schema
|
|
78
|
+
- **Required fields** - Validates mandatory data presence for route completion
|
|
79
|
+
- **Format validation** - Email, dates, custom formats from agent schema
|
|
80
|
+
- **Business rules** - Custom validation logic in agent-level hooks
|
|
81
|
+
- **Cross-route consistency** - Ensures data consistency across all routes
|
|
74
82
|
|
|
75
83
|
## Context Updates
|
|
76
84
|
|
|
77
85
|
Response processing updates multiple context layers:
|
|
78
86
|
|
|
79
|
-
###
|
|
87
|
+
### Agent-Level Data
|
|
80
88
|
|
|
81
89
|
```typescript
|
|
82
|
-
// Collected data merged into
|
|
83
|
-
|
|
84
|
-
...
|
|
90
|
+
// Collected data merged into agent-level data structure
|
|
91
|
+
agent.collectedData = {
|
|
92
|
+
...agent.collectedData,
|
|
85
93
|
...extractedData,
|
|
86
94
|
...toolResults,
|
|
87
95
|
};
|
|
96
|
+
|
|
97
|
+
// Session references agent data
|
|
98
|
+
session.data = agent.collectedData;
|
|
88
99
|
```
|
|
89
100
|
|
|
90
101
|
### Route Context
|