@falai/agent 0.9.0-alpha-1 → 0.9.0-alpha-2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (166) hide show
  1. package/README.md +34 -22
  2. package/dist/cjs/src/core/Agent.d.ts +52 -24
  3. package/dist/cjs/src/core/Agent.d.ts.map +1 -1
  4. package/dist/cjs/src/core/Agent.js +266 -39
  5. package/dist/cjs/src/core/Agent.js.map +1 -1
  6. package/dist/cjs/src/core/PersistenceManager.d.ts.map +1 -1
  7. package/dist/cjs/src/core/PersistenceManager.js +48 -25
  8. package/dist/cjs/src/core/PersistenceManager.js.map +1 -1
  9. package/dist/cjs/src/core/PromptComposer.d.ts +1 -1
  10. package/dist/cjs/src/core/PromptComposer.d.ts.map +1 -1
  11. package/dist/cjs/src/core/PromptComposer.js.map +1 -1
  12. package/dist/cjs/src/core/ResponseEngine.d.ts +13 -12
  13. package/dist/cjs/src/core/ResponseEngine.d.ts.map +1 -1
  14. package/dist/cjs/src/core/ResponseEngine.js +4 -4
  15. package/dist/cjs/src/core/ResponseEngine.js.map +1 -1
  16. package/dist/cjs/src/core/ResponsePipeline.d.ts +66 -38
  17. package/dist/cjs/src/core/ResponsePipeline.d.ts.map +1 -1
  18. package/dist/cjs/src/core/ResponsePipeline.js +71 -3
  19. package/dist/cjs/src/core/ResponsePipeline.js.map +1 -1
  20. package/dist/cjs/src/core/Route.d.ts +24 -5
  21. package/dist/cjs/src/core/Route.d.ts.map +1 -1
  22. package/dist/cjs/src/core/Route.js +45 -1
  23. package/dist/cjs/src/core/Route.js.map +1 -1
  24. package/dist/cjs/src/core/RoutingEngine.d.ts +31 -6
  25. package/dist/cjs/src/core/RoutingEngine.d.ts.map +1 -1
  26. package/dist/cjs/src/core/RoutingEngine.js +113 -9
  27. package/dist/cjs/src/core/RoutingEngine.js.map +1 -1
  28. package/dist/cjs/src/core/SessionManager.d.ts +14 -4
  29. package/dist/cjs/src/core/SessionManager.d.ts.map +1 -1
  30. package/dist/cjs/src/core/SessionManager.js +25 -5
  31. package/dist/cjs/src/core/SessionManager.js.map +1 -1
  32. package/dist/cjs/src/core/Step.d.ts +10 -10
  33. package/dist/cjs/src/core/Step.d.ts.map +1 -1
  34. package/dist/cjs/src/core/Step.js.map +1 -1
  35. package/dist/cjs/src/core/ToolExecutor.d.ts +4 -2
  36. package/dist/cjs/src/core/ToolExecutor.d.ts.map +1 -1
  37. package/dist/cjs/src/core/ToolExecutor.js +13 -3
  38. package/dist/cjs/src/core/ToolExecutor.js.map +1 -1
  39. package/dist/cjs/src/types/agent.d.ts +41 -21
  40. package/dist/cjs/src/types/agent.d.ts.map +1 -1
  41. package/dist/cjs/src/types/agent.js.map +1 -1
  42. package/dist/cjs/src/types/index.d.ts +1 -1
  43. package/dist/cjs/src/types/index.d.ts.map +1 -1
  44. package/dist/cjs/src/types/index.js.map +1 -1
  45. package/dist/cjs/src/types/persistence.d.ts +0 -1
  46. package/dist/cjs/src/types/persistence.d.ts.map +1 -1
  47. package/dist/cjs/src/types/route.d.ts +22 -16
  48. package/dist/cjs/src/types/route.d.ts.map +1 -1
  49. package/dist/cjs/src/types/session.d.ts +6 -11
  50. package/dist/cjs/src/types/session.d.ts.map +1 -1
  51. package/dist/cjs/src/types/tool.d.ts +12 -6
  52. package/dist/cjs/src/types/tool.d.ts.map +1 -1
  53. package/dist/cjs/src/utils/session.d.ts +2 -2
  54. package/dist/cjs/src/utils/session.d.ts.map +1 -1
  55. package/dist/cjs/src/utils/session.js +6 -26
  56. package/dist/cjs/src/utils/session.js.map +1 -1
  57. package/dist/src/core/Agent.d.ts +52 -24
  58. package/dist/src/core/Agent.d.ts.map +1 -1
  59. package/dist/src/core/Agent.js +266 -39
  60. package/dist/src/core/Agent.js.map +1 -1
  61. package/dist/src/core/PersistenceManager.d.ts.map +1 -1
  62. package/dist/src/core/PersistenceManager.js +48 -25
  63. package/dist/src/core/PersistenceManager.js.map +1 -1
  64. package/dist/src/core/PromptComposer.d.ts +1 -1
  65. package/dist/src/core/PromptComposer.d.ts.map +1 -1
  66. package/dist/src/core/PromptComposer.js.map +1 -1
  67. package/dist/src/core/ResponseEngine.d.ts +13 -12
  68. package/dist/src/core/ResponseEngine.d.ts.map +1 -1
  69. package/dist/src/core/ResponseEngine.js +4 -4
  70. package/dist/src/core/ResponseEngine.js.map +1 -1
  71. package/dist/src/core/ResponsePipeline.d.ts +66 -38
  72. package/dist/src/core/ResponsePipeline.d.ts.map +1 -1
  73. package/dist/src/core/ResponsePipeline.js +71 -3
  74. package/dist/src/core/ResponsePipeline.js.map +1 -1
  75. package/dist/src/core/Route.d.ts +24 -5
  76. package/dist/src/core/Route.d.ts.map +1 -1
  77. package/dist/src/core/Route.js +45 -1
  78. package/dist/src/core/Route.js.map +1 -1
  79. package/dist/src/core/RoutingEngine.d.ts +31 -6
  80. package/dist/src/core/RoutingEngine.d.ts.map +1 -1
  81. package/dist/src/core/RoutingEngine.js +113 -9
  82. package/dist/src/core/RoutingEngine.js.map +1 -1
  83. package/dist/src/core/SessionManager.d.ts +14 -4
  84. package/dist/src/core/SessionManager.d.ts.map +1 -1
  85. package/dist/src/core/SessionManager.js +25 -5
  86. package/dist/src/core/SessionManager.js.map +1 -1
  87. package/dist/src/core/Step.d.ts +10 -10
  88. package/dist/src/core/Step.d.ts.map +1 -1
  89. package/dist/src/core/Step.js.map +1 -1
  90. package/dist/src/core/ToolExecutor.d.ts +4 -2
  91. package/dist/src/core/ToolExecutor.d.ts.map +1 -1
  92. package/dist/src/core/ToolExecutor.js +13 -3
  93. package/dist/src/core/ToolExecutor.js.map +1 -1
  94. package/dist/src/types/agent.d.ts +41 -21
  95. package/dist/src/types/agent.d.ts.map +1 -1
  96. package/dist/src/types/agent.js.map +1 -1
  97. package/dist/src/types/index.d.ts +1 -1
  98. package/dist/src/types/index.d.ts.map +1 -1
  99. package/dist/src/types/index.js.map +1 -1
  100. package/dist/src/types/persistence.d.ts +0 -1
  101. package/dist/src/types/persistence.d.ts.map +1 -1
  102. package/dist/src/types/route.d.ts +22 -16
  103. package/dist/src/types/route.d.ts.map +1 -1
  104. package/dist/src/types/session.d.ts +6 -11
  105. package/dist/src/types/session.d.ts.map +1 -1
  106. package/dist/src/types/tool.d.ts +12 -6
  107. package/dist/src/types/tool.d.ts.map +1 -1
  108. package/dist/src/utils/session.d.ts +2 -2
  109. package/dist/src/utils/session.d.ts.map +1 -1
  110. package/dist/src/utils/session.js +6 -26
  111. package/dist/src/utils/session.js.map +1 -1
  112. package/docs/README.md +3 -3
  113. package/docs/api/README.md +35 -4
  114. package/docs/api/overview.md +166 -12
  115. package/docs/core/agent/README.md +162 -17
  116. package/docs/core/agent/context-management.md +39 -15
  117. package/docs/core/agent/session-management.md +49 -16
  118. package/docs/core/ai-integration/prompt-composition.md +38 -14
  119. package/docs/core/ai-integration/response-processing.md +28 -17
  120. package/docs/core/conversation-flows/data-collection.md +103 -25
  121. package/docs/core/conversation-flows/route-dsl.md +45 -22
  122. package/docs/core/conversation-flows/routes.md +74 -18
  123. package/docs/core/conversation-flows/step-transitions.md +3 -3
  124. package/docs/core/conversation-flows/steps.md +39 -15
  125. package/docs/core/routing/intelligent-routing.md +18 -9
  126. package/docs/core/tools/tool-definition.md +8 -8
  127. package/docs/core/tools/tool-execution.md +26 -26
  128. package/docs/core/tools/tool-scoping.md +5 -5
  129. package/docs/guides/getting-started/README.md +54 -32
  130. package/examples/advanced-patterns/knowledge-based-agent.ts +37 -28
  131. package/examples/advanced-patterns/persistent-onboarding.ts +70 -41
  132. package/examples/advanced-patterns/route-lifecycle-hooks.ts +28 -2
  133. package/examples/advanced-patterns/streaming-responses.ts +28 -23
  134. package/examples/ai-providers/anthropic-integration.ts +40 -33
  135. package/examples/ai-providers/openai-integration.ts +25 -25
  136. package/examples/conversation-flows/completion-transitions.ts +36 -32
  137. package/examples/core-concepts/basic-agent.ts +76 -78
  138. package/examples/core-concepts/schema-driven-extraction.ts +20 -16
  139. package/examples/core-concepts/session-management.ts +65 -53
  140. package/examples/integrations/database-integration.ts +49 -34
  141. package/examples/integrations/healthcare-integration.ts +96 -91
  142. package/examples/integrations/search-integration.ts +79 -82
  143. package/examples/integrations/server-session-management.ts +25 -17
  144. package/examples/persistence/database-persistence.ts +61 -45
  145. package/examples/persistence/memory-sessions.ts +52 -63
  146. package/examples/persistence/redis-persistence.ts +81 -95
  147. package/examples/tools/basic-tools.ts +73 -62
  148. package/examples/tools/data-enrichment-tools.ts +52 -44
  149. package/package.json +1 -1
  150. package/src/core/Agent.ts +418 -128
  151. package/src/core/PersistenceManager.ts +51 -27
  152. package/src/core/PromptComposer.ts +1 -1
  153. package/src/core/ResponseEngine.ts +21 -19
  154. package/src/core/ResponsePipeline.ts +174 -59
  155. package/src/core/Route.ts +58 -6
  156. package/src/core/RoutingEngine.ts +174 -27
  157. package/src/core/SessionManager.ts +32 -8
  158. package/src/core/Step.ts +20 -12
  159. package/src/core/ToolExecutor.ts +19 -5
  160. package/src/types/agent.ts +46 -23
  161. package/src/types/index.ts +2 -0
  162. package/src/types/persistence.ts +0 -1
  163. package/src/types/route.ts +22 -16
  164. package/src/types/session.ts +6 -12
  165. package/src/types/tool.ts +15 -9
  166. package/src/utils/session.ts +6 -31
@@ -64,8 +64,20 @@ async function example() {
64
64
 
65
65
  const userId = "user_123";
66
66
 
67
+ // Define support ticket schema
68
+ const supportTicketSchema = {
69
+ type: "object",
70
+ properties: {
71
+ issue: { type: "string" },
72
+ category: { type: "string", enum: ["technical", "billing", "account", "other"] },
73
+ priority: { type: "string", enum: ["low", "medium", "high"] },
74
+ description: { type: "string" },
75
+ },
76
+ required: ["issue", "category", "priority", "description"],
77
+ };
78
+
67
79
  // Create agent with Redis persistence
68
- const agent = new Agent<ChatContext>({
80
+ const agent = new Agent<ChatContext, SupportTicketData>({
69
81
  name: "Support Assistant",
70
82
  description: "Fast, real-time support assistant",
71
83
  goal: "Help users resolve issues quickly",
@@ -78,6 +90,8 @@ async function example() {
78
90
  userName: "Alice",
79
91
  chatType: "support",
80
92
  },
93
+ // NEW: Agent-level schema
94
+ schema: supportTicketSchema,
81
95
  // ✨ Redis adapter with custom options
82
96
  persistence: {
83
97
  adapter: new RedisAdapter<ChatContext>({
@@ -92,7 +106,7 @@ async function example() {
92
106
  });
93
107
 
94
108
  // Create support ticket route with data collecting
95
- const ticketRoute = agent.createRoute<SupportTicketData>({
109
+ const ticketRoute = agent.createRoute({
96
110
  title: "Create Support Ticket",
97
111
  description: "Help user create and track support tickets",
98
112
  conditions: [
@@ -100,31 +114,10 @@ async function example() {
100
114
  "User wants to report a problem",
101
115
  "User mentions support, help, or issue",
102
116
  ],
103
- schema: {
104
- type: "object",
105
- properties: {
106
- issue: {
107
- type: "string",
108
- description: "Brief summary of the issue",
109
- },
110
- category: {
111
- type: "string",
112
- enum: ["technical", "billing", "account", "other"],
113
- description: "Issue category",
114
- },
115
- priority: {
116
- type: "string",
117
- enum: ["low", "medium", "high"],
118
- default: "medium",
119
- description: "Issue priority",
120
- },
121
- description: {
122
- type: "string",
123
- description: "Detailed description of the issue",
124
- },
125
- },
126
- required: ["issue", "category", "description"],
127
- },
117
+ // NEW: Required fields for route completion
118
+ requiredFields: ["issue", "category", "description"],
119
+ // NEW: Optional fields that enhance the experience
120
+ optionalFields: ["priority"],
128
121
  });
129
122
 
130
123
  // Step flow
@@ -156,9 +149,9 @@ async function example() {
156
149
  console.log("✨ Session ready:", agent.session.id);
157
150
 
158
151
  // Set initial data
159
- await agent.session.setData<SupportTicketData>({ priority: "medium" });
152
+ await agent.session.setData({ priority: "medium" });
160
153
 
161
- console.log("📊 Initial data:", agent.session.getData<SupportTicketData>());
154
+ console.log("📊 Initial data:", agent.session.getData());
162
155
 
163
156
  // Turn 1: User provides issue
164
157
  console.log("\n--- Turn 1 ---");
@@ -177,11 +170,11 @@ async function example() {
177
170
  console.log("🤖 Agent:", response1.message);
178
171
 
179
172
  await agent.session.addMessage("assistant", response1.message);
180
- console.log("📊 Collected data:", agent.session.getData<SupportTicketData>());
173
+ console.log("📊 Collected data:", agent.session.getData());
181
174
 
182
175
  // Turn 2: Provide more details
183
176
  console.log("\n--- Turn 2 ---");
184
-
177
+
185
178
  await agent.session.addMessage(
186
179
  "user",
187
180
  "I keep getting 'Invalid credentials' error even though I reset my password",
@@ -193,20 +186,20 @@ async function example() {
193
186
  });
194
187
 
195
188
  console.log("🤖 Agent:", response2.message);
196
- console.log("📊 Collected data:", agent.session.getData<SupportTicketData>());
189
+ console.log("📊 Collected data:", agent.session.getData());
197
190
 
198
191
  await agent.session.addMessage("assistant", response2.message);
199
192
 
200
193
  if (response2.isRouteComplete) {
201
194
  console.log("\n✅ Support ticket route complete!");
202
- await fileSupportTicket(agent.session.getData<SupportTicketData>() as SupportTicketData);
195
+ await fileSupportTicket(agent.session.getData() as SupportTicketData);
203
196
  }
204
197
 
205
198
  // Demonstrate session recovery with new agent instance
206
199
  console.log("\n--- Session Recovery Example ---");
207
200
  const sessionId = agent.session.id;
208
-
209
- const recoveredAgent = new Agent<ChatContext>({
201
+
202
+ const recoveredAgent = new Agent<ChatContext, SupportTicketData>({
210
203
  name: "Support Assistant",
211
204
  provider: new GeminiProvider({
212
205
  apiKey: process.env.GEMINI_API_KEY!,
@@ -217,6 +210,8 @@ async function example() {
217
210
  userName: "Alice",
218
211
  chatType: "support",
219
212
  },
213
+ // NEW: Agent-level schema (same as original agent)
214
+ schema: supportTicketSchema,
220
215
  persistence: {
221
216
  adapter: new RedisAdapter<ChatContext>({
222
217
  redis,
@@ -230,7 +225,7 @@ async function example() {
230
225
  });
231
226
 
232
227
  // Recreate the same route on recovered agent
233
- recoveredAgent.createRoute<SupportTicketData>({
228
+ recoveredAgent.createRoute({
234
229
  title: "Create Support Ticket",
235
230
  description: "Help user create and track support tickets",
236
231
  conditions: [
@@ -238,31 +233,16 @@ async function example() {
238
233
  "User wants to report a problem",
239
234
  "User mentions support, help, or issue",
240
235
  ],
241
- schema: {
242
- type: "object",
243
- properties: {
244
- issue: { type: "string", description: "Brief summary of the issue" },
245
- category: {
246
- type: "string",
247
- enum: ["technical", "billing", "account", "other"],
248
- description: "Issue category",
249
- },
250
- priority: {
251
- type: "string",
252
- enum: ["low", "medium", "high"],
253
- default: "medium",
254
- description: "Issue priority",
255
- },
256
- description: { type: "string", description: "Detailed description of the issue" },
257
- },
258
- required: ["issue", "category", "description"],
259
- },
236
+ // NEW: Required fields for route completion
237
+ requiredFields: ["issue", "category", "description"],
238
+ // NEW: Optional fields that enhance the experience
239
+ optionalFields: ["priority"],
260
240
  });
261
241
 
262
242
  console.log("📥 Recovered session:", {
263
243
  sessionId: recoveredAgent.session.id,
264
244
  historyLength: recoveredAgent.session.getHistory().length,
265
- data: recoveredAgent.session.getData<SupportTicketData>(),
245
+ data: recoveredAgent.session.getData(),
266
246
  });
267
247
 
268
248
  console.log("✅ Session recovery complete!");
@@ -278,15 +258,27 @@ async function example() {
278
258
  async function highThroughputExample() {
279
259
  const redis = new Redis();
280
260
 
281
- const agent = new Agent<QuickChatData>({
261
+ // Define quick chat schema
262
+ const quickChatSchema = {
263
+ type: "object",
264
+ properties: {
265
+ topic: { type: "string" },
266
+ sentiment: { type: "string", enum: ["positive", "neutral", "negative"] },
267
+ },
268
+ required: ["topic", "sentiment"],
269
+ };
270
+
271
+ const agent = new Agent<unknown, QuickChatData>({
282
272
  name: "Chat Bot",
283
273
  description: "Fast chat responses",
284
274
  provider: new GeminiProvider({
285
275
  apiKey: process.env.GEMINI_API_KEY!,
286
276
  model: "models/gemini-2.5-flash",
287
277
  }),
278
+ // NEW: Agent-level schema
279
+ schema: quickChatSchema,
288
280
  persistence: {
289
- adapter: new RedisAdapter<QuickChatData>({
281
+ adapter: new RedisAdapter<unknown>({
290
282
  redis,
291
283
  keyPrefix: "chat:",
292
284
  sessionTTL: 60 * 60, // 1 hour for quick chats
@@ -297,23 +289,10 @@ async function highThroughputExample() {
297
289
  });
298
290
 
299
291
  // Simple chat route that extracts topic and sentiment
300
- const chatRoute = agent.createRoute<QuickChatData>({
292
+ const chatRoute = agent.createRoute({
301
293
  title: "General Chat",
302
- schema: {
303
- type: "object",
304
- properties: {
305
- topic: {
306
- type: "string",
307
- description: "Main topic of conversation",
308
- },
309
- sentiment: {
310
- type: "string",
311
- enum: ["positive", "neutral", "negative"],
312
- description: "User's sentiment",
313
- },
314
- },
315
- required: ["topic", "sentiment"],
316
- },
294
+ // NEW: Required fields for route completion
295
+ requiredFields: ["topic", "sentiment"],
317
296
  });
318
297
 
319
298
  chatRoute.initialStep
@@ -334,13 +313,13 @@ async function highThroughputExample() {
334
313
  });
335
314
 
336
315
  console.log("🤖 Response:", response.message);
337
- console.log("📊 Data:", agent.session.getData<QuickChatData>());
316
+ console.log("📊 Data:", agent.session.getData());
338
317
 
339
318
  await agent.session.addMessage("assistant", response.message);
340
319
 
341
320
  if (response.isRouteComplete) {
342
321
  console.log("\n✅ Chat analytics route complete!");
343
- await logChatAnalytics(agent.session.getData<QuickChatData>() as QuickChatData);
322
+ await logChatAnalytics(agent.session.getData() as QuickChatData);
344
323
  }
345
324
 
346
325
  console.log("💾 Session automatically saved to Redis!");
@@ -355,30 +334,36 @@ async function highThroughputExample() {
355
334
  async function sessionRecoveryExample() {
356
335
  const redis = new Redis();
357
336
 
358
- const agent = new Agent<OrderData>({
337
+ // Define order schema
338
+ const orderSchema = {
339
+ type: "object",
340
+ properties: {
341
+ productId: { type: "string" },
342
+ quantity: { type: "number", minimum: 1 },
343
+ shippingAddress: { type: "string" },
344
+ },
345
+ required: ["productId", "quantity", "shippingAddress"],
346
+ };
347
+
348
+ const agent = new Agent<unknown, OrderData>({
359
349
  name: "Order Assistant",
360
350
  provider: new GeminiProvider({
361
351
  apiKey: process.env.GEMINI_API_KEY!,
362
352
  model: "models/gemini-2.5-flash",
363
353
  }),
354
+ // NEW: Agent-level schema
355
+ schema: orderSchema,
364
356
  persistence: {
365
- adapter: new RedisAdapter<OrderData>({ redis }),
357
+ adapter: new RedisAdapter<unknown>({ redis }),
366
358
  autoSave: true,
367
359
  userId: "user_789",
368
360
  },
369
361
  });
370
362
 
371
- const orderRoute = agent.createRoute<OrderData>({
363
+ const orderRoute = agent.createRoute({
372
364
  title: "Place Order",
373
- schema: {
374
- type: "object",
375
- properties: {
376
- productId: { type: "string" },
377
- quantity: { type: "number", minimum: 1 },
378
- shippingAddress: { type: "string" },
379
- },
380
- required: ["productId", "quantity", "shippingAddress"],
381
- },
365
+ // NEW: Required fields for route completion
366
+ requiredFields: ["productId", "quantity", "shippingAddress"],
382
367
  });
383
368
 
384
369
  orderRoute.initialStep
@@ -404,7 +389,7 @@ async function sessionRecoveryExample() {
404
389
  });
405
390
 
406
391
  console.log("🤖 Response:", response1.message);
407
- console.log("📊 Data so far:", agent.session.getData<OrderData>());
392
+ console.log("📊 Data so far:", agent.session.getData());
408
393
 
409
394
  await agent.session.addMessage("assistant", response1.message);
410
395
 
@@ -412,24 +397,25 @@ async function sessionRecoveryExample() {
412
397
  console.log("\n--- User Reconnects ---");
413
398
 
414
399
  // Create new agent instance with same sessionId (simulates reconnection)
415
- const reconnectedAgent = new Agent<OrderData>({
400
+ const reconnectedAgent = new Agent<unknown, OrderData>({
416
401
  name: "Order Assistant",
417
402
  provider: new GeminiProvider({
418
403
  apiKey: process.env.GEMINI_API_KEY!,
419
404
  model: "models/gemini-2.5-flash",
420
405
  }),
406
+ // NEW: Agent-level schema (same as original agent)
407
+ schema: orderSchema,
421
408
  persistence: {
422
- adapter: new RedisAdapter<OrderData>({ redis }),
409
+ adapter: new RedisAdapter<unknown>({ redis }),
423
410
  autoSave: true,
424
411
  },
425
412
  sessionId, // Same sessionId - will load existing session
426
- routes: [orderRoute],
427
413
  });
428
414
 
429
415
  console.log("📥 Recovered session:", {
430
416
  sessionId: reconnectedAgent.session.id,
431
417
  historyLength: reconnectedAgent.session.getHistory().length,
432
- data: reconnectedAgent.session.getData<OrderData>(),
418
+ data: reconnectedAgent.session.getData(),
433
419
  });
434
420
 
435
421
  // Continue conversation
@@ -440,13 +426,13 @@ async function sessionRecoveryExample() {
440
426
  });
441
427
 
442
428
  console.log("🤖 Response:", response2.message);
443
- console.log("📊 Final collected data:", reconnectedAgent.session.getData<OrderData>());
429
+ console.log("📊 Final collected data:", reconnectedAgent.session.getData());
444
430
 
445
431
  await reconnectedAgent.session.addMessage("assistant", response2.message);
446
432
 
447
433
  if (response2.isRouteComplete) {
448
434
  console.log("\n✅ Order placement complete!");
449
- await processOrder(reconnectedAgent.session.getData<OrderData>() as OrderData);
435
+ await processOrder(reconnectedAgent.session.getData() as OrderData);
450
436
  }
451
437
 
452
438
  console.log("✅ Order complete with recovered session!");
@@ -6,7 +6,7 @@
6
6
  * and integration with conversation flows.
7
7
  *
8
8
  * Key concepts:
9
- * - Tool definition with Tool<TContext, TArgs, TResult, TData> interface
9
+ * - Tool definition with Tool<TContext, TData, TArgs, TResult> interface
10
10
  * - Tool context and parameters
11
11
  * - Tool execution in conversation flows
12
12
  * - Error handling in tools
@@ -36,7 +36,7 @@ interface SearchData {
36
36
  }
37
37
 
38
38
  // Example 1: Simple Calculator Tool
39
- const calculatorTool: Tool<unknown, [], string, CalculatorData> = {
39
+ const calculatorTool: Tool<unknown, UnifiedToolData, [], string> = {
40
40
  id: "calculator",
41
41
  name: "Math Calculator",
42
42
  description: "Evaluate mathematical expressions and return results",
@@ -51,8 +51,7 @@ const calculatorTool: Tool<unknown, [], string, CalculatorData> = {
51
51
  required: ["expression"],
52
52
  },
53
53
  handler: ({ data }) => {
54
- const calcData = data as Partial<CalculatorData>;
55
- if (!calcData?.expression) {
54
+ if (!data?.expression) {
56
55
  throw new Error("No expression provided");
57
56
  }
58
57
 
@@ -60,22 +59,22 @@ const calculatorTool: Tool<unknown, [], string, CalculatorData> = {
60
59
  // Simple expression evaluation (in production, use a safe math library)
61
60
  // WARNING: eval is unsafe - use a proper math evaluation library in production
62
61
  // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
63
- const result = eval(calcData.expression);
62
+ const result = eval(data.expression);
64
63
 
65
64
  if (typeof result !== "number" || isNaN(result)) {
66
65
  throw new Error("Invalid calculation result");
67
66
  }
68
67
 
69
68
  return {
70
- data: `The result of ${calcData.expression} is ${result}`,
69
+ data: `The result of ${data.expression} is ${result}`,
71
70
  dataUpdate: {
72
71
  result,
73
- operation: calcData.expression,
72
+ operation: data.expression,
74
73
  },
75
74
  };
76
75
  } catch (error) {
77
76
  throw new Error(
78
- `Error calculating ${calcData.expression}: ${
77
+ `Error calculating ${data.expression}: ${
79
78
  error instanceof Error ? error.message : "Unknown error"
80
79
  }`
81
80
  );
@@ -84,7 +83,7 @@ const calculatorTool: Tool<unknown, [], string, CalculatorData> = {
84
83
  };
85
84
 
86
85
  // Example 2: Weather Tool with External API Simulation
87
- const weatherTool: Tool<unknown, [], string, WeatherData> = {
86
+ const weatherTool: Tool<unknown, UnifiedToolData, [], string> = {
88
87
  id: "get_weather",
89
88
  name: "Weather Lookup",
90
89
  description: "Get current weather and forecast for a location",
@@ -96,8 +95,7 @@ const weatherTool: Tool<unknown, [], string, WeatherData> = {
96
95
  required: ["location"],
97
96
  },
98
97
  handler: async ({ data }) => {
99
- const weatherData = data as Partial<WeatherData>;
100
- if (!weatherData?.location) {
98
+ if (!data?.location) {
101
99
  throw new Error("No location provided");
102
100
  }
103
101
 
@@ -127,14 +125,14 @@ const weatherTool: Tool<unknown, [], string, WeatherData> = {
127
125
  },
128
126
  };
129
127
 
130
- const weather = mockWeather[weatherData.location] || {
128
+ const weather = mockWeather[data.location] || {
131
129
  temp: 70,
132
130
  condition: "Unknown",
133
131
  forecast: "Weather data unavailable",
134
132
  };
135
133
 
136
134
  return {
137
- data: `Weather in ${weatherData.location}: ${weather.temp}°F and ${weather.condition}. ${weather.forecast}`,
135
+ data: `Weather in ${data.location}: ${weather.temp}°F and ${weather.condition}. ${weather.forecast}`,
138
136
  dataUpdate: {
139
137
  temperature: weather.temp,
140
138
  condition: weather.condition,
@@ -145,7 +143,7 @@ const weatherTool: Tool<unknown, [], string, WeatherData> = {
145
143
  };
146
144
 
147
145
  // Example 3: Search Tool with Multiple Results
148
- const searchTool: Tool<unknown, [], string, SearchData> = {
146
+ const searchTool: Tool<unknown, UnifiedToolData, [], string> = {
149
147
  id: "web_search",
150
148
  name: "Web Search",
151
149
  description: "Search the web for information on a given query",
@@ -157,8 +155,7 @@ const searchTool: Tool<unknown, [], string, SearchData> = {
157
155
  required: ["query"],
158
156
  },
159
157
  handler: async ({ data }) => {
160
- const searchData = data as Partial<SearchData>;
161
- if (!searchData?.query) {
158
+ if (!data?.query) {
162
159
  throw new Error("No search query provided");
163
160
  }
164
161
 
@@ -187,15 +184,15 @@ const searchTool: Tool<unknown, [], string, SearchData> = {
187
184
  ],
188
185
  };
189
186
 
190
- const results = mockResults[searchData.query.toLowerCase()] || [
191
- `Search results for "${searchData.query}"`,
187
+ const results = mockResults[data.query.toLowerCase()] || [
188
+ `Search results for "${data.query}"`,
192
189
  "This is a simulated search result",
193
190
  "In a real implementation, this would connect to a search API",
194
191
  "Such as Google Custom Search, Bing Web Search, or Elasticsearch",
195
192
  ];
196
193
 
197
194
  return {
198
- data: `Search results for "${searchData.query}":\n${results
195
+ data: `Search results for "${data.query}":\n${results
199
196
  .map((r, i) => `${i + 1}. ${r}`)
200
197
  .join("\n")}`,
201
198
  dataUpdate: {
@@ -209,9 +206,9 @@ const searchTool: Tool<unknown, [], string, SearchData> = {
209
206
  // Example 4: Tool that Modifies Context (Advanced)
210
207
  const updatePreferencesTool: Tool<
211
208
  { preferences?: { theme: string; language: string } },
209
+ UnifiedToolData,
212
210
  [],
213
- string,
214
- { theme?: string; language?: string }
211
+ string
215
212
  > = {
216
213
  id: "update_preferences",
217
214
  name: "Update Preferences",
@@ -242,29 +239,54 @@ const updatePreferencesTool: Tool<
242
239
  },
243
240
  };
244
241
 
242
+ // Define unified data schema for all tool interactions
243
+ interface UnifiedToolData extends CalculatorData, WeatherData, SearchData {
244
+ theme?: string;
245
+ language?: string;
246
+ }
247
+
248
+ const unifiedToolSchema = {
249
+ type: "object",
250
+ properties: {
251
+ // Calculator fields
252
+ expression: { type: "string" },
253
+ result: { type: "number" },
254
+ operation: { type: "string" },
255
+ // Weather fields
256
+ location: { type: "string" },
257
+ temperature: { type: "number" },
258
+ condition: { type: "string" },
259
+ forecast: { type: "string" },
260
+ // Search fields
261
+ query: { type: "string" },
262
+ results: { type: "array", items: { type: "string" } },
263
+ source: { type: "string" },
264
+ // Preferences fields
265
+ theme: { type: "string", enum: ["light", "dark"] },
266
+ language: { type: "string", enum: ["en", "es", "fr"] },
267
+ },
268
+ };
269
+
245
270
  // Create agent with tools
246
- const agent = new Agent<{ preferences?: { theme: string; language: string } }>({
271
+ const agent = new Agent<{ preferences?: { theme: string; language: string } }, UnifiedToolData>({
247
272
  name: "ToolBot",
248
273
  description: "An agent demonstrating various tool capabilities",
249
274
  provider: new GeminiProvider({
250
275
  apiKey: process.env.GEMINI_API_KEY!,
251
276
  model: "models/gemini-2.5-flash",
252
277
  }),
278
+ // NEW: Agent-level schema
279
+ schema: unifiedToolSchema,
253
280
  });
254
281
 
255
282
  // Create routes that use different tools
256
- agent.createRoute<CalculatorData>({
283
+ agent.createRoute({
257
284
  title: "Calculator",
258
285
  description: "Mathematical calculations",
259
- schema: {
260
- type: "object",
261
- properties: {
262
- expression: { type: "string" },
263
- result: { type: "number" },
264
- operation: { type: "string" },
265
- },
266
- required: ["expression"],
267
- },
286
+ // NEW: Required fields for route completion
287
+ requiredFields: ["expression"],
288
+ // NEW: Optional fields that enhance the experience
289
+ optionalFields: ["result", "operation"],
268
290
  steps: [
269
291
  {
270
292
  id: "get_expression",
@@ -283,19 +305,13 @@ agent.createRoute<CalculatorData>({
283
305
  ],
284
306
  });
285
307
 
286
- agent.createRoute<WeatherData>({
308
+ agent.createRoute({
287
309
  title: "Weather",
288
310
  description: "Weather information",
289
- schema: {
290
- type: "object",
291
- properties: {
292
- location: { type: "string" },
293
- temperature: { type: "number" },
294
- condition: { type: "string" },
295
- forecast: { type: "string" },
296
- },
297
- required: ["location"],
298
- },
311
+ // NEW: Required fields for route completion
312
+ requiredFields: ["location"],
313
+ // NEW: Optional fields that enhance the experience
314
+ optionalFields: ["temperature", "condition", "forecast"],
299
315
  steps: [
300
316
  {
301
317
  id: "get_location",
@@ -314,18 +330,13 @@ agent.createRoute<WeatherData>({
314
330
  ],
315
331
  });
316
332
 
317
- agent.createRoute<SearchData>({
333
+ agent.createRoute({
318
334
  title: "Web Search",
319
335
  description: "Information search",
320
- schema: {
321
- type: "object",
322
- properties: {
323
- query: { type: "string" },
324
- results: { type: "array", items: { type: "string" } },
325
- source: { type: "string" },
326
- },
327
- required: ["query"],
328
- },
336
+ // NEW: Required fields for route completion
337
+ requiredFields: ["query"],
338
+ // NEW: Optional fields that enhance the experience
339
+ optionalFields: ["results", "source"],
329
340
  steps: [
330
341
  {
331
342
  id: "get_query",
@@ -371,7 +382,7 @@ async function demonstrateBasicTools() {
371
382
  console.log("Bot:", calcResponse.message);
372
383
  console.log(
373
384
  "Calculated result:",
374
- (calcResponse.session?.data as Partial<CalculatorData>)?.result
385
+ calcResponse.session?.data?.result
375
386
  );
376
387
  console.log();
377
388
 
@@ -383,9 +394,9 @@ async function demonstrateBasicTools() {
383
394
  });
384
395
  console.log("Bot:", weatherResponse.message);
385
396
  console.log("Weather data:", {
386
- temperature: (weatherResponse.session?.data as Partial<WeatherData>)
397
+ temperature: (weatherResponse.session?.data as Partial<UnifiedToolData>)
387
398
  ?.temperature,
388
- condition: (weatherResponse.session?.data as Partial<WeatherData>)
399
+ condition: (weatherResponse.session?.data as Partial<UnifiedToolData>)
389
400
  ?.condition,
390
401
  });
391
402
  console.log();
@@ -404,7 +415,7 @@ async function demonstrateBasicTools() {
404
415
  console.log("Bot:", searchResponse.message);
405
416
  console.log(
406
417
  "Search results count:",
407
- (searchResponse.session?.data as Partial<SearchData>)?.results?.length
418
+ (searchResponse.session?.data as Partial<UnifiedToolData>)?.results?.length
408
419
  );
409
420
  }
410
421
 
@@ -453,15 +464,15 @@ async function demonstrateToolDataFlow() {
453
464
  console.log("1. Initial calculation:");
454
465
  console.log(
455
466
  " User input collected:",
456
- (response1.session?.data as Partial<CalculatorData>)?.expression
467
+ (response1.session?.data as Partial<UnifiedToolData>)?.expression
457
468
  );
458
469
  console.log(
459
470
  " Tool result:",
460
- (response1.session?.data as Partial<CalculatorData>)?.result
471
+ (response1.session?.data as Partial<UnifiedToolData>)?.result
461
472
  );
462
473
  console.log(
463
474
  " Operation stored:",
464
- (response1.session?.data as Partial<CalculatorData>)?.operation
475
+ (response1.session?.data as Partial<UnifiedToolData>)?.operation
465
476
  );
466
477
 
467
478
  // Follow up question using previous result
@@ -475,7 +486,7 @@ async function demonstrateToolDataFlow() {
475
486
  console.log("\n2. Follow-up calculation:");
476
487
  console.log(
477
488
  " Previous result available:",
478
- (response2.session?.data as Partial<CalculatorData>)?.result
489
+ (response2.session?.data as Partial<UnifiedToolData>)?.result
479
490
  );
480
491
  console.log(" Bot response:", response2.message);
481
492
  }
@@ -486,7 +497,7 @@ function demonstrateToolPatterns() {
486
497
 
487
498
  console.log("1. Basic Tool Pattern:");
488
499
  console.log(`
489
- const myTool: Tool<ContextType, [], ResultType, DataType> = {
500
+ const myTool: Tool<ContextType, DataType, [], ResultType> = {
490
501
  id: "tool_name", // Unique identifier
491
502
  description: "What this tool does", // AI uses this to decide when to call
492
503
  parameters: { // JSON Schema for tool parameters