@falai/agent 0.3.0 → 0.3.11
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 +257 -24
- package/dist/cjs/core/Agent.d.ts +37 -0
- package/dist/cjs/core/Agent.d.ts.map +1 -1
- package/dist/cjs/core/Agent.js +167 -1
- package/dist/cjs/core/Agent.js.map +1 -1
- package/dist/cjs/core/DomainRegistry.d.ts +10 -0
- package/dist/cjs/core/DomainRegistry.d.ts.map +1 -1
- package/dist/cjs/core/DomainRegistry.js +25 -0
- package/dist/cjs/core/DomainRegistry.js.map +1 -1
- package/dist/cjs/core/PromptBuilder.d.ts +9 -1
- package/dist/cjs/core/PromptBuilder.d.ts.map +1 -1
- package/dist/cjs/core/PromptBuilder.js +49 -2
- package/dist/cjs/core/PromptBuilder.js.map +1 -1
- package/dist/cjs/core/Route.d.ts +16 -0
- package/dist/cjs/core/Route.d.ts.map +1 -1
- package/dist/cjs/core/Route.js +22 -0
- package/dist/cjs/core/Route.js.map +1 -1
- package/dist/cjs/index.d.ts +2 -0
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +3 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/providers/AnthropicProvider.d.ts +43 -0
- package/dist/cjs/providers/AnthropicProvider.d.ts.map +1 -0
- package/dist/cjs/providers/AnthropicProvider.js +328 -0
- package/dist/cjs/providers/AnthropicProvider.js.map +1 -0
- package/dist/cjs/providers/GeminiProvider.d.ts +4 -1
- package/dist/cjs/providers/GeminiProvider.d.ts.map +1 -1
- package/dist/cjs/providers/GeminiProvider.js +96 -0
- package/dist/cjs/providers/GeminiProvider.js.map +1 -1
- package/dist/cjs/providers/OpenAIProvider.d.ts +4 -1
- package/dist/cjs/providers/OpenAIProvider.d.ts.map +1 -1
- package/dist/cjs/providers/OpenAIProvider.js +115 -0
- package/dist/cjs/providers/OpenAIProvider.js.map +1 -1
- package/dist/cjs/providers/OpenRouterProvider.d.ts +4 -1
- package/dist/cjs/providers/OpenRouterProvider.d.ts.map +1 -1
- package/dist/cjs/providers/OpenRouterProvider.js +115 -0
- package/dist/cjs/providers/OpenRouterProvider.js.map +1 -1
- package/dist/cjs/providers/index.d.ts +13 -0
- package/dist/cjs/providers/index.d.ts.map +1 -0
- package/dist/cjs/providers/index.js +16 -0
- package/dist/cjs/providers/index.js.map +1 -0
- package/dist/cjs/types/ai.d.ts +28 -0
- package/dist/cjs/types/ai.d.ts.map +1 -1
- package/dist/cjs/types/route.d.ts +6 -0
- package/dist/cjs/types/route.d.ts.map +1 -1
- package/dist/core/Agent.d.ts +37 -0
- package/dist/core/Agent.d.ts.map +1 -1
- package/dist/core/Agent.js +167 -1
- package/dist/core/Agent.js.map +1 -1
- package/dist/core/DomainRegistry.d.ts +10 -0
- package/dist/core/DomainRegistry.d.ts.map +1 -1
- package/dist/core/DomainRegistry.js +25 -0
- package/dist/core/DomainRegistry.js.map +1 -1
- package/dist/core/PromptBuilder.d.ts +9 -1
- package/dist/core/PromptBuilder.d.ts.map +1 -1
- package/dist/core/PromptBuilder.js +49 -2
- package/dist/core/PromptBuilder.js.map +1 -1
- package/dist/core/Route.d.ts +16 -0
- package/dist/core/Route.d.ts.map +1 -1
- package/dist/core/Route.js +22 -0
- package/dist/core/Route.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/providers/AnthropicProvider.d.ts +43 -0
- package/dist/providers/AnthropicProvider.d.ts.map +1 -0
- package/dist/providers/AnthropicProvider.js +321 -0
- package/dist/providers/AnthropicProvider.js.map +1 -0
- package/dist/providers/GeminiProvider.d.ts +4 -1
- package/dist/providers/GeminiProvider.d.ts.map +1 -1
- package/dist/providers/GeminiProvider.js +96 -0
- package/dist/providers/GeminiProvider.js.map +1 -1
- package/dist/providers/OpenAIProvider.d.ts +4 -1
- package/dist/providers/OpenAIProvider.d.ts.map +1 -1
- package/dist/providers/OpenAIProvider.js +115 -0
- package/dist/providers/OpenAIProvider.js.map +1 -1
- package/dist/providers/OpenRouterProvider.d.ts +4 -1
- package/dist/providers/OpenRouterProvider.d.ts.map +1 -1
- package/dist/providers/OpenRouterProvider.js +115 -0
- package/dist/providers/OpenRouterProvider.js.map +1 -1
- package/dist/providers/index.d.ts +13 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/index.js +9 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/types/ai.d.ts +28 -0
- package/dist/types/ai.d.ts.map +1 -1
- package/dist/types/route.d.ts +6 -0
- package/dist/types/route.d.ts.map +1 -1
- package/docs/API_REFERENCE.md +357 -2
- package/docs/CONSTRUCTOR_OPTIONS.md +178 -37
- package/docs/GETTING_STARTED.md +10 -2
- package/docs/PROVIDERS.md +139 -2
- package/examples/business-onboarding.ts +708 -0
- package/examples/declarative-agent.ts +1 -1
- package/examples/domain-scoping.ts +267 -0
- package/examples/healthcare-agent.ts +4 -4
- package/examples/openai-agent.ts +6 -4
- package/examples/rules-prohibitions.ts +258 -0
- package/examples/streaming-agent.ts +371 -0
- package/examples/travel-agent.ts +7 -4
- package/package.json +2 -1
- package/src/core/Agent.ts +220 -1
- package/src/core/DomainRegistry.ts +30 -0
- package/src/core/PromptBuilder.ts +70 -3
- package/src/core/Route.ts +28 -0
- package/src/index.ts +2 -0
- package/src/providers/AnthropicProvider.ts +467 -0
- package/src/providers/GeminiProvider.ts +135 -0
- package/src/providers/OpenAIProvider.ts +157 -0
- package/src/providers/OpenRouterProvider.ts +157 -0
- package/src/providers/index.ts +16 -0
- package/src/types/ai.ts +32 -0
- package/src/types/route.ts +6 -0
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Domain Scoping Example
|
|
3
|
+
*
|
|
4
|
+
* This example demonstrates how to use domain scoping to restrict which tools
|
|
5
|
+
* are available in different conversation routes for security and clarity.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { Agent, createMessageEvent, EventSource } from "../src/index";
|
|
9
|
+
import { OpenRouterProvider } from "../src/providers";
|
|
10
|
+
|
|
11
|
+
// Initialize AI provider
|
|
12
|
+
const ai = new OpenRouterProvider({
|
|
13
|
+
apiKey: process.env.OPENROUTER_API_KEY || "your-api-key-here",
|
|
14
|
+
model: "google/gemini-2.0-flash-exp",
|
|
15
|
+
backupModels: ["anthropic/claude-sonnet-4-5"],
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
// Create agent
|
|
19
|
+
const agent = new Agent({
|
|
20
|
+
name: "Multi-Domain Assistant",
|
|
21
|
+
description:
|
|
22
|
+
"An assistant that handles different tasks with domain-scoped tools",
|
|
23
|
+
ai,
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
// Register different domains with their tools
|
|
27
|
+
agent.addDomain("scraping", {
|
|
28
|
+
scrapeSite: async (url: string) => {
|
|
29
|
+
console.log(`[Scraping] Scraping site: ${url}`);
|
|
30
|
+
return { success: true, data: "Scraped content..." };
|
|
31
|
+
},
|
|
32
|
+
extractData: async (html: string, selector: string) => {
|
|
33
|
+
console.log(`[Scraping] Extracting data with selector: ${selector}`);
|
|
34
|
+
return { elements: [] };
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
agent.addDomain("calendar", {
|
|
39
|
+
scheduleEvent: async (date: Date, title: string, description?: string) => {
|
|
40
|
+
console.log(`[Calendar] Scheduling event: ${title} on ${date}`);
|
|
41
|
+
return { eventId: "evt_123", success: true };
|
|
42
|
+
},
|
|
43
|
+
listEvents: async (startDate: Date, endDate: Date) => {
|
|
44
|
+
console.log(`[Calendar] Listing events from ${startDate} to ${endDate}`);
|
|
45
|
+
return { events: [] };
|
|
46
|
+
},
|
|
47
|
+
cancelEvent: async (eventId: string) => {
|
|
48
|
+
console.log(`[Calendar] Cancelling event: ${eventId}`);
|
|
49
|
+
return { success: true };
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
agent.addDomain("payment", {
|
|
54
|
+
processPayment: async (amount: number, currency: string) => {
|
|
55
|
+
console.log(`[Payment] Processing payment: ${amount} ${currency}`);
|
|
56
|
+
return { transactionId: "txn_456", success: true };
|
|
57
|
+
},
|
|
58
|
+
refund: async (transactionId: string) => {
|
|
59
|
+
console.log(`[Payment] Processing refund for: ${transactionId}`);
|
|
60
|
+
return { success: true };
|
|
61
|
+
},
|
|
62
|
+
checkBalance: async () => {
|
|
63
|
+
console.log(`[Payment] Checking balance`);
|
|
64
|
+
return { balance: 1000, currency: "USD" };
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
agent.addDomain("analytics", {
|
|
69
|
+
trackEvent: async (
|
|
70
|
+
eventName: string,
|
|
71
|
+
properties: Record<string, unknown>
|
|
72
|
+
) => {
|
|
73
|
+
console.log(`[Analytics] Tracking event: ${eventName}`, properties);
|
|
74
|
+
return { success: true };
|
|
75
|
+
},
|
|
76
|
+
generateReport: async (
|
|
77
|
+
reportType: string,
|
|
78
|
+
dateRange: { start: Date; end: Date }
|
|
79
|
+
) => {
|
|
80
|
+
console.log(`[Analytics] Generating ${reportType} report`);
|
|
81
|
+
return { report: {} };
|
|
82
|
+
},
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
// Create routes with domain scoping
|
|
86
|
+
agent.createRoute({
|
|
87
|
+
title: "Data Collection",
|
|
88
|
+
description: "Collect and process web data",
|
|
89
|
+
conditions: ["User wants to scrape or extract data from websites"],
|
|
90
|
+
domains: ["scraping"], // ✅ Only scraping tools available
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
agent.createRoute({
|
|
94
|
+
title: "Schedule Meeting",
|
|
95
|
+
description: "Book and manage appointments",
|
|
96
|
+
conditions: ["User wants to schedule, view, or cancel events"],
|
|
97
|
+
domains: ["calendar"], // ✅ Only calendar tools available
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
agent.createRoute({
|
|
101
|
+
title: "Checkout Process",
|
|
102
|
+
description: "Process purchases and payments",
|
|
103
|
+
conditions: ["User wants to make a purchase or payment"],
|
|
104
|
+
domains: ["payment", "analytics"], // ✅ Multiple domains allowed
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
agent.createRoute({
|
|
108
|
+
title: "Customer Support",
|
|
109
|
+
description: "Answer general questions and provide help",
|
|
110
|
+
conditions: ["User has general questions or needs support"],
|
|
111
|
+
domains: [], // ✅ No tools available (conversation only)
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
agent.createRoute({
|
|
115
|
+
title: "Admin Support",
|
|
116
|
+
description: "Administrative tasks with full access",
|
|
117
|
+
conditions: ["User is admin and needs full system access"],
|
|
118
|
+
// domains not specified = all domains available
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
// Example conversations
|
|
122
|
+
async function demonstrateScoping() {
|
|
123
|
+
console.log("\n=== Domain Scoping Demo ===\n");
|
|
124
|
+
|
|
125
|
+
// Example 1: Data Collection route - only scraping tools available
|
|
126
|
+
console.log("1️⃣ Example: User wants to scrape data");
|
|
127
|
+
const history1 = [
|
|
128
|
+
createMessageEvent(
|
|
129
|
+
EventSource.CUSTOMER,
|
|
130
|
+
"Alice",
|
|
131
|
+
"Can you scrape the homepage of example.com?"
|
|
132
|
+
),
|
|
133
|
+
];
|
|
134
|
+
|
|
135
|
+
const response1 = await agent.respond({ history: history1 });
|
|
136
|
+
console.log(`Route chosen: ${response1.route?.title}`);
|
|
137
|
+
console.log(`Available tools in this route: scraping only`);
|
|
138
|
+
console.log(`Response: ${response1.message}\n`);
|
|
139
|
+
|
|
140
|
+
// Example 2: Schedule Meeting route - only calendar tools available
|
|
141
|
+
console.log("2️⃣ Example: User wants to schedule a meeting");
|
|
142
|
+
const history2 = [
|
|
143
|
+
createMessageEvent(
|
|
144
|
+
EventSource.CUSTOMER,
|
|
145
|
+
"Bob",
|
|
146
|
+
"Schedule a meeting for tomorrow at 2pm"
|
|
147
|
+
),
|
|
148
|
+
];
|
|
149
|
+
|
|
150
|
+
const response2 = await agent.respond({ history: history2 });
|
|
151
|
+
console.log(`Route chosen: ${response2.route?.title}`);
|
|
152
|
+
console.log(`Available tools in this route: calendar only`);
|
|
153
|
+
console.log(`Response: ${response2.message}\n`);
|
|
154
|
+
|
|
155
|
+
// Example 3: Customer Support route - NO tools available
|
|
156
|
+
console.log("3️⃣ Example: User has a general question");
|
|
157
|
+
const history3 = [
|
|
158
|
+
createMessageEvent(
|
|
159
|
+
EventSource.CUSTOMER,
|
|
160
|
+
"Charlie",
|
|
161
|
+
"What are your business hours?"
|
|
162
|
+
),
|
|
163
|
+
];
|
|
164
|
+
|
|
165
|
+
const response3 = await agent.respond({ history: history3 });
|
|
166
|
+
console.log(`Route chosen: ${response3.route?.title}`);
|
|
167
|
+
console.log(`Available tools in this route: none (conversation only)`);
|
|
168
|
+
console.log(`Response: ${response3.message}\n`);
|
|
169
|
+
|
|
170
|
+
// Example 4: Admin Support route - ALL tools available (for demo purposes)
|
|
171
|
+
console.log("4️⃣ Example: Admin needs full access");
|
|
172
|
+
const history4 = [
|
|
173
|
+
createMessageEvent(
|
|
174
|
+
EventSource.CUSTOMER,
|
|
175
|
+
"Admin",
|
|
176
|
+
"I need to generate a report and process a refund"
|
|
177
|
+
),
|
|
178
|
+
];
|
|
179
|
+
|
|
180
|
+
const response4 = await agent.respond({ history: history4 });
|
|
181
|
+
console.log(`Route chosen: ${response4.route?.title}`);
|
|
182
|
+
console.log(`Available tools in this route: all domains`);
|
|
183
|
+
console.log(`Response: ${response4.message}\n`);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Benefits demonstration
|
|
187
|
+
console.log(`
|
|
188
|
+
🔒 Security Benefits:
|
|
189
|
+
- Customer Support route cannot accidentally call payment.processPayment()
|
|
190
|
+
- Data Collection route cannot access calendar.scheduleEvent()
|
|
191
|
+
- Each route has minimum necessary permissions
|
|
192
|
+
|
|
193
|
+
⚡ Performance Benefits:
|
|
194
|
+
- AI only sees relevant tools for each route
|
|
195
|
+
- Faster decision making with reduced context
|
|
196
|
+
- Clearer intent and fewer errors
|
|
197
|
+
|
|
198
|
+
🎯 Clarity Benefits:
|
|
199
|
+
- Routes clearly document their capabilities
|
|
200
|
+
- Easy to audit what each route can do
|
|
201
|
+
- Better debugging when tools are called
|
|
202
|
+
`);
|
|
203
|
+
|
|
204
|
+
// Inspect route configurations
|
|
205
|
+
console.log("\n📋 Route Configurations:\n");
|
|
206
|
+
for (const route of agent.getRoutes()) {
|
|
207
|
+
const domains = route.getDomains();
|
|
208
|
+
const domainsText =
|
|
209
|
+
domains === undefined
|
|
210
|
+
? "all domains"
|
|
211
|
+
: domains.length === 0
|
|
212
|
+
? "no tools (conversation only)"
|
|
213
|
+
: domains.join(", ");
|
|
214
|
+
|
|
215
|
+
console.log(`• ${route.title}: ${domainsText}`);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// Validate tool calls (example helper function)
|
|
219
|
+
function validateToolCall(toolName: string, routeTitle: string): boolean {
|
|
220
|
+
const route = agent.getRoutes().find((r) => r.title === routeTitle);
|
|
221
|
+
if (!route) return false;
|
|
222
|
+
|
|
223
|
+
const allowedDomains = route.getDomains();
|
|
224
|
+
|
|
225
|
+
// If undefined, all domains allowed
|
|
226
|
+
if (allowedDomains === undefined) return true;
|
|
227
|
+
|
|
228
|
+
// If empty array, no tools allowed
|
|
229
|
+
if (allowedDomains.length === 0) return false;
|
|
230
|
+
|
|
231
|
+
// Check if tool's domain is in allowed list
|
|
232
|
+
const [domain] = toolName.split(".");
|
|
233
|
+
return allowedDomains.includes(domain);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
console.log("\n✅ Validation Examples:");
|
|
237
|
+
console.log(
|
|
238
|
+
`- scraping.scrapeSite in "Data Collection": ${validateToolCall(
|
|
239
|
+
"scraping.scrapeSite",
|
|
240
|
+
"Data Collection"
|
|
241
|
+
)}`
|
|
242
|
+
);
|
|
243
|
+
console.log(
|
|
244
|
+
`- calendar.scheduleEvent in "Data Collection": ${validateToolCall(
|
|
245
|
+
"calendar.scheduleEvent",
|
|
246
|
+
"Data Collection"
|
|
247
|
+
)}`
|
|
248
|
+
);
|
|
249
|
+
console.log(
|
|
250
|
+
`- payment.processPayment in "Customer Support": ${validateToolCall(
|
|
251
|
+
"payment.processPayment",
|
|
252
|
+
"Customer Support"
|
|
253
|
+
)}`
|
|
254
|
+
);
|
|
255
|
+
console.log(
|
|
256
|
+
`- analytics.trackEvent in "Admin Support": ${validateToolCall(
|
|
257
|
+
"analytics.trackEvent",
|
|
258
|
+
"Admin Support"
|
|
259
|
+
)}`
|
|
260
|
+
);
|
|
261
|
+
|
|
262
|
+
// Run demonstration
|
|
263
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
264
|
+
demonstrateScoping().catch(console.error);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
export { agent };
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import {
|
|
6
6
|
Agent,
|
|
7
7
|
defineTool,
|
|
8
|
-
|
|
8
|
+
AnthropicProvider,
|
|
9
9
|
END_ROUTE,
|
|
10
10
|
EventSource,
|
|
11
11
|
createMessageEvent,
|
|
@@ -63,9 +63,9 @@ const getLabResults = defineTool<HealthcareContext, [], object>(
|
|
|
63
63
|
);
|
|
64
64
|
|
|
65
65
|
async function createHealthcareAgent() {
|
|
66
|
-
const provider = new
|
|
67
|
-
apiKey: process.env.
|
|
68
|
-
model: "
|
|
66
|
+
const provider = new AnthropicProvider({
|
|
67
|
+
apiKey: process.env.ANTHROPIC_API_KEY || "test-key",
|
|
68
|
+
model: "claude-sonnet-4-5",
|
|
69
69
|
});
|
|
70
70
|
|
|
71
71
|
const agent = new Agent<HealthcareContext>({
|
package/examples/openai-agent.ts
CHANGED
|
@@ -108,10 +108,12 @@ async function main() {
|
|
|
108
108
|
chatState: "Ask which city they want weather for",
|
|
109
109
|
});
|
|
110
110
|
|
|
111
|
-
const fetchWeather = askLocation.transitionTo(
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
111
|
+
const fetchWeather = askLocation.transitionTo(
|
|
112
|
+
{
|
|
113
|
+
toolState: getWeather,
|
|
114
|
+
},
|
|
115
|
+
"User provides a city name"
|
|
116
|
+
);
|
|
115
117
|
|
|
116
118
|
const showWeather = fetchWeather.transitionTo({
|
|
117
119
|
chatState:
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rules & Prohibitions Example
|
|
3
|
+
*
|
|
4
|
+
* Demonstrates how to use rules and prohibitions to control agent behavior
|
|
5
|
+
* in different conversation routes (e.g., WhatsApp bot with different styles)
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { Agent, createMessageEvent, EventSource } from "../src/index";
|
|
9
|
+
import { AnthropicProvider } from "../src/providers";
|
|
10
|
+
|
|
11
|
+
// Initialize AI provider
|
|
12
|
+
const ai = new AnthropicProvider({
|
|
13
|
+
apiKey: process.env.ANTHROPIC_API_KEY || "your-api-key-here",
|
|
14
|
+
model: "claude-sonnet-4-5",
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
// Create WhatsApp support bot with different styles per route
|
|
18
|
+
const agent = new Agent({
|
|
19
|
+
name: "SupportBot",
|
|
20
|
+
description: "Customer support assistant for WhatsApp",
|
|
21
|
+
ai,
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
// Route 1: Quick Support - Short, direct messages
|
|
25
|
+
agent.createRoute({
|
|
26
|
+
title: "Quick Support",
|
|
27
|
+
description: "Fast answers for common questions",
|
|
28
|
+
conditions: ["User has a simple question", "User wants quick help"],
|
|
29
|
+
rules: [
|
|
30
|
+
"Keep messages extremely short (1-2 lines maximum)",
|
|
31
|
+
"Use bullet points for lists",
|
|
32
|
+
"Maximum 1 emoji per message 👍",
|
|
33
|
+
"Be direct and to the point",
|
|
34
|
+
],
|
|
35
|
+
prohibitions: [
|
|
36
|
+
"Never send long paragraphs",
|
|
37
|
+
"Do not over-explain",
|
|
38
|
+
"Never use more than 2 emojis",
|
|
39
|
+
"Do not ask follow-up questions unless necessary",
|
|
40
|
+
],
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
// Route 2: Sales Consultation - Conversational, engaging
|
|
44
|
+
agent.createRoute({
|
|
45
|
+
title: "Sales Consultation",
|
|
46
|
+
description: "Help customer discover needs and present solutions",
|
|
47
|
+
conditions: [
|
|
48
|
+
"User is interested in buying",
|
|
49
|
+
"User wants product information",
|
|
50
|
+
],
|
|
51
|
+
rules: [
|
|
52
|
+
"Ask open-ended questions to discover needs",
|
|
53
|
+
"Use storytelling when presenting solutions",
|
|
54
|
+
"Emoji to reinforce positive emotions 😊✨",
|
|
55
|
+
"Present value before mentioning price",
|
|
56
|
+
"Make customer feel special and understood",
|
|
57
|
+
],
|
|
58
|
+
prohibitions: [
|
|
59
|
+
"Never talk about price before showing value",
|
|
60
|
+
"Do not pressure or push",
|
|
61
|
+
"Avoid technical jargon",
|
|
62
|
+
"Never send more than 2 messages without waiting for response",
|
|
63
|
+
"Do not make promises you cannot keep",
|
|
64
|
+
],
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
// Route 3: Technical Support - Detailed, step-by-step
|
|
68
|
+
agent.createRoute({
|
|
69
|
+
title: "Technical Support",
|
|
70
|
+
description: "Help with technical issues and troubleshooting",
|
|
71
|
+
conditions: ["User has technical problem", "User needs step-by-step help"],
|
|
72
|
+
rules: [
|
|
73
|
+
"Provide clear, numbered steps",
|
|
74
|
+
"Use simple language for technical concepts",
|
|
75
|
+
"Confirm understanding after each major step",
|
|
76
|
+
"Offer screenshots or visual aids when helpful",
|
|
77
|
+
"Be patient and thorough",
|
|
78
|
+
],
|
|
79
|
+
prohibitions: [
|
|
80
|
+
"Never skip steps or assume knowledge",
|
|
81
|
+
"Do not use excessive technical terms without explanation",
|
|
82
|
+
"Never blame the user for the issue",
|
|
83
|
+
"Do not rush through explanations",
|
|
84
|
+
],
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
// Route 4: Emergency Support - Calm, reassuring, action-oriented
|
|
88
|
+
agent.createRoute({
|
|
89
|
+
title: "Emergency Support",
|
|
90
|
+
description: "Handle urgent customer issues",
|
|
91
|
+
conditions: ["Customer is frustrated", "Urgent issue", "Service down"],
|
|
92
|
+
rules: [
|
|
93
|
+
"Acknowledge the urgency immediately",
|
|
94
|
+
"Express empathy and understanding",
|
|
95
|
+
"Provide concrete next steps",
|
|
96
|
+
"Set clear expectations on resolution time",
|
|
97
|
+
"Keep customer updated",
|
|
98
|
+
],
|
|
99
|
+
prohibitions: [
|
|
100
|
+
"Never downplay the customer's concern",
|
|
101
|
+
"Do not use emojis (keep it professional)",
|
|
102
|
+
'Never say "calm down" or similar dismissive phrases',
|
|
103
|
+
"Do not transfer without explaining why",
|
|
104
|
+
"Never make excuses or blame others",
|
|
105
|
+
],
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
// Route 5: General Chat - Friendly, casual, helpful
|
|
109
|
+
agent.createRoute({
|
|
110
|
+
title: "General Chat",
|
|
111
|
+
description: "Casual conversation and general questions",
|
|
112
|
+
conditions: ["User is just chatting", "Greeting", "General question"],
|
|
113
|
+
rules: [
|
|
114
|
+
"Be friendly and conversational",
|
|
115
|
+
"Use emojis naturally 😊",
|
|
116
|
+
"Mirror the customer's tone and energy",
|
|
117
|
+
"Keep it light and positive",
|
|
118
|
+
],
|
|
119
|
+
prohibitions: [
|
|
120
|
+
"Do not be overly formal",
|
|
121
|
+
"Never ignore the customer's mood",
|
|
122
|
+
"Do not push products unless asked",
|
|
123
|
+
],
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
// Demonstration function
|
|
127
|
+
async function demonstrateRulesAndProhibitions() {
|
|
128
|
+
console.log("\n=== Rules & Prohibitions Demo ===\n");
|
|
129
|
+
|
|
130
|
+
// Example 1: Quick Support - Should be short and direct
|
|
131
|
+
console.log("1️⃣ Quick Support Route (short, direct)");
|
|
132
|
+
const history1 = [
|
|
133
|
+
createMessageEvent(
|
|
134
|
+
EventSource.CUSTOMER,
|
|
135
|
+
"Alice",
|
|
136
|
+
"What are your business hours?"
|
|
137
|
+
),
|
|
138
|
+
];
|
|
139
|
+
|
|
140
|
+
const response1 = await agent.respond({ history: history1 });
|
|
141
|
+
console.log(`Route: ${response1.route?.title}`);
|
|
142
|
+
console.log(`Response: ${response1.message}`);
|
|
143
|
+
console.log(`Expected: Short, direct, max 1 emoji\n`);
|
|
144
|
+
|
|
145
|
+
// Example 2: Sales Consultation - Should be engaging and value-focused
|
|
146
|
+
console.log("2️⃣ Sales Consultation Route (conversational, value-first)");
|
|
147
|
+
const history2 = [
|
|
148
|
+
createMessageEvent(
|
|
149
|
+
EventSource.CUSTOMER,
|
|
150
|
+
"Bob",
|
|
151
|
+
"I'm interested in your premium plan"
|
|
152
|
+
),
|
|
153
|
+
];
|
|
154
|
+
|
|
155
|
+
const response2 = await agent.respond({ history: history2 });
|
|
156
|
+
console.log(`Route: ${response2.route?.title}`);
|
|
157
|
+
console.log(`Response: ${response2.message}`);
|
|
158
|
+
console.log(`Expected: Ask about needs, show value before price\n`);
|
|
159
|
+
|
|
160
|
+
// Example 3: Technical Support - Should be detailed and step-by-step
|
|
161
|
+
console.log("3️⃣ Technical Support Route (detailed, step-by-step)");
|
|
162
|
+
const history3 = [
|
|
163
|
+
createMessageEvent(
|
|
164
|
+
EventSource.CUSTOMER,
|
|
165
|
+
"Charlie",
|
|
166
|
+
"My app keeps crashing when I try to login"
|
|
167
|
+
),
|
|
168
|
+
];
|
|
169
|
+
|
|
170
|
+
const response3 = await agent.respond({ history: history3 });
|
|
171
|
+
console.log(`Route: ${response3.route?.title}`);
|
|
172
|
+
console.log(`Response: ${response3.message}`);
|
|
173
|
+
console.log(`Expected: Clear steps, simple language, patient\n`);
|
|
174
|
+
|
|
175
|
+
// Example 4: Emergency Support - Should be calm and action-oriented
|
|
176
|
+
console.log("4️⃣ Emergency Support Route (urgent, professional)");
|
|
177
|
+
const history4 = [
|
|
178
|
+
createMessageEvent(
|
|
179
|
+
EventSource.CUSTOMER,
|
|
180
|
+
"Diana",
|
|
181
|
+
"This is urgent! My payment failed and I need access NOW!"
|
|
182
|
+
),
|
|
183
|
+
];
|
|
184
|
+
|
|
185
|
+
const response4 = await agent.respond({ history: history4 });
|
|
186
|
+
console.log(`Route: ${response4.route?.title}`);
|
|
187
|
+
console.log(`Response: ${response4.message}`);
|
|
188
|
+
console.log(`Expected: Acknowledge urgency, no emojis, concrete steps\n`);
|
|
189
|
+
|
|
190
|
+
// Example 5: General Chat - Should be friendly and casual
|
|
191
|
+
console.log("5️⃣ General Chat Route (friendly, casual)");
|
|
192
|
+
const history5 = [
|
|
193
|
+
createMessageEvent(EventSource.CUSTOMER, "Eve", "Hey! How's it going?"),
|
|
194
|
+
];
|
|
195
|
+
|
|
196
|
+
const response5 = await agent.respond({ history: history5 });
|
|
197
|
+
console.log(`Route: ${response5.route?.title}`);
|
|
198
|
+
console.log(`Response: ${response5.message}`);
|
|
199
|
+
console.log(`Expected: Friendly, emojis, mirrors customer tone\n`);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Inspect route configurations
|
|
203
|
+
console.log("\n📋 Route Configurations:\n");
|
|
204
|
+
for (const route of agent.getRoutes()) {
|
|
205
|
+
console.log(`\n🛤️ ${route.title}`);
|
|
206
|
+
|
|
207
|
+
const rules = route.getRules();
|
|
208
|
+
if (rules.length > 0) {
|
|
209
|
+
console.log(` ✅ Rules (${rules.length}):`);
|
|
210
|
+
rules.forEach((rule, i) => console.log(` ${i + 1}. ${rule}`));
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
const prohibitions = route.getProhibitions();
|
|
214
|
+
if (prohibitions.length > 0) {
|
|
215
|
+
console.log(` ❌ Prohibitions (${prohibitions.length}):`);
|
|
216
|
+
prohibitions.forEach((prohibition, i) =>
|
|
217
|
+
console.log(` ${i + 1}. ${prohibition}`)
|
|
218
|
+
);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// Benefits explanation
|
|
223
|
+
console.log(`
|
|
224
|
+
\n💡 Benefits of Rules & Prohibitions:
|
|
225
|
+
|
|
226
|
+
1️⃣ **Context-Specific Behavior**
|
|
227
|
+
- Each route can have completely different communication styles
|
|
228
|
+
- WhatsApp support: short messages
|
|
229
|
+
- Sales: engaging, story-driven
|
|
230
|
+
- Technical: detailed, step-by-step
|
|
231
|
+
|
|
232
|
+
2️⃣ **Brand Consistency**
|
|
233
|
+
- Rules ensure the agent always follows brand guidelines
|
|
234
|
+
- Prohibitions prevent off-brand behavior
|
|
235
|
+
- Different routes for different contexts
|
|
236
|
+
|
|
237
|
+
3️⃣ **User Experience**
|
|
238
|
+
- Emergency route: professional, no emojis
|
|
239
|
+
- General chat: friendly, casual
|
|
240
|
+
- Technical support: patient, thorough
|
|
241
|
+
|
|
242
|
+
4️⃣ **Automatic Enforcement**
|
|
243
|
+
- Rules are applied in the AI prompt automatically
|
|
244
|
+
- No manual checking needed
|
|
245
|
+
- Consistent behavior across all conversations
|
|
246
|
+
|
|
247
|
+
5️⃣ **Easy to Update**
|
|
248
|
+
- Change rules without changing code
|
|
249
|
+
- A/B test different communication styles
|
|
250
|
+
- Iterate based on customer feedback
|
|
251
|
+
`);
|
|
252
|
+
|
|
253
|
+
// Run demonstration
|
|
254
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
255
|
+
demonstrateRulesAndProhibitions().catch(console.error);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
export { agent };
|