@falai/agent 0.9.0-alpha-1 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (217) hide show
  1. package/README.md +34 -22
  2. package/dist/cjs/src/core/Agent.d.ts +77 -59
  3. package/dist/cjs/src/core/Agent.d.ts.map +1 -1
  4. package/dist/cjs/src/core/Agent.js +284 -1060
  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/ResponseModal.d.ts +205 -0
  17. package/dist/cjs/src/core/ResponseModal.d.ts.map +1 -0
  18. package/dist/cjs/src/core/ResponseModal.js +1328 -0
  19. package/dist/cjs/src/core/ResponseModal.js.map +1 -0
  20. package/dist/cjs/src/core/ResponsePipeline.d.ts +66 -38
  21. package/dist/cjs/src/core/ResponsePipeline.d.ts.map +1 -1
  22. package/dist/cjs/src/core/ResponsePipeline.js +72 -4
  23. package/dist/cjs/src/core/ResponsePipeline.js.map +1 -1
  24. package/dist/cjs/src/core/Route.d.ts +24 -5
  25. package/dist/cjs/src/core/Route.d.ts.map +1 -1
  26. package/dist/cjs/src/core/Route.js +45 -1
  27. package/dist/cjs/src/core/Route.js.map +1 -1
  28. package/dist/cjs/src/core/RoutingEngine.d.ts +31 -6
  29. package/dist/cjs/src/core/RoutingEngine.d.ts.map +1 -1
  30. package/dist/cjs/src/core/RoutingEngine.js +113 -9
  31. package/dist/cjs/src/core/RoutingEngine.js.map +1 -1
  32. package/dist/cjs/src/core/SessionManager.d.ts +14 -4
  33. package/dist/cjs/src/core/SessionManager.d.ts.map +1 -1
  34. package/dist/cjs/src/core/SessionManager.js +25 -5
  35. package/dist/cjs/src/core/SessionManager.js.map +1 -1
  36. package/dist/cjs/src/core/Step.d.ts +10 -10
  37. package/dist/cjs/src/core/Step.d.ts.map +1 -1
  38. package/dist/cjs/src/core/Step.js.map +1 -1
  39. package/dist/cjs/src/core/ToolExecutor.d.ts +4 -2
  40. package/dist/cjs/src/core/ToolExecutor.d.ts.map +1 -1
  41. package/dist/cjs/src/core/ToolExecutor.js +13 -3
  42. package/dist/cjs/src/core/ToolExecutor.js.map +1 -1
  43. package/dist/cjs/src/index.d.ts +3 -1
  44. package/dist/cjs/src/index.d.ts.map +1 -1
  45. package/dist/cjs/src/index.js +7 -1
  46. package/dist/cjs/src/index.js.map +1 -1
  47. package/dist/cjs/src/types/agent.d.ts +42 -21
  48. package/dist/cjs/src/types/agent.d.ts.map +1 -1
  49. package/dist/cjs/src/types/agent.js.map +1 -1
  50. package/dist/cjs/src/types/ai.d.ts +1 -1
  51. package/dist/cjs/src/types/ai.d.ts.map +1 -1
  52. package/dist/cjs/src/types/index.d.ts +1 -1
  53. package/dist/cjs/src/types/index.d.ts.map +1 -1
  54. package/dist/cjs/src/types/index.js.map +1 -1
  55. package/dist/cjs/src/types/persistence.d.ts +0 -1
  56. package/dist/cjs/src/types/persistence.d.ts.map +1 -1
  57. package/dist/cjs/src/types/route.d.ts +22 -16
  58. package/dist/cjs/src/types/route.d.ts.map +1 -1
  59. package/dist/cjs/src/types/session.d.ts +6 -11
  60. package/dist/cjs/src/types/session.d.ts.map +1 -1
  61. package/dist/cjs/src/types/tool.d.ts +12 -6
  62. package/dist/cjs/src/types/tool.d.ts.map +1 -1
  63. package/dist/cjs/src/utils/clone.d.ts.map +1 -1
  64. package/dist/cjs/src/utils/clone.js +0 -4
  65. package/dist/cjs/src/utils/clone.js.map +1 -1
  66. package/dist/cjs/src/utils/history.d.ts +30 -1
  67. package/dist/cjs/src/utils/history.d.ts.map +1 -1
  68. package/dist/cjs/src/utils/history.js +169 -23
  69. package/dist/cjs/src/utils/history.js.map +1 -1
  70. package/dist/cjs/src/utils/index.d.ts +1 -1
  71. package/dist/cjs/src/utils/index.d.ts.map +1 -1
  72. package/dist/cjs/src/utils/index.js +5 -1
  73. package/dist/cjs/src/utils/index.js.map +1 -1
  74. package/dist/cjs/src/utils/session.d.ts +2 -2
  75. package/dist/cjs/src/utils/session.d.ts.map +1 -1
  76. package/dist/cjs/src/utils/session.js +6 -26
  77. package/dist/cjs/src/utils/session.js.map +1 -1
  78. package/dist/src/core/Agent.d.ts +77 -59
  79. package/dist/src/core/Agent.d.ts.map +1 -1
  80. package/dist/src/core/Agent.js +285 -1061
  81. package/dist/src/core/Agent.js.map +1 -1
  82. package/dist/src/core/PersistenceManager.d.ts.map +1 -1
  83. package/dist/src/core/PersistenceManager.js +48 -25
  84. package/dist/src/core/PersistenceManager.js.map +1 -1
  85. package/dist/src/core/PromptComposer.d.ts +1 -1
  86. package/dist/src/core/PromptComposer.d.ts.map +1 -1
  87. package/dist/src/core/PromptComposer.js.map +1 -1
  88. package/dist/src/core/ResponseEngine.d.ts +13 -12
  89. package/dist/src/core/ResponseEngine.d.ts.map +1 -1
  90. package/dist/src/core/ResponseEngine.js +4 -4
  91. package/dist/src/core/ResponseEngine.js.map +1 -1
  92. package/dist/src/core/ResponseModal.d.ts +205 -0
  93. package/dist/src/core/ResponseModal.d.ts.map +1 -0
  94. package/dist/src/core/ResponseModal.js +1323 -0
  95. package/dist/src/core/ResponseModal.js.map +1 -0
  96. package/dist/src/core/ResponsePipeline.d.ts +66 -38
  97. package/dist/src/core/ResponsePipeline.d.ts.map +1 -1
  98. package/dist/src/core/ResponsePipeline.js +72 -4
  99. package/dist/src/core/ResponsePipeline.js.map +1 -1
  100. package/dist/src/core/Route.d.ts +24 -5
  101. package/dist/src/core/Route.d.ts.map +1 -1
  102. package/dist/src/core/Route.js +45 -1
  103. package/dist/src/core/Route.js.map +1 -1
  104. package/dist/src/core/RoutingEngine.d.ts +31 -6
  105. package/dist/src/core/RoutingEngine.d.ts.map +1 -1
  106. package/dist/src/core/RoutingEngine.js +113 -9
  107. package/dist/src/core/RoutingEngine.js.map +1 -1
  108. package/dist/src/core/SessionManager.d.ts +14 -4
  109. package/dist/src/core/SessionManager.d.ts.map +1 -1
  110. package/dist/src/core/SessionManager.js +25 -5
  111. package/dist/src/core/SessionManager.js.map +1 -1
  112. package/dist/src/core/Step.d.ts +10 -10
  113. package/dist/src/core/Step.d.ts.map +1 -1
  114. package/dist/src/core/Step.js.map +1 -1
  115. package/dist/src/core/ToolExecutor.d.ts +4 -2
  116. package/dist/src/core/ToolExecutor.d.ts.map +1 -1
  117. package/dist/src/core/ToolExecutor.js +13 -3
  118. package/dist/src/core/ToolExecutor.js.map +1 -1
  119. package/dist/src/index.d.ts +3 -1
  120. package/dist/src/index.d.ts.map +1 -1
  121. package/dist/src/index.js +2 -1
  122. package/dist/src/index.js.map +1 -1
  123. package/dist/src/types/agent.d.ts +42 -21
  124. package/dist/src/types/agent.d.ts.map +1 -1
  125. package/dist/src/types/agent.js.map +1 -1
  126. package/dist/src/types/ai.d.ts +1 -1
  127. package/dist/src/types/ai.d.ts.map +1 -1
  128. package/dist/src/types/index.d.ts +1 -1
  129. package/dist/src/types/index.d.ts.map +1 -1
  130. package/dist/src/types/index.js.map +1 -1
  131. package/dist/src/types/persistence.d.ts +0 -1
  132. package/dist/src/types/persistence.d.ts.map +1 -1
  133. package/dist/src/types/route.d.ts +22 -16
  134. package/dist/src/types/route.d.ts.map +1 -1
  135. package/dist/src/types/session.d.ts +6 -11
  136. package/dist/src/types/session.d.ts.map +1 -1
  137. package/dist/src/types/tool.d.ts +12 -6
  138. package/dist/src/types/tool.d.ts.map +1 -1
  139. package/dist/src/utils/clone.d.ts.map +1 -1
  140. package/dist/src/utils/clone.js +0 -4
  141. package/dist/src/utils/clone.js.map +1 -1
  142. package/dist/src/utils/history.d.ts +30 -1
  143. package/dist/src/utils/history.d.ts.map +1 -1
  144. package/dist/src/utils/history.js +165 -23
  145. package/dist/src/utils/history.js.map +1 -1
  146. package/dist/src/utils/index.d.ts +1 -1
  147. package/dist/src/utils/index.d.ts.map +1 -1
  148. package/dist/src/utils/index.js +1 -1
  149. package/dist/src/utils/index.js.map +1 -1
  150. package/dist/src/utils/session.d.ts +2 -2
  151. package/dist/src/utils/session.d.ts.map +1 -1
  152. package/dist/src/utils/session.js +6 -26
  153. package/dist/src/utils/session.js.map +1 -1
  154. package/docs/README.md +5 -4
  155. package/docs/api/README.md +195 -4
  156. package/docs/api/overview.md +232 -13
  157. package/docs/core/agent/README.md +162 -17
  158. package/docs/core/agent/context-management.md +39 -15
  159. package/docs/core/agent/session-management.md +49 -16
  160. package/docs/core/ai-integration/prompt-composition.md +38 -14
  161. package/docs/core/ai-integration/response-processing.md +28 -17
  162. package/docs/core/conversation-flows/data-collection.md +103 -25
  163. package/docs/core/conversation-flows/route-dsl.md +45 -22
  164. package/docs/core/conversation-flows/routes.md +74 -18
  165. package/docs/core/conversation-flows/step-transitions.md +3 -3
  166. package/docs/core/conversation-flows/steps.md +39 -15
  167. package/docs/core/routing/intelligent-routing.md +18 -9
  168. package/docs/core/tools/tool-definition.md +8 -8
  169. package/docs/core/tools/tool-execution.md +26 -26
  170. package/docs/core/tools/tool-scoping.md +5 -5
  171. package/docs/guides/getting-started/README.md +54 -32
  172. package/docs/guides/migration/README.md +72 -0
  173. package/docs/guides/migration/response-modal-refactor.md +518 -0
  174. package/examples/advanced-patterns/knowledge-based-agent.ts +37 -28
  175. package/examples/advanced-patterns/persistent-onboarding.ts +70 -41
  176. package/examples/advanced-patterns/route-lifecycle-hooks.ts +28 -2
  177. package/examples/advanced-patterns/streaming-responses.ts +197 -119
  178. package/examples/ai-providers/anthropic-integration.ts +40 -33
  179. package/examples/ai-providers/openai-integration.ts +25 -25
  180. package/examples/conversation-flows/completion-transitions.ts +36 -32
  181. package/examples/core-concepts/basic-agent.ts +76 -78
  182. package/examples/core-concepts/modern-streaming-api.ts +309 -0
  183. package/examples/core-concepts/schema-driven-extraction.ts +20 -16
  184. package/examples/core-concepts/session-management.ts +65 -53
  185. package/examples/integrations/database-integration.ts +49 -34
  186. package/examples/integrations/healthcare-integration.ts +96 -91
  187. package/examples/integrations/search-integration.ts +79 -82
  188. package/examples/integrations/server-session-management.ts +25 -17
  189. package/examples/persistence/database-persistence.ts +61 -45
  190. package/examples/persistence/memory-sessions.ts +52 -63
  191. package/examples/persistence/redis-persistence.ts +81 -95
  192. package/examples/tools/basic-tools.ts +73 -62
  193. package/examples/tools/data-enrichment-tools.ts +52 -44
  194. package/package.json +1 -1
  195. package/src/core/Agent.ts +396 -1499
  196. package/src/core/PersistenceManager.ts +51 -27
  197. package/src/core/PromptComposer.ts +1 -1
  198. package/src/core/ResponseEngine.ts +21 -19
  199. package/src/core/ResponseModal.ts +1722 -0
  200. package/src/core/ResponsePipeline.ts +175 -60
  201. package/src/core/Route.ts +58 -6
  202. package/src/core/RoutingEngine.ts +174 -27
  203. package/src/core/SessionManager.ts +32 -8
  204. package/src/core/Step.ts +20 -12
  205. package/src/core/ToolExecutor.ts +19 -5
  206. package/src/index.ts +11 -0
  207. package/src/types/agent.ts +47 -23
  208. package/src/types/ai.ts +1 -1
  209. package/src/types/index.ts +2 -0
  210. package/src/types/persistence.ts +0 -1
  211. package/src/types/route.ts +22 -16
  212. package/src/types/session.ts +6 -12
  213. package/src/types/tool.ts +15 -9
  214. package/src/utils/clone.ts +6 -8
  215. package/src/utils/history.ts +190 -27
  216. package/src/utils/index.ts +4 -0
  217. package/src/utils/session.ts +6 -31
@@ -124,8 +124,21 @@ async function example() {
124
124
  const userId = "user_123";
125
125
  const sessionId = "session_user123_onboarding";
126
126
 
127
+ // Define onboarding schema
128
+ const onboardingSchema = {
129
+ type: "object",
130
+ properties: {
131
+ fullName: { type: "string" },
132
+ email: { type: "string" },
133
+ companyName: { type: "string" },
134
+ phoneNumber: { type: "string" },
135
+ industry: { type: "string" },
136
+ },
137
+ required: ["fullName", "email", "companyName"],
138
+ };
139
+
127
140
  // Create agent with SessionManager (no persistence adapter)
128
- const agent = new Agent({
141
+ const agent = new Agent<unknown, OnboardingData>({
129
142
  name: "Onboarding Assistant",
130
143
  description: "Help new customers get started",
131
144
  goal: "Collect customer information efficiently",
@@ -133,28 +146,23 @@ async function example() {
133
146
  apiKey: process.env.GEMINI_API_KEY!,
134
147
  model: "models/gemini-2.5-flash",
135
148
  }),
149
+ // NEW: Agent-level schema
150
+ schema: onboardingSchema,
136
151
  // No persistence - we'll sync manually with our database
137
152
  });
138
153
 
139
154
  // Create onboarding route
140
- const onboardingRoute = agent.createRoute<OnboardingData>({
155
+ const onboardingRoute = agent.createRoute({
141
156
  title: "Customer Onboarding",
142
157
  description: "Collect customer information",
143
158
  conditions: [
144
159
  "User is a new customer",
145
160
  "User needs to set up their account",
146
161
  ],
147
- schema: {
148
- type: "object",
149
- properties: {
150
- fullName: { type: "string" },
151
- email: { type: "string" },
152
- companyName: { type: "string" },
153
- phoneNumber: { type: "string" },
154
- industry: { type: "string" },
155
- },
156
- required: ["fullName", "email", "companyName"],
157
- },
162
+ // NEW: Required fields for route completion
163
+ requiredFields: ["fullName", "email", "companyName"],
164
+ // NEW: Optional fields that enhance the experience
165
+ optionalFields: ["phoneNumber", "industry"],
158
166
  });
159
167
 
160
168
  // Define steps with custom IDs
@@ -251,7 +259,7 @@ async function example() {
251
259
  console.log("āœ… Session synchronized:", {
252
260
  sessionId: agent.session.id,
253
261
  historyLength: agent.session.getHistory().length,
254
- data: agent.session.getData<OnboardingData>(),
262
+ data: agent.session.getData(),
255
263
  });
256
264
 
257
265
  /**
@@ -267,7 +275,7 @@ async function example() {
267
275
  });
268
276
 
269
277
  console.log("šŸ¤– Agent:", response1.message);
270
- console.log("šŸ“Š Data collected:", agent.session.getData<OnboardingData>());
278
+ console.log("šŸ“Š Data collected:", agent.session.getData());
271
279
 
272
280
  // Add agent response to SessionManager
273
281
  await agent.session.addMessage("assistant", response1.message);
@@ -286,7 +294,7 @@ async function example() {
286
294
  });
287
295
 
288
296
  console.log("šŸ¤– Agent:", response2.message);
289
- console.log("šŸ“Š Data collected:", agent.session.getData<OnboardingData>());
297
+ console.log("šŸ“Š Data collected:", agent.session.getData());
290
298
 
291
299
  await agent.session.addMessage("assistant", response2.message);
292
300
 
@@ -297,7 +305,7 @@ async function example() {
297
305
  // Check for route completion
298
306
  if (response2.isRouteComplete) {
299
307
  console.log("\nāœ… Onboarding Complete!");
300
- await processOnboarding(agent.session.getData<OnboardingData>());
308
+ await processOnboarding(agent.session.getData());
301
309
  }
302
310
 
303
311
  /**
@@ -347,7 +355,7 @@ async function example() {
347
355
  console.log("āœ… Session recovered in new agent:", {
348
356
  sessionId: newAgent.session.id,
349
357
  historyLength: newAgent.session.getHistory().length,
350
- data: newAgent.session.getData<OnboardingData>(),
358
+ data: newAgent.session.getData(),
351
359
  });
352
360
 
353
361
  // Continue conversation with recovered session
@@ -367,7 +375,7 @@ async function example() {
367
375
  * Helper function to sync SessionManager state to custom database
368
376
  */
369
377
  async function syncSessionToDatabase(
370
- agent: Agent,
378
+ agent: Agent<unknown, OnboardingData>,
371
379
  db: CustomDatabase,
372
380
  sessionId: string,
373
381
  userId: string
@@ -424,15 +432,28 @@ async function advancedExample() {
424
432
  const db = new CustomDatabase();
425
433
  const sessionId = "session_user456_smart_onboarding";
426
434
 
427
- const agent = new Agent({
435
+ const smartOnboardingSchema = {
436
+ type: "object",
437
+ properties: {
438
+ fullName: { type: "string" },
439
+ email: { type: "string" },
440
+ companyName: { type: "string" },
441
+ phoneNumber: { type: "string" },
442
+ },
443
+ required: ["fullName", "email", "companyName"],
444
+ };
445
+
446
+ const agent = new Agent<unknown, OnboardingData>({
428
447
  name: "Smart Onboarding",
429
448
  provider: new GeminiProvider({
430
449
  apiKey: process.env.GEMINI_API_KEY!,
431
450
  model: "models/gemini-2.5-flash",
432
451
  }),
452
+ // NEW: Agent-level schema
453
+ schema: smartOnboardingSchema,
433
454
  hooks: {
434
455
  // Validate and enrich collected data
435
- onDataUpdate: (data: OnboardingData, _previous: OnboardingData) => {
456
+ onDataUpdate: (data: Partial<OnboardingData>, _previous: Partial<OnboardingData>) => {
436
457
  console.log("šŸ”„ Data collected, validating...");
437
458
 
438
459
  // Normalize email
@@ -450,18 +471,12 @@ async function advancedExample() {
450
471
  },
451
472
  });
452
473
 
453
- const route = agent.createRoute<OnboardingData>({
474
+ const route = agent.createRoute({
454
475
  title: "Smart Onboarding",
455
- schema: {
456
- type: "object",
457
- properties: {
458
- fullName: { type: "string" },
459
- email: { type: "string" },
460
- companyName: { type: "string" },
461
- phoneNumber: { type: "string" },
462
- },
463
- required: ["fullName", "email", "companyName"],
464
- },
476
+ // NEW: Required fields for route completion
477
+ requiredFields: ["fullName", "email", "companyName"],
478
+ // NEW: Optional fields
479
+ optionalFields: ["phoneNumber"],
465
480
  });
466
481
 
467
482
  route.initialStep.nextStep({
@@ -492,7 +507,7 @@ async function advancedExample() {
492
507
  });
493
508
 
494
509
  console.log("šŸ¤– Agent:", response.message);
495
- console.log("šŸ“Š Normalized data:", agent.session.getData<OnboardingData>());
510
+ console.log("šŸ“Š Normalized data:", agent.session.getData());
496
511
  // Shows: { email: "alice@example.com", phoneNumber: "5551234567", ... }
497
512
 
498
513
  await agent.session.addMessage("assistant", response.message);
@@ -518,7 +533,7 @@ async function serverEndpointExample() {
518
533
  const { sessionId, userId, message } = req;
519
534
 
520
535
  // Create agent with sessionId (loads existing or creates new)
521
- const agent = new Agent({
536
+ const agent = new Agent<unknown, OnboardingData>({
522
537
  name: "Customer Support",
523
538
  provider: new GeminiProvider({
524
539
  apiKey: process.env.GEMINI_API_KEY!,
@@ -39,7 +39,7 @@ interface SatisfactionData {
39
39
 
40
40
  // Tools
41
41
 
42
- const getUpcomingSlots: Tool<HealthcareContext, unknown[], unknown, unknown> = {
42
+ const getUpcomingSlots: Tool<HealthcareContext, HealthcareData, unknown[], unknown> = {
43
43
  id: "get_upcoming_slots",
44
44
  name: "Available Appointment Slots",
45
45
  description: "Get upcoming appointment slots",
@@ -52,7 +52,7 @@ const getUpcomingSlots: Tool<HealthcareContext, unknown[], unknown, unknown> = {
52
52
  },
53
53
  };
54
54
 
55
- const getLaterSlots: Tool<HealthcareContext, unknown[], unknown, unknown> = {
55
+ const getLaterSlots: Tool<HealthcareContext, HealthcareData, unknown[], unknown> = {
56
56
  id: "get_later_slots",
57
57
  name: "Extended Appointment Slots",
58
58
  description: "Get later appointment slots",
@@ -67,9 +67,9 @@ const getLaterSlots: Tool<HealthcareContext, unknown[], unknown, unknown> = {
67
67
 
68
68
  const scheduleAppointment: Tool<
69
69
  HealthcareContext,
70
+ HealthcareData,
70
71
  unknown[],
71
- unknown,
72
- AppointmentData
72
+ unknown
73
73
  > = {
74
74
  id: "schedule_appointment",
75
75
  name: "Appointment Scheduler",
@@ -82,25 +82,24 @@ const scheduleAppointment: Tool<
82
82
  required: ["datetime"],
83
83
  },
84
84
  handler: ({ data }) => {
85
- const appointment = data as Partial<AppointmentData>;
86
- if (!appointment?.preferredDate || !appointment?.preferredTime) {
85
+ if (!data?.preferredDate || !data?.preferredTime) {
87
86
  return {
88
87
  data: "Please specify preferred date and time for the appointment",
89
88
  };
90
89
  }
91
90
  return {
92
- data: `Appointment scheduled for ${appointment.preferredDate} at ${
93
- appointment.preferredTime
94
- } for ${appointment.appointmentReason || "consultation"}`,
91
+ data: `Appointment scheduled for ${data.preferredDate} at ${
92
+ data.preferredTime
93
+ } for ${data.appointmentReason || "consultation"}`,
95
94
  };
96
95
  },
97
96
  };
98
97
 
99
98
  const getLabResults: Tool<
100
99
  HealthcareContext,
100
+ HealthcareData,
101
101
  unknown[],
102
- unknown,
103
- LabResultsData
102
+ unknown
104
103
  > = {
105
104
  id: "get_lab_results",
106
105
  name: "Lab Results Retriever",
@@ -110,10 +109,9 @@ const getLabResults: Tool<
110
109
  properties: {},
111
110
  },
112
111
  handler: ({ context, data }) => {
113
- const labData = data as Partial<LabResultsData>;
114
112
  return {
115
113
  data: {
116
- report: `Lab results for ${labData?.testType || "general"} tests`,
114
+ report: `Lab results for ${data?.testType || "general"} tests`,
117
115
  prognosis: "All tests are within the valid range",
118
116
  patientName: context.patientName,
119
117
  },
@@ -121,18 +119,79 @@ const getLabResults: Tool<
121
119
  },
122
120
  };
123
121
 
122
+ // Define unified healthcare data schema
123
+ interface HealthcareData extends AppointmentData, LabResultsData, SatisfactionData {}
124
+
125
+ const healthcareSchema = {
126
+ type: "object",
127
+ properties: {
128
+ // Appointment fields
129
+ appointmentReason: {
130
+ type: "string",
131
+ description: "Reason for the appointment",
132
+ },
133
+ urgency: {
134
+ type: "string",
135
+ enum: ["low", "medium", "high"],
136
+ default: "medium",
137
+ },
138
+ preferredTime: {
139
+ type: "string",
140
+ description: "Preferred time slot",
141
+ },
142
+ preferredDate: {
143
+ type: "string",
144
+ description: "Preferred date",
145
+ },
146
+ appointmentType: {
147
+ type: "string",
148
+ enum: ["checkup", "consultation", "followup"],
149
+ default: "consultation",
150
+ },
151
+ // Lab results fields
152
+ testType: {
153
+ type: "string",
154
+ description: "Type of lab test",
155
+ },
156
+ testDate: {
157
+ type: "string",
158
+ description: "Date of the lab test",
159
+ },
160
+ resultsNeeded: {
161
+ type: "boolean",
162
+ default: true,
163
+ description: "Whether detailed results are needed",
164
+ },
165
+ // Satisfaction fields
166
+ rating: {
167
+ type: "number",
168
+ description: "Overall satisfaction rating 1-5",
169
+ },
170
+ easeOfScheduling: {
171
+ type: "number",
172
+ description: "Ease of scheduling process 1-5",
173
+ },
174
+ comments: {
175
+ type: "string",
176
+ description: "Optional feedback comments",
177
+ },
178
+ },
179
+ };
180
+
124
181
  function createHealthcareAgent() {
125
182
  const provider = new AnthropicProvider({
126
183
  apiKey: process.env.ANTHROPIC_API_KEY || "test-key",
127
184
  model: "claude-sonnet-4-5",
128
185
  });
129
186
 
130
- const agent = new Agent<HealthcareContext>({
187
+ const agent = new Agent<HealthcareContext, HealthcareData>({
131
188
  name: "Healthcare Agent",
132
189
  description: "Is empathetic and calming to the patient.",
133
190
  identity:
134
191
  "I am the Healthcare Agent, a compassionate AI assistant dedicated to providing excellent patient care. With deep knowledge of medical procedures and a focus on patient comfort, I'm here to help you navigate your healthcare journey with empathy and expertise.",
135
192
  provider: provider,
193
+ // NEW: Agent-level schema
194
+ schema: healthcareSchema,
136
195
 
137
196
  // Knowledge base with healthcare-specific information
138
197
  knowledgeBase: {
@@ -200,7 +259,7 @@ function createHealthcareAgent() {
200
259
 
201
260
  // Create scheduling route with data extraction schema
202
261
  // NEW: Added onComplete to automatically transition to satisfaction survey after booking
203
- const schedulingRoute = agent.createRoute<AppointmentData>({
262
+ const schedulingRoute = agent.createRoute({
204
263
  title: "Schedule an Appointment",
205
264
  description: "Helps the patient find a time for their appointment.",
206
265
  conditions: ["The patient wants to schedule an appointment"],
@@ -224,34 +283,10 @@ function createHealthcareAgent() {
224
283
  description: "Remote healthcare consultation via video call or phone",
225
284
  },
226
285
  ],
227
- schema: {
228
- type: "object",
229
- properties: {
230
- appointmentReason: {
231
- type: "string",
232
- description: "Reason for the appointment",
233
- },
234
- urgency: {
235
- type: "string",
236
- enum: ["low", "medium", "high"],
237
- default: "medium",
238
- },
239
- preferredTime: {
240
- type: "string",
241
- description: "Preferred time slot",
242
- },
243
- preferredDate: {
244
- type: "string",
245
- description: "Preferred date",
246
- },
247
- appointmentType: {
248
- type: "string",
249
- enum: ["checkup", "consultation", "followup"],
250
- default: "consultation",
251
- },
252
- },
253
- required: ["appointmentReason"],
254
- },
286
+ // NEW: Required fields for route completion
287
+ requiredFields: ["appointmentReason"],
288
+ // NEW: Optional fields that enhance the experience
289
+ optionalFields: ["urgency", "preferredTime", "preferredDate", "appointmentType"],
255
290
  // NEW: Automatically collect feedback after successful scheduling
256
291
  onComplete: "Satisfaction Survey",
257
292
  });
@@ -334,29 +369,14 @@ function createHealthcareAgent() {
334
369
  });
335
370
 
336
371
  // Create lab results route with data extraction schema
337
- const labResultsRoute = agent.createRoute<LabResultsData>({
372
+ const labResultsRoute = agent.createRoute({
338
373
  title: "Lab Results",
339
374
  description: "Retrieves the patient's lab results and explains them.",
340
375
  conditions: ["The patient wants to see their lab results"],
341
- schema: {
342
- type: "object",
343
- properties: {
344
- testType: {
345
- type: "string",
346
- description: "Type of lab test",
347
- },
348
- testDate: {
349
- type: "string",
350
- description: "Date of the lab test",
351
- },
352
- resultsNeeded: {
353
- type: "boolean",
354
- default: true,
355
- description: "Whether detailed results are needed",
356
- },
357
- },
358
- required: ["testType"],
359
- },
376
+ // NEW: Required fields for route completion
377
+ requiredFields: ["testType"],
378
+ // NEW: Optional fields
379
+ optionalFields: ["testDate", "resultsNeeded"],
360
380
  });
361
381
 
362
382
  // Step 1: Collect test information
@@ -395,7 +415,7 @@ function createHealthcareAgent() {
395
415
  });
396
416
 
397
417
  // NEW: Satisfaction Survey route - collects feedback after appointment scheduling
398
- const satisfactionRoute = agent.createRoute<SatisfactionData>({
418
+ const satisfactionRoute = agent.createRoute({
399
419
  title: "Satisfaction Survey",
400
420
  description: "Quick satisfaction survey after scheduling",
401
421
  conditions: ["Collect patient satisfaction feedback"],
@@ -426,24 +446,10 @@ function createHealthcareAgent() {
426
446
  positive: "Share with staff as recognition",
427
447
  },
428
448
  },
429
- schema: {
430
- type: "object",
431
- properties: {
432
- rating: {
433
- type: "number",
434
- description: "Overall satisfaction rating 1-5",
435
- },
436
- easeOfScheduling: {
437
- type: "number",
438
- description: "Ease of scheduling process 1-5",
439
- },
440
- comments: {
441
- type: "string",
442
- description: "Optional feedback comments",
443
- },
444
- },
445
- required: ["rating"],
446
- },
449
+ // NEW: Required fields for route completion
450
+ requiredFields: ["rating"],
451
+ // NEW: Optional fields
452
+ optionalFields: ["easeOfScheduling", "comments"],
447
453
  });
448
454
 
449
455
  const askRating = satisfactionRoute.initialStep.nextStep({
@@ -512,14 +518,15 @@ async function main() {
512
518
  // Turn 1: Patient wants to follow up
513
519
  await agent.session.addMessage("user", "Hi, I need to follow up on my visit", "Patient");
514
520
 
521
+ const history = agent.session.getHistory()
515
522
  const response1 = await agent.respond({
516
- history: agent.session.getHistory()
523
+ history,
517
524
  });
518
525
 
519
526
  console.log("Patient: Hi, I need to follow up on my visit");
520
527
  console.log("Agent:", response1.message);
521
528
  console.log("Route:", response1.session?.currentRoute?.title);
522
- console.log("Data:", agent.session.getData<AppointmentData | LabResultsData>());
529
+ console.log("Data:", agent.session.getData());
523
530
 
524
531
  await agent.session.addMessage("assistant", response1.message);
525
532
 
@@ -534,14 +541,12 @@ async function main() {
534
541
  },
535
542
  ];
536
543
 
537
- const response2 = await agent.respond({ history: history2, session });
544
+ const response2 = await agent.respond({ history: history2 });
538
545
  console.log("\nPatient: I need to schedule a checkup for next week");
539
546
  console.log("Agent:", response2.message);
540
547
  console.log("Updated data:", response2.session?.data);
541
548
  console.log("Current step:", response2.session?.currentStep?.id);
542
549
 
543
- // Update session again
544
- session = response2.session!;
545
550
 
546
551
  // NEW: Check if route is complete - will auto-transition to satisfaction survey
547
552
  if (response2.isRouteComplete) {
@@ -563,7 +568,7 @@ async function main() {
563
568
  },
564
569
  ];
565
570
 
566
- const response3 = await agent.respond({ history: history3, session });
571
+ const response3 = await agent.respond({ history: history3 });
567
572
  console.log("\nPatient: Tuesday at 2 PM works for me.");
568
573
  console.log("Agent:", response3.message);
569
574
  console.log("Updated data:", response3.session?.data);
@@ -573,7 +578,7 @@ async function main() {
573
578
  if (response3.isRouteComplete) {
574
579
  console.log("\nāœ… Appointment scheduling complete!");
575
580
  await sendAppointmentReminder(
576
- agent.getData(response3.session?.id) as unknown as AppointmentData
581
+ agent.getCollectedData() as HealthcareData
577
582
  );
578
583
  }
579
584
  }
@@ -581,9 +586,9 @@ async function main() {
581
586
 
582
587
  /**
583
588
  * Mock function to send an appointment reminder.
584
- * @param data - The appointment data.
589
+ * @param data - The healthcare data.
585
590
  */
586
- async function sendAppointmentReminder(data: AppointmentData) {
591
+ async function sendAppointmentReminder(data: HealthcareData) {
587
592
  console.log("\n" + "=".repeat(60));
588
593
  console.log("šŸš€ Sending Appointment Reminder...");
589
594
  console.log("=".repeat(60));