@falai/agent 0.4.1 → 0.5.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/README.md +21 -74
- package/dist/cjs/core/Agent.d.ts +22 -29
- package/dist/cjs/core/Agent.d.ts.map +1 -1
- package/dist/cjs/core/Agent.js +464 -291
- package/dist/cjs/core/Agent.js.map +1 -1
- package/dist/cjs/core/Events.d.ts +10 -1
- package/dist/cjs/core/Events.d.ts.map +1 -1
- package/dist/cjs/core/Events.js +3 -2
- package/dist/cjs/core/Events.js.map +1 -1
- package/dist/cjs/core/PersistenceManager.d.ts +19 -0
- package/dist/cjs/core/PersistenceManager.d.ts.map +1 -1
- package/dist/cjs/core/PersistenceManager.js +55 -0
- package/dist/cjs/core/PersistenceManager.js.map +1 -1
- package/dist/cjs/core/PromptComposer.d.ts +24 -0
- package/dist/cjs/core/PromptComposer.d.ts.map +1 -0
- package/dist/cjs/core/PromptComposer.js +127 -0
- package/dist/cjs/core/PromptComposer.js.map +1 -0
- package/dist/cjs/core/ResponseEngine.d.ts +19 -0
- package/dist/cjs/core/ResponseEngine.d.ts.map +1 -0
- package/dist/cjs/core/ResponseEngine.js +51 -0
- package/dist/cjs/core/ResponseEngine.js.map +1 -0
- package/dist/cjs/core/Route.d.ts +18 -12
- package/dist/cjs/core/Route.d.ts.map +1 -1
- package/dist/cjs/core/Route.js +15 -9
- package/dist/cjs/core/Route.js.map +1 -1
- package/dist/cjs/core/RoutingEngine.d.ts +38 -0
- package/dist/cjs/core/RoutingEngine.d.ts.map +1 -0
- package/dist/cjs/core/RoutingEngine.js +110 -0
- package/dist/cjs/core/RoutingEngine.js.map +1 -0
- package/dist/cjs/core/State.d.ts +15 -4
- package/dist/cjs/core/State.d.ts.map +1 -1
- package/dist/cjs/core/State.js +21 -2
- package/dist/cjs/core/State.js.map +1 -1
- package/dist/cjs/core/ToolExecutor.d.ts +29 -0
- package/dist/cjs/core/ToolExecutor.d.ts.map +1 -0
- package/dist/cjs/core/ToolExecutor.js +73 -0
- package/dist/cjs/core/ToolExecutor.js.map +1 -0
- package/dist/cjs/core/Transition.d.ts +5 -5
- package/dist/cjs/core/Transition.d.ts.map +1 -1
- package/dist/cjs/core/Transition.js.map +1 -1
- package/dist/cjs/index.d.ts +6 -8
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +8 -10
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/providers/AnthropicProvider.d.ts.map +1 -1
- package/dist/cjs/providers/AnthropicProvider.js +10 -13
- package/dist/cjs/providers/AnthropicProvider.js.map +1 -1
- package/dist/cjs/providers/GeminiProvider.d.ts.map +1 -1
- package/dist/cjs/providers/GeminiProvider.js +12 -8
- package/dist/cjs/providers/GeminiProvider.js.map +1 -1
- package/dist/cjs/providers/OpenAIProvider.d.ts.map +1 -1
- package/dist/cjs/providers/OpenAIProvider.js +10 -53
- package/dist/cjs/providers/OpenAIProvider.js.map +1 -1
- package/dist/cjs/providers/OpenRouterProvider.d.ts.map +1 -1
- package/dist/cjs/providers/OpenRouterProvider.js +10 -53
- package/dist/cjs/providers/OpenRouterProvider.js.map +1 -1
- package/dist/cjs/types/agent.d.ts +13 -12
- package/dist/cjs/types/agent.d.ts.map +1 -1
- package/dist/cjs/types/ai.d.ts +8 -2
- package/dist/cjs/types/ai.d.ts.map +1 -1
- package/dist/cjs/types/history.d.ts +8 -0
- package/dist/cjs/types/history.d.ts.map +1 -1
- package/dist/cjs/types/index.d.ts +0 -3
- package/dist/cjs/types/index.d.ts.map +1 -1
- package/dist/cjs/types/index.js +1 -3
- package/dist/cjs/types/index.js.map +1 -1
- package/dist/cjs/types/route.d.ts +39 -4
- package/dist/cjs/types/route.d.ts.map +1 -1
- package/dist/cjs/types/routing.d.ts +16 -0
- package/dist/cjs/types/routing.d.ts.map +1 -0
- package/dist/cjs/types/routing.js +3 -0
- package/dist/cjs/types/routing.js.map +1 -0
- package/dist/cjs/types/schema.d.ts +22 -0
- package/dist/cjs/types/schema.d.ts.map +1 -0
- package/dist/cjs/types/schema.js +3 -0
- package/dist/cjs/types/schema.js.map +1 -0
- package/dist/cjs/types/session.d.ts +77 -0
- package/dist/cjs/types/session.d.ts.map +1 -0
- package/dist/cjs/types/session.js +146 -0
- package/dist/cjs/types/session.js.map +1 -0
- package/dist/cjs/types/tool.d.ts +11 -5
- package/dist/cjs/types/tool.d.ts.map +1 -1
- package/dist/cjs/utils/id.d.ts +0 -5
- package/dist/cjs/utils/id.d.ts.map +1 -1
- package/dist/cjs/utils/id.js +0 -10
- package/dist/cjs/utils/id.js.map +1 -1
- package/dist/cjs/utils/schema.d.ts +17 -0
- package/dist/cjs/utils/schema.d.ts.map +1 -0
- package/dist/cjs/utils/schema.js +32 -0
- package/dist/cjs/utils/schema.js.map +1 -0
- package/dist/core/Agent.d.ts +22 -29
- package/dist/core/Agent.d.ts.map +1 -1
- package/dist/core/Agent.js +464 -291
- package/dist/core/Agent.js.map +1 -1
- package/dist/core/Events.d.ts +10 -1
- package/dist/core/Events.d.ts.map +1 -1
- package/dist/core/Events.js +3 -2
- package/dist/core/Events.js.map +1 -1
- package/dist/core/PersistenceManager.d.ts +19 -0
- package/dist/core/PersistenceManager.d.ts.map +1 -1
- package/dist/core/PersistenceManager.js +55 -0
- package/dist/core/PersistenceManager.js.map +1 -1
- package/dist/core/PromptComposer.d.ts +24 -0
- package/dist/core/PromptComposer.d.ts.map +1 -0
- package/dist/core/PromptComposer.js +123 -0
- package/dist/core/PromptComposer.js.map +1 -0
- package/dist/core/ResponseEngine.d.ts +19 -0
- package/dist/core/ResponseEngine.d.ts.map +1 -0
- package/dist/core/ResponseEngine.js +47 -0
- package/dist/core/ResponseEngine.js.map +1 -0
- package/dist/core/Route.d.ts +18 -12
- package/dist/core/Route.d.ts.map +1 -1
- package/dist/core/Route.js +15 -9
- package/dist/core/Route.js.map +1 -1
- package/dist/core/RoutingEngine.d.ts +38 -0
- package/dist/core/RoutingEngine.d.ts.map +1 -0
- package/dist/core/RoutingEngine.js +106 -0
- package/dist/core/RoutingEngine.js.map +1 -0
- package/dist/core/State.d.ts +15 -4
- package/dist/core/State.d.ts.map +1 -1
- package/dist/core/State.js +21 -2
- package/dist/core/State.js.map +1 -1
- package/dist/core/ToolExecutor.d.ts +29 -0
- package/dist/core/ToolExecutor.d.ts.map +1 -0
- package/dist/core/ToolExecutor.js +69 -0
- package/dist/core/ToolExecutor.js.map +1 -0
- package/dist/core/Transition.d.ts +5 -5
- package/dist/core/Transition.d.ts.map +1 -1
- package/dist/core/Transition.js.map +1 -1
- package/dist/index.d.ts +6 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -5
- package/dist/index.js.map +1 -1
- package/dist/providers/AnthropicProvider.d.ts.map +1 -1
- package/dist/providers/AnthropicProvider.js +10 -13
- package/dist/providers/AnthropicProvider.js.map +1 -1
- package/dist/providers/GeminiProvider.d.ts.map +1 -1
- package/dist/providers/GeminiProvider.js +12 -8
- package/dist/providers/GeminiProvider.js.map +1 -1
- package/dist/providers/OpenAIProvider.d.ts.map +1 -1
- package/dist/providers/OpenAIProvider.js +10 -53
- package/dist/providers/OpenAIProvider.js.map +1 -1
- package/dist/providers/OpenRouterProvider.d.ts.map +1 -1
- package/dist/providers/OpenRouterProvider.js +10 -53
- package/dist/providers/OpenRouterProvider.js.map +1 -1
- package/dist/types/agent.d.ts +13 -12
- package/dist/types/agent.d.ts.map +1 -1
- package/dist/types/ai.d.ts +8 -2
- package/dist/types/ai.d.ts.map +1 -1
- package/dist/types/history.d.ts +8 -0
- package/dist/types/history.d.ts.map +1 -1
- package/dist/types/index.d.ts +0 -3
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +0 -1
- package/dist/types/index.js.map +1 -1
- package/dist/types/route.d.ts +39 -4
- package/dist/types/route.d.ts.map +1 -1
- package/dist/types/routing.d.ts +16 -0
- package/dist/types/routing.d.ts.map +1 -0
- package/dist/types/routing.js +2 -0
- package/dist/types/routing.js.map +1 -0
- package/dist/types/schema.d.ts +22 -0
- package/dist/types/schema.d.ts.map +1 -0
- package/dist/types/schema.js +2 -0
- package/dist/types/schema.js.map +1 -0
- package/dist/types/session.d.ts +77 -0
- package/dist/types/session.d.ts.map +1 -0
- package/dist/types/session.js +138 -0
- package/dist/types/session.js.map +1 -0
- package/dist/types/tool.d.ts +11 -5
- package/dist/types/tool.d.ts.map +1 -1
- package/dist/utils/id.d.ts +0 -5
- package/dist/utils/id.d.ts.map +1 -1
- package/dist/utils/id.js +0 -9
- package/dist/utils/id.js.map +1 -1
- package/dist/utils/schema.d.ts +17 -0
- package/dist/utils/schema.d.ts.map +1 -0
- package/dist/utils/schema.js +27 -0
- package/dist/utils/schema.js.map +1 -0
- package/docs/ADAPTERS.md +83 -3
- package/docs/API_REFERENCE.md +329 -104
- package/docs/ARCHITECTURE.md +284 -286
- package/docs/CONSTRUCTOR_OPTIONS.md +192 -135
- package/docs/CONTEXT_MANAGEMENT.md +311 -28
- package/docs/CONTRIBUTING.md +1 -1
- package/docs/DOMAINS.md +61 -0
- package/docs/GETTING_STARTED.md +177 -88
- package/docs/PERSISTENCE.md +170 -23
- package/docs/README.md +7 -10
- package/examples/business-onboarding.ts +21 -9
- package/examples/company-qna-agent.ts +508 -0
- package/examples/declarative-agent.ts +143 -26
- package/examples/domain-scoping.ts +31 -10
- package/examples/extracted-data-modification.ts +415 -0
- package/examples/healthcare-agent.ts +194 -90
- package/examples/openai-agent.ts +67 -25
- package/examples/opensearch-persistence.ts +455 -151
- package/examples/persistent-onboarding.ts +162 -96
- package/examples/prisma-persistence.ts +371 -125
- package/examples/redis-persistence.ts +393 -23
- package/examples/rules-prohibitions.ts +32 -11
- package/examples/streaming-agent.ts +61 -13
- package/examples/travel-agent.ts +266 -133
- package/package.json +1 -1
- package/src/core/Agent.ts +668 -356
- package/src/core/Events.ts +12 -2
- package/src/core/PersistenceManager.ts +81 -0
- package/src/core/PromptComposer.ts +143 -0
- package/src/core/ResponseEngine.ts +82 -0
- package/src/core/Route.ts +32 -17
- package/src/core/RoutingEngine.ts +165 -0
- package/src/core/State.ts +55 -15
- package/src/core/ToolExecutor.ts +117 -0
- package/src/core/Transition.ts +5 -5
- package/src/index.ts +12 -21
- package/src/providers/AnthropicProvider.ts +10 -13
- package/src/providers/GeminiProvider.ts +12 -8
- package/src/providers/OpenAIProvider.ts +10 -56
- package/src/providers/OpenRouterProvider.ts +10 -56
- package/src/types/agent.ts +16 -13
- package/src/types/ai.ts +6 -2
- package/src/types/history.ts +8 -0
- package/src/types/index.ts +0 -11
- package/src/types/route.ts +41 -5
- package/src/types/routing.ts +18 -0
- package/src/types/schema.ts +23 -0
- package/src/types/session.ts +219 -0
- package/src/types/tool.ts +29 -7
- package/src/utils/id.ts +0 -10
- package/src/utils/schema.ts +32 -0
- package/dist/cjs/core/ConditionEvaluator.d.ts +0 -72
- package/dist/cjs/core/ConditionEvaluator.d.ts.map +0 -1
- package/dist/cjs/core/ConditionEvaluator.js +0 -272
- package/dist/cjs/core/ConditionEvaluator.js.map +0 -1
- package/dist/cjs/core/Observation.d.ts +0 -24
- package/dist/cjs/core/Observation.d.ts.map +0 -1
- package/dist/cjs/core/Observation.js +0 -39
- package/dist/cjs/core/Observation.js.map +0 -1
- package/dist/cjs/core/PreparationEngine.d.ts +0 -116
- package/dist/cjs/core/PreparationEngine.d.ts.map +0 -1
- package/dist/cjs/core/PreparationEngine.js +0 -353
- package/dist/cjs/core/PreparationEngine.js.map +0 -1
- package/dist/cjs/core/PromptBuilder.d.ts +0 -136
- package/dist/cjs/core/PromptBuilder.d.ts.map +0 -1
- package/dist/cjs/core/PromptBuilder.js +0 -421
- package/dist/cjs/core/PromptBuilder.js.map +0 -1
- package/dist/cjs/types/observation.d.ts +0 -27
- package/dist/cjs/types/observation.d.ts.map +0 -1
- package/dist/cjs/types/observation.js +0 -6
- package/dist/cjs/types/observation.js.map +0 -1
- package/dist/cjs/types/prompt.d.ts +0 -46
- package/dist/cjs/types/prompt.d.ts.map +0 -1
- package/dist/cjs/types/prompt.js +0 -19
- package/dist/cjs/types/prompt.js.map +0 -1
- package/dist/core/ConditionEvaluator.d.ts +0 -72
- package/dist/core/ConditionEvaluator.d.ts.map +0 -1
- package/dist/core/ConditionEvaluator.js +0 -268
- package/dist/core/ConditionEvaluator.js.map +0 -1
- package/dist/core/Observation.d.ts +0 -24
- package/dist/core/Observation.d.ts.map +0 -1
- package/dist/core/Observation.js +0 -35
- package/dist/core/Observation.js.map +0 -1
- package/dist/core/PreparationEngine.d.ts +0 -116
- package/dist/core/PreparationEngine.d.ts.map +0 -1
- package/dist/core/PreparationEngine.js +0 -349
- package/dist/core/PreparationEngine.js.map +0 -1
- package/dist/core/PromptBuilder.d.ts +0 -136
- package/dist/core/PromptBuilder.d.ts.map +0 -1
- package/dist/core/PromptBuilder.js +0 -417
- package/dist/core/PromptBuilder.js.map +0 -1
- package/dist/types/observation.d.ts +0 -27
- package/dist/types/observation.d.ts.map +0 -1
- package/dist/types/observation.js +0 -5
- package/dist/types/observation.js.map +0 -1
- package/dist/types/prompt.d.ts +0 -46
- package/dist/types/prompt.d.ts.map +0 -1
- package/dist/types/prompt.js +0 -16
- package/dist/types/prompt.js.map +0 -1
- package/docs/STRUCTURE.md +0 -58
- package/src/core/ConditionEvaluator.ts +0 -381
- package/src/core/Observation.ts +0 -47
- package/src/core/PreparationEngine.ts +0 -561
- package/src/core/PromptBuilder.ts +0 -617
- package/src/types/observation.ts +0 -29
- package/src/types/prompt.ts +0 -49
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Business Onboarding Example
|
|
3
|
+
* Updated for v2 architecture with session state management and schema-first data extraction
|
|
3
4
|
*
|
|
4
5
|
* Real-world example showing:
|
|
5
|
-
* - Complex multi-step onboarding flow
|
|
6
|
-
* - Tools with
|
|
7
|
-
* - Lifecycle hooks for persistence
|
|
8
|
-
* - Branching logic (physical vs online business)
|
|
9
|
-
* -
|
|
10
|
-
* - Agent caching with lifecycle hooks
|
|
6
|
+
* - Complex multi-step onboarding flow with schema-based data extraction
|
|
7
|
+
* - Tools with enhanced context access for automatic state management
|
|
8
|
+
* - Lifecycle hooks for data validation and persistence
|
|
9
|
+
* - Branching logic (physical vs online business) with skipIf conditions
|
|
10
|
+
* - Code-based state progression instead of fuzzy conditions
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
import {
|
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
EventSource,
|
|
18
18
|
createMessageEvent,
|
|
19
19
|
OpenAIProvider,
|
|
20
|
+
createSession,
|
|
20
21
|
type ToolContext,
|
|
21
22
|
} from "../src/index";
|
|
22
23
|
|
|
@@ -690,10 +691,21 @@ async function main() {
|
|
|
690
691
|
|
|
691
692
|
// Generate response (requires valid API key)
|
|
692
693
|
try {
|
|
693
|
-
|
|
694
|
+
// Initialize session state for multi-turn conversation
|
|
695
|
+
let session = createSession<OnboardingData>();
|
|
696
|
+
|
|
697
|
+
const response = await agent.respond({ history, session });
|
|
694
698
|
console.log("Agent:", response.message);
|
|
695
|
-
console.log("\nRoute:", response.
|
|
696
|
-
console.log("
|
|
699
|
+
console.log("\nRoute:", response.session?.currentRoute?.title);
|
|
700
|
+
console.log("Extracted:", response.session?.extracted);
|
|
701
|
+
|
|
702
|
+
// Update session with progress
|
|
703
|
+
session = response.session!;
|
|
704
|
+
|
|
705
|
+
console.log("\n✅ Session state benefits:");
|
|
706
|
+
console.log(" - Data extraction tracked across turns");
|
|
707
|
+
console.log(" - State progression managed automatically");
|
|
708
|
+
console.log(" - Always-on routing respects intent changes");
|
|
697
709
|
} catch (error: any) {
|
|
698
710
|
console.log("\n(Skipping AI response - requires valid API key)");
|
|
699
711
|
console.log("Error:", error.message);
|
|
@@ -0,0 +1,508 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Example: Company Q&A Agent (Stateless, Knowledge-Based)
|
|
3
|
+
*
|
|
4
|
+
* This demonstrates:
|
|
5
|
+
* 1. Schema-first architecture for stateless Q&A routes (no gatherSchema)
|
|
6
|
+
* 2. Tools for context enrichment (not data extraction)
|
|
7
|
+
* 3. Session state management even for stateless conversations
|
|
8
|
+
* 4. Always-on routing with context awareness
|
|
9
|
+
* 5. Three-phase pipeline: PREPARATION → ROUTING → RESPONSE
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import {
|
|
13
|
+
Agent,
|
|
14
|
+
createSession,
|
|
15
|
+
EventSource,
|
|
16
|
+
createMessageEvent,
|
|
17
|
+
EventKind,
|
|
18
|
+
} from "../src";
|
|
19
|
+
import type { Event } from "../src/types";
|
|
20
|
+
import type { ToolRef } from "../src/types/tool";
|
|
21
|
+
|
|
22
|
+
// ==============================================================================
|
|
23
|
+
// CONTEXT: Company Knowledge Base
|
|
24
|
+
// ==============================================================================
|
|
25
|
+
|
|
26
|
+
interface CompanyContext {
|
|
27
|
+
companyInfo: {
|
|
28
|
+
name: string;
|
|
29
|
+
founded: number;
|
|
30
|
+
employees: number;
|
|
31
|
+
headquarters: string;
|
|
32
|
+
};
|
|
33
|
+
products: Array<{
|
|
34
|
+
id: string;
|
|
35
|
+
name: string;
|
|
36
|
+
description: string;
|
|
37
|
+
price: string;
|
|
38
|
+
category: string;
|
|
39
|
+
}>;
|
|
40
|
+
policies: {
|
|
41
|
+
returnPolicy: string;
|
|
42
|
+
shippingPolicy: string;
|
|
43
|
+
warrantyPolicy: string;
|
|
44
|
+
};
|
|
45
|
+
faqs: Array<{
|
|
46
|
+
question: string;
|
|
47
|
+
answer: string;
|
|
48
|
+
category: string;
|
|
49
|
+
}>;
|
|
50
|
+
recentNews?: Array<{
|
|
51
|
+
title: string;
|
|
52
|
+
date: string;
|
|
53
|
+
summary: string;
|
|
54
|
+
}>;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// ==============================================================================
|
|
58
|
+
// TOOLS: Context Enrichment (PREPARATION Phase)
|
|
59
|
+
// ==============================================================================
|
|
60
|
+
|
|
61
|
+
// Tool: Fetch latest company news (context enrichment)
|
|
62
|
+
const fetchNewsTool: ToolRef<CompanyContext, [], void> = {
|
|
63
|
+
id: "fetch_news",
|
|
64
|
+
name: "Fetch Company News",
|
|
65
|
+
description: "Retrieve latest company news and updates",
|
|
66
|
+
handler: async (context) => {
|
|
67
|
+
// Simulate API call to news service
|
|
68
|
+
const news = [
|
|
69
|
+
{
|
|
70
|
+
title: "New Product Launch: Acme Widget Pro",
|
|
71
|
+
date: "2025-10-10",
|
|
72
|
+
summary: "We're excited to announce the Acme Widget Pro...",
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
title: "Company Expands to European Market",
|
|
76
|
+
date: "2025-10-01",
|
|
77
|
+
summary: "Acme Corp opens new offices in London and Berlin...",
|
|
78
|
+
},
|
|
79
|
+
];
|
|
80
|
+
|
|
81
|
+
console.log(`[Tool] Fetched ${news.length} news articles`);
|
|
82
|
+
|
|
83
|
+
return {
|
|
84
|
+
data: undefined,
|
|
85
|
+
contextUpdate: {
|
|
86
|
+
recentNews: news,
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
},
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
// Tool: Search knowledge base (context enrichment)
|
|
93
|
+
const searchKnowledgeTool: ToolRef<CompanyContext, [], string> = {
|
|
94
|
+
id: "search_knowledge",
|
|
95
|
+
name: "Search Knowledge Base",
|
|
96
|
+
description: "Search FAQs and documentation",
|
|
97
|
+
handler: async (context) => {
|
|
98
|
+
const { history } = context;
|
|
99
|
+
|
|
100
|
+
// Get last user message
|
|
101
|
+
const lastMessage = history
|
|
102
|
+
.filter(
|
|
103
|
+
(e) => e.kind === EventKind.MESSAGE && e.source === EventSource.CUSTOMER
|
|
104
|
+
)
|
|
105
|
+
.pop();
|
|
106
|
+
|
|
107
|
+
if (!lastMessage) {
|
|
108
|
+
return { data: "No query found" };
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const query = (lastMessage.data as any).message.toLowerCase();
|
|
112
|
+
|
|
113
|
+
// Simple keyword matching (in real app, use vector search)
|
|
114
|
+
const relevantFaqs = context.context.faqs.filter(
|
|
115
|
+
(faq) =>
|
|
116
|
+
faq.question.toLowerCase().includes(query) ||
|
|
117
|
+
faq.answer.toLowerCase().includes(query)
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
console.log(`[Tool] Found ${relevantFaqs.length} relevant FAQs`);
|
|
121
|
+
|
|
122
|
+
return {
|
|
123
|
+
data: relevantFaqs
|
|
124
|
+
.map((faq) => `Q: ${faq.question}\nA: ${faq.answer}`)
|
|
125
|
+
.join("\n\n"),
|
|
126
|
+
};
|
|
127
|
+
},
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
// ==============================================================================
|
|
131
|
+
// AGENT SETUP
|
|
132
|
+
// ==============================================================================
|
|
133
|
+
|
|
134
|
+
const agent = new Agent<CompanyContext>({
|
|
135
|
+
name: "Acme Support Agent",
|
|
136
|
+
goal: "Answer questions about Acme Corp and our products",
|
|
137
|
+
description:
|
|
138
|
+
"I'm here to help you learn about Acme Corp, our products, and policies",
|
|
139
|
+
personality:
|
|
140
|
+
"Friendly, helpful, and knowledgeable. Always professional but approachable.",
|
|
141
|
+
ai: null as any, // Replace with actual AI provider
|
|
142
|
+
|
|
143
|
+
// Initialize with company knowledge
|
|
144
|
+
context: {
|
|
145
|
+
companyInfo: {
|
|
146
|
+
name: "Acme Corporation",
|
|
147
|
+
founded: 2010,
|
|
148
|
+
employees: 500,
|
|
149
|
+
headquarters: "San Francisco, CA",
|
|
150
|
+
},
|
|
151
|
+
products: [
|
|
152
|
+
{
|
|
153
|
+
id: "widget-1",
|
|
154
|
+
name: "Acme Widget",
|
|
155
|
+
description: "Our flagship product for all your widget needs",
|
|
156
|
+
price: "$99.99",
|
|
157
|
+
category: "widgets",
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
id: "gadget-1",
|
|
161
|
+
name: "Acme Gadget",
|
|
162
|
+
description: "The revolutionary gadget that changed everything",
|
|
163
|
+
price: "$149.99",
|
|
164
|
+
category: "gadgets",
|
|
165
|
+
},
|
|
166
|
+
],
|
|
167
|
+
policies: {
|
|
168
|
+
returnPolicy: "30-day money-back guarantee, no questions asked",
|
|
169
|
+
shippingPolicy:
|
|
170
|
+
"Free shipping on orders over $50. 2-5 business days delivery",
|
|
171
|
+
warrantyPolicy: "1-year warranty on all products",
|
|
172
|
+
},
|
|
173
|
+
faqs: [
|
|
174
|
+
{
|
|
175
|
+
question: "What is your return policy?",
|
|
176
|
+
answer: "We offer a 30-day money-back guarantee on all products.",
|
|
177
|
+
category: "returns",
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
question: "Do you ship internationally?",
|
|
181
|
+
answer: "Yes, we ship to over 50 countries worldwide.",
|
|
182
|
+
category: "shipping",
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
question: "How long is the warranty?",
|
|
186
|
+
answer: "All products come with a 1-year manufacturer warranty.",
|
|
187
|
+
category: "warranty",
|
|
188
|
+
},
|
|
189
|
+
],
|
|
190
|
+
},
|
|
191
|
+
|
|
192
|
+
// Add domain terms for better understanding
|
|
193
|
+
terms: [
|
|
194
|
+
{
|
|
195
|
+
name: "Widget",
|
|
196
|
+
description: "Our core product line for task automation",
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
name: "Gadget",
|
|
200
|
+
description: "Advanced tools for power users",
|
|
201
|
+
},
|
|
202
|
+
],
|
|
203
|
+
|
|
204
|
+
// General guidelines (no tools attached - just behavioral)
|
|
205
|
+
guidelines: [
|
|
206
|
+
{
|
|
207
|
+
action: "Always be polite and professional",
|
|
208
|
+
enabled: true,
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
action:
|
|
212
|
+
"If you don't know the answer, admit it and offer to connect them with a human",
|
|
213
|
+
enabled: true,
|
|
214
|
+
},
|
|
215
|
+
{
|
|
216
|
+
action: "Provide specific, accurate information from the knowledge base",
|
|
217
|
+
enabled: true,
|
|
218
|
+
},
|
|
219
|
+
],
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
// ==============================================================================
|
|
223
|
+
// ROUTES: STATELESS Q&A ROUTES (Schema-First Architecture)
|
|
224
|
+
// ==============================================================================
|
|
225
|
+
|
|
226
|
+
// Route 1: Company Information (stateless - no data extraction)
|
|
227
|
+
const companyInfoRoute = agent.createRoute({
|
|
228
|
+
title: "Company Information",
|
|
229
|
+
description: "Answer general questions about Acme Corp",
|
|
230
|
+
conditions: [
|
|
231
|
+
"User asks about the company",
|
|
232
|
+
"Questions about company history, size, location",
|
|
233
|
+
"When was the company founded",
|
|
234
|
+
"How many employees",
|
|
235
|
+
"Where is the headquarters",
|
|
236
|
+
],
|
|
237
|
+
// NO gatherSchema - stateless Q&A route
|
|
238
|
+
// Just use initial state with chatState for response generation
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
// Initial state: Answer from knowledge base (no data gathering needed)
|
|
242
|
+
|
|
243
|
+
// Route 2: Product Information (stateless)
|
|
244
|
+
const productInfoRoute = agent.createRoute({
|
|
245
|
+
title: "Product Information",
|
|
246
|
+
description: "Answer questions about products",
|
|
247
|
+
conditions: [
|
|
248
|
+
"User asks about products",
|
|
249
|
+
"Questions about features, pricing, availability",
|
|
250
|
+
"What products do you offer",
|
|
251
|
+
"Tell me about your widgets",
|
|
252
|
+
],
|
|
253
|
+
// NO gatherSchema - just answering questions
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
// Initial state is enough - no transitions needed for simple Q&A
|
|
257
|
+
|
|
258
|
+
// Route 3: Policy Questions (stateless)
|
|
259
|
+
const policyRoute = agent.createRoute({
|
|
260
|
+
title: "Policy Information",
|
|
261
|
+
description: "Answer questions about company policies",
|
|
262
|
+
conditions: [
|
|
263
|
+
"User asks about policies",
|
|
264
|
+
"Return policy",
|
|
265
|
+
"Shipping information",
|
|
266
|
+
"Warranty questions",
|
|
267
|
+
],
|
|
268
|
+
// NO gatherSchema
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
// Initial state is enough - no extra setup needed
|
|
272
|
+
|
|
273
|
+
// Route 4: News & Updates (uses tool, but still stateless)
|
|
274
|
+
const newsRoute = agent.createRoute({
|
|
275
|
+
title: "Company News",
|
|
276
|
+
description: "Share latest company news and updates",
|
|
277
|
+
conditions: [
|
|
278
|
+
"User asks about news",
|
|
279
|
+
"What's new",
|
|
280
|
+
"Recent updates",
|
|
281
|
+
"Latest announcements",
|
|
282
|
+
],
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
// Add tool to initial state to fetch news
|
|
286
|
+
const fetchNews = newsRoute.initialState.transitionTo({
|
|
287
|
+
toolState: fetchNewsTool,
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
const shareNews = fetchNews.transitionTo({
|
|
291
|
+
chatState: "Share the latest company news from context",
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
// Route 5: General FAQ Search (uses tool)
|
|
295
|
+
const faqRoute = agent.createRoute({
|
|
296
|
+
title: "FAQ Search",
|
|
297
|
+
description: "Search FAQs for relevant answers",
|
|
298
|
+
conditions: [
|
|
299
|
+
"User has a question that might be in FAQs",
|
|
300
|
+
"How do I...",
|
|
301
|
+
"Can I...",
|
|
302
|
+
"Is there...",
|
|
303
|
+
],
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
const searchFaqs = faqRoute.initialState.transitionTo({
|
|
307
|
+
toolState: searchKnowledgeTool,
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
const provideFaqAnswer = searchFaqs.transitionTo({
|
|
311
|
+
chatState: "Provide answer based on FAQ search results",
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
// Route 6: Fallback (generic response)
|
|
315
|
+
const fallbackRoute = agent.createRoute({
|
|
316
|
+
title: "General Conversation",
|
|
317
|
+
description: "Handle general conversation or unclear questions",
|
|
318
|
+
conditions: [
|
|
319
|
+
"User message doesn't match other routes",
|
|
320
|
+
"Greetings",
|
|
321
|
+
"Small talk",
|
|
322
|
+
"Unclear intent",
|
|
323
|
+
],
|
|
324
|
+
});
|
|
325
|
+
|
|
326
|
+
// Initial state is enough for fallback conversations
|
|
327
|
+
|
|
328
|
+
// ==============================================================================
|
|
329
|
+
// USAGE EXAMPLES: Three-Phase Pipeline Demonstration
|
|
330
|
+
// ==============================================================================
|
|
331
|
+
|
|
332
|
+
async function exampleConversations() {
|
|
333
|
+
let session = createSession();
|
|
334
|
+
|
|
335
|
+
// =========================================================================
|
|
336
|
+
// Example 1: Simple company info question (stateless)
|
|
337
|
+
// =========================================================================
|
|
338
|
+
console.log("\n=== EXAMPLE 1: Company Info (Stateless Q&A) ===");
|
|
339
|
+
const history1: Event[] = [
|
|
340
|
+
createMessageEvent(
|
|
341
|
+
EventSource.CUSTOMER,
|
|
342
|
+
"User",
|
|
343
|
+
"How many employees does Acme have?"
|
|
344
|
+
),
|
|
345
|
+
];
|
|
346
|
+
|
|
347
|
+
const response1 = await agent.respond({ history: history1, session });
|
|
348
|
+
console.log("AI:", response1.message);
|
|
349
|
+
console.log("Route:", response1.session?.currentRoute?.title);
|
|
350
|
+
|
|
351
|
+
/*
|
|
352
|
+
* ARCHITECTURE FLOW:
|
|
353
|
+
* 1. PREPARATION: No tools needed for simple Q&A
|
|
354
|
+
* 2. ROUTING: Framework routes to "Company Information" (score: 95)
|
|
355
|
+
* 3. RESPONSE: AI answers from context knowledge
|
|
356
|
+
* - Route: "Company Information"
|
|
357
|
+
* - Session: Updated with route/state (even for stateless)
|
|
358
|
+
* - No data extraction (stateless route)
|
|
359
|
+
*/
|
|
360
|
+
|
|
361
|
+
// =========================================================================
|
|
362
|
+
// Example 2: Product question (stateless)
|
|
363
|
+
// =========================================================================
|
|
364
|
+
console.log("\n=== EXAMPLE 2: Product Info ===");
|
|
365
|
+
const history2: Event[] = [
|
|
366
|
+
createMessageEvent(
|
|
367
|
+
EventSource.CUSTOMER,
|
|
368
|
+
"User",
|
|
369
|
+
"What products do you offer?"
|
|
370
|
+
),
|
|
371
|
+
];
|
|
372
|
+
|
|
373
|
+
const response2 = await agent.respond({ history: history2, session });
|
|
374
|
+
console.log("AI:", response2.message);
|
|
375
|
+
console.log("Route:", response2.session?.currentRoute?.title);
|
|
376
|
+
// Expected: "We offer two main products: Acme Widget ($99.99)..."
|
|
377
|
+
// Route: "Product Information"
|
|
378
|
+
|
|
379
|
+
// =========================================================================
|
|
380
|
+
// Example 3: Policy question (stateless)
|
|
381
|
+
// =========================================================================
|
|
382
|
+
console.log("\n=== EXAMPLE 3: Policy Question ===");
|
|
383
|
+
const history3: Event[] = [
|
|
384
|
+
createMessageEvent(
|
|
385
|
+
EventSource.CUSTOMER,
|
|
386
|
+
"User",
|
|
387
|
+
"What's your return policy?"
|
|
388
|
+
),
|
|
389
|
+
];
|
|
390
|
+
|
|
391
|
+
const response3 = await agent.respond({ history: history3, session });
|
|
392
|
+
console.log("AI:", response3.message);
|
|
393
|
+
console.log("Route:", response3.session?.currentRoute?.title);
|
|
394
|
+
// Expected: "We offer a 30-day money-back guarantee..."
|
|
395
|
+
// Route: "Policy Information"
|
|
396
|
+
|
|
397
|
+
// =========================================================================
|
|
398
|
+
// Example 4: News request (tool execution, but still stateless)
|
|
399
|
+
// =========================================================================
|
|
400
|
+
console.log("\n=== EXAMPLE 4: Latest News ===");
|
|
401
|
+
const history4: Event[] = [
|
|
402
|
+
createMessageEvent(EventSource.CUSTOMER, "User", "What's new at Acme?"),
|
|
403
|
+
];
|
|
404
|
+
|
|
405
|
+
const response4 = await agent.respond({ history: history4, session });
|
|
406
|
+
console.log("AI:", response4.message);
|
|
407
|
+
console.log("Route:", response4.session?.currentRoute?.title);
|
|
408
|
+
// Tool fetches news → Updates context → AI responds with news
|
|
409
|
+
// Route: "Company News"
|
|
410
|
+
// NO data extraction - tool just enriches context
|
|
411
|
+
|
|
412
|
+
// =========================================================================
|
|
413
|
+
// Example 5: Multi-turn conversation (context maintained)
|
|
414
|
+
// =========================================================================
|
|
415
|
+
console.log("\n=== EXAMPLE 5: Multi-turn ===");
|
|
416
|
+
|
|
417
|
+
// Turn 1
|
|
418
|
+
const turn1: Event[] = [
|
|
419
|
+
createMessageEvent(
|
|
420
|
+
EventSource.CUSTOMER,
|
|
421
|
+
"User",
|
|
422
|
+
"Tell me about the Acme Widget"
|
|
423
|
+
),
|
|
424
|
+
];
|
|
425
|
+
const resp1 = await agent.respond({ history: turn1, session });
|
|
426
|
+
console.log("User: Tell me about the Acme Widget");
|
|
427
|
+
console.log("AI:", resp1.message);
|
|
428
|
+
|
|
429
|
+
// Turn 2 - follow-up question
|
|
430
|
+
const turn2: Event[] = [
|
|
431
|
+
...turn1,
|
|
432
|
+
createMessageEvent(EventSource.AI_AGENT, "Agent", resp1.message),
|
|
433
|
+
createMessageEvent(EventSource.CUSTOMER, "User", "How much does it cost?"),
|
|
434
|
+
];
|
|
435
|
+
const resp2 = await agent.respond({
|
|
436
|
+
history: turn2,
|
|
437
|
+
session: resp1.session, // Pass previous session
|
|
438
|
+
});
|
|
439
|
+
console.log("User: How much does it cost?");
|
|
440
|
+
console.log("AI:", resp2.message);
|
|
441
|
+
// AI understands "it" refers to Acme Widget from context
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
// ==============================================================================
|
|
445
|
+
// KEY TAKEAWAYS FOR Q&A USE CASES
|
|
446
|
+
// ==============================================================================
|
|
447
|
+
|
|
448
|
+
/*
|
|
449
|
+
* 1. NO STATE MACHINES REQUIRED
|
|
450
|
+
* - Just use the initial state with a chatState description
|
|
451
|
+
* - No gather, no skipIf, no state transitions
|
|
452
|
+
* - Perfect for stateless question-answering
|
|
453
|
+
*
|
|
454
|
+
* 2. ROUTING STILL WORKS
|
|
455
|
+
* - Framework routes to most relevant Q&A route
|
|
456
|
+
* - Always-on routing handles topic switches
|
|
457
|
+
* - Conditions guide the AI to the right knowledge domain
|
|
458
|
+
*
|
|
459
|
+
* 3. TOOLS FOR CONTEXT ENRICHMENT
|
|
460
|
+
* - Tools fetch additional data (news, search results)
|
|
461
|
+
* - Updates context (not extracted data)
|
|
462
|
+
* - AI uses enriched context to answer
|
|
463
|
+
*
|
|
464
|
+
* 4. KNOWLEDGE IN CONTEXT
|
|
465
|
+
* - Store company knowledge in context
|
|
466
|
+
* - Use contextProvider for always-fresh data
|
|
467
|
+
* - Tools can augment context at runtime
|
|
468
|
+
*
|
|
469
|
+
* 5. MIX STATEFUL & STATELESS
|
|
470
|
+
* - Have Q&A routes (stateless)
|
|
471
|
+
* - AND booking/onboarding routes (stateful)
|
|
472
|
+
* - Framework handles both seamlessly
|
|
473
|
+
*
|
|
474
|
+
* 6. GUIDELINES FOR BEHAVIOR
|
|
475
|
+
* - Use guidelines for general behavioral rules
|
|
476
|
+
* - No need for complex state machines for simple policies
|
|
477
|
+
* - Keep it simple!
|
|
478
|
+
*
|
|
479
|
+
* ARCHITECTURE FOR Q&A:
|
|
480
|
+
*
|
|
481
|
+
* User Question
|
|
482
|
+
* ↓
|
|
483
|
+
* Routing (score all Q&A routes)
|
|
484
|
+
* ↓
|
|
485
|
+
* Tool Execution (if needed - fetch data)
|
|
486
|
+
* ↓
|
|
487
|
+
* Response (AI answers from context)
|
|
488
|
+
* ↓
|
|
489
|
+
* Done (no state tracking needed)
|
|
490
|
+
*
|
|
491
|
+
* vs. STATEFUL FLOWS (booking, onboarding):
|
|
492
|
+
*
|
|
493
|
+
* User Intent
|
|
494
|
+
* ↓
|
|
495
|
+
* Routing
|
|
496
|
+
* ↓
|
|
497
|
+
* State Machine (gather data step-by-step)
|
|
498
|
+
* ↓
|
|
499
|
+
* Tools (validate/enrich extracted data)
|
|
500
|
+
* ↓
|
|
501
|
+
* Response (continue conversation)
|
|
502
|
+
* ↓
|
|
503
|
+
* Track Session (extracted data, current state)
|
|
504
|
+
*/
|
|
505
|
+
|
|
506
|
+
if (require.main === module) {
|
|
507
|
+
exampleConversations().catch(console.error);
|
|
508
|
+
}
|