@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
@@ -26,7 +26,7 @@ interface WeatherData {
26
26
  }
27
27
 
28
28
  // Define a tool that can access collected data
29
- const getWeather: Tool<CustomerContext, unknown[], unknown, WeatherData> = {
29
+ const getWeather: Tool<CustomerContext, WeatherData, unknown[], unknown> = {
30
30
  id: "get_weather",
31
31
  description: "Get current weather for a location",
32
32
  parameters: {
@@ -38,8 +38,7 @@ const getWeather: Tool<CustomerContext, unknown[], unknown, WeatherData> = {
38
38
  },
39
39
  handler: ({ data }, location) => {
40
40
  // Use data location if available, otherwise use args
41
- const weatherData = data as Partial<WeatherData>;
42
- const finalLocation = weatherData?.location || location;
41
+ const finalLocation = data?.location || location;
43
42
 
44
43
  // Simulate API call
45
44
  return {
@@ -71,7 +70,7 @@ async function main() {
71
70
  });
72
71
 
73
72
  // Create agent with OpenAI
74
- const agent = new Agent<CustomerContext>({
73
+ const agent = new Agent<CustomerContext, WeatherData>({
75
74
  name: "Assistant",
76
75
  description:
77
76
  "A helpful AI assistant that can check weather and answer questions",
@@ -84,6 +83,25 @@ async function main() {
84
83
  preferences: ["concise answers", "weather updates"],
85
84
  },
86
85
  provider: openaiProvider,
86
+
87
+ schema: {
88
+ type: "object",
89
+ properties: {
90
+ location: {
91
+ type: "string",
92
+ description: "City or location for weather check",
93
+ },
94
+ temperature: {
95
+ type: "number",
96
+ description: "Temperature in Fahrenheit",
97
+ },
98
+ condition: {
99
+ type: "string",
100
+ description: "Weather condition (sunny, cloudy, rainy, etc.)",
101
+ },
102
+ },
103
+ required: ["location"],
104
+ },
87
105
  });
88
106
 
89
107
  // Add domain knowledge
@@ -106,28 +124,10 @@ async function main() {
106
124
  });
107
125
 
108
126
  // Create weather route with data extraction schema
109
- const weatherRoute = agent.createRoute<WeatherData>({
127
+ const weatherRoute = agent.createRoute({
110
128
  title: "Check Weather",
111
129
  description: "Help user check weather for a location",
112
130
  conditions: ["User wants to know the weather"],
113
- schema: {
114
- type: "object",
115
- properties: {
116
- location: {
117
- type: "string",
118
- description: "City or location for weather check",
119
- },
120
- temperature: {
121
- type: "number",
122
- description: "Temperature in Fahrenheit",
123
- },
124
- condition: {
125
- type: "string",
126
- description: "Weather condition (sunny, cloudy, rainy, etc.)",
127
- },
128
- },
129
- required: ["location"],
130
- },
131
131
  });
132
132
 
133
133
  // Step 1: Collect location
@@ -180,14 +180,14 @@ async function main() {
180
180
  console.log(` Customer: What's the weather like in San Francisco?`);
181
181
  console.log(` Agent: ${response.message}`);
182
182
  console.log(` Route: ${response.session?.currentRoute?.title}`);
183
- console.log(` Data:`, agent.session.getData<WeatherData>());
183
+ console.log(` Data:`, agent.session.getData());
184
184
 
185
185
  await agent.session.addMessage("assistant", response.message);
186
186
 
187
187
  // Check for route completion
188
188
  if (response.isRouteComplete) {
189
189
  console.log("\nāœ… Weather route complete!");
190
- await logWeatherRequest(agent.session.getData<WeatherData>());
190
+ await logWeatherRequest(agent.session.getData());
191
191
  }
192
192
 
193
193
  console.log("\n✨ Session step benefits:");
@@ -15,21 +15,35 @@ import {
15
15
  type SessionState,
16
16
  } from "../../src/index";
17
17
 
18
- // Type definitions for our booking data
19
- interface BookingData {
18
+ // Type definitions for our unified data collection
19
+ interface UnifiedBookingData {
20
+ // Booking fields
20
21
  hotelName: string;
21
22
  date: string;
22
23
  guests: number;
23
- }
24
-
25
- interface FeedbackData {
24
+ // Feedback fields
26
25
  rating: number;
27
26
  comments?: string;
28
27
  }
29
28
 
30
29
  async function main() {
31
- // Create agent
32
- const agent = new Agent({
30
+ // Define unified schema for both booking and feedback data
31
+ const unifiedSchema = {
32
+ type: "object",
33
+ properties: {
34
+ // Booking fields
35
+ hotelName: { type: "string" },
36
+ date: { type: "string" },
37
+ guests: { type: "number" },
38
+ // Feedback fields
39
+ rating: { type: "number", minimum: 1, maximum: 5 },
40
+ comments: { type: "string" },
41
+ },
42
+ required: ["hotelName", "date", "guests"], // Only booking fields are required initially
43
+ };
44
+
45
+ // Create agent with unified schema
46
+ const agent = new Agent<unknown, UnifiedBookingData>({
33
47
  name: "HotelBot",
34
48
  description: "A hotel booking assistant with feedback collection",
35
49
  provider: new GeminiProvider({
@@ -37,22 +51,16 @@ async function main() {
37
51
  model: "models/gemini-2.5-flash",
38
52
  }),
39
53
  debug: true,
54
+ schema: unifiedSchema,
40
55
  });
41
56
 
42
57
  // Route 1: Hotel Booking with automatic transition to feedback
43
- agent.createRoute<BookingData>({
58
+ agent.createRoute({
44
59
  title: "Book Hotel",
45
60
  description: "Collects hotel booking information",
46
61
  conditions: ["User wants to book a hotel"],
47
- schema: {
48
- type: "object",
49
- properties: {
50
- hotelName: { type: "string" },
51
- date: { type: "string" },
52
- guests: { type: "number" },
53
- },
54
- required: ["hotelName", "date", "guests"],
55
- },
62
+ // NEW: Required fields for route completion
63
+ requiredFields: ["hotelName", "date", "guests"],
56
64
  // Sequential steps for booking flow
57
65
  steps: [
58
66
  {
@@ -60,7 +68,7 @@ async function main() {
60
68
  description: "Ask for hotel preference",
61
69
  prompt: "Which hotel would you like to book?",
62
70
  collect: ["hotelName"],
63
- skipIf: (data: Partial<BookingData>) => !!data.hotelName,
71
+ skipIf: (data: Partial<UnifiedBookingData>) => !!data.hotelName,
64
72
  },
65
73
  {
66
74
  id: "ask_date",
@@ -68,7 +76,7 @@ async function main() {
68
76
  prompt: "What date would you like to book for?",
69
77
  collect: ["date"],
70
78
  requires: ["hotelName"],
71
- skipIf: (data: Partial<BookingData>) => !!data.date,
79
+ skipIf: (data: Partial<UnifiedBookingData>) => !!data.date,
72
80
  },
73
81
  {
74
82
  id: "ask_guests",
@@ -76,7 +84,7 @@ async function main() {
76
84
  prompt: "How many guests will be staying?",
77
85
  collect: ["guests"],
78
86
  requires: ["hotelName", "date"],
79
- skipIf: (data: Partial<BookingData>) => data.guests !== undefined,
87
+ skipIf: (data: Partial<UnifiedBookingData>) => data.guests !== undefined,
80
88
  },
81
89
  {
82
90
  id: "confirm_booking",
@@ -91,18 +99,14 @@ async function main() {
91
99
  });
92
100
 
93
101
  // Route 2: Feedback Collection
94
- agent.createRoute<FeedbackData>({
102
+ agent.createRoute({
95
103
  title: "Collect Feedback",
96
104
  description: "Collects user feedback after booking",
97
105
  conditions: ["User wants to provide feedback"],
98
- schema: {
99
- type: "object",
100
- properties: {
101
- rating: { type: "number", minimum: 1, maximum: 5 },
102
- comments: { type: "string" },
103
- },
104
- required: ["rating"],
105
- },
106
+ // NEW: Required fields for route completion
107
+ requiredFields: ["rating"],
108
+ // NEW: Optional fields that enhance the experience
109
+ optionalFields: ["comments"],
106
110
  // Sequential steps for feedback collection
107
111
  steps: [
108
112
  {
@@ -110,7 +114,7 @@ async function main() {
110
114
  description: "Ask for rating",
111
115
  prompt: "How would you rate your booking experience from 1 to 5?",
112
116
  collect: ["rating"],
113
- skipIf: (data: Partial<FeedbackData>) => data.rating !== undefined,
117
+ skipIf: (data: Partial<UnifiedBookingData>) => data.rating !== undefined,
114
118
  },
115
119
  {
116
120
  id: "ask_comments",
@@ -153,7 +157,7 @@ async function main() {
153
157
  "Pending transition?",
154
158
  response1.session?.pendingTransition?.targetRouteId
155
159
  );
156
- console.log("Data booking data:", response1.session?.data);
160
+ console.log("Collected data:", response1.session?.data);
157
161
 
158
162
  session = response1.session;
159
163
  history = [
@@ -203,7 +207,7 @@ async function main() {
203
207
  const response3 = await agent.respond({ history, session });
204
208
  console.log("\nBot:", response3.message);
205
209
  console.log("Current route:", response3.session?.currentRoute?.title);
206
- console.log("Data feedback data:", response3.session?.data);
210
+ console.log("Collected data:", response3.session?.data);
207
211
  console.log("Route complete?", response3.isRouteComplete);
208
212
 
209
213
  console.log("\n=== Manual Transition Example ===\n");
@@ -17,7 +17,6 @@ import {
17
17
  type Guideline,
18
18
  type Tool,
19
19
  type RouteOptions,
20
- History,
21
20
  } from "../../src/index";
22
21
 
23
22
  // Context type
@@ -42,7 +41,7 @@ interface LabData {
42
41
  }
43
42
 
44
43
  // Define tools using the new Tool interface
45
- const getInsuranceProviders: Tool<HealthcareContext, [], string[]> = {
44
+ const getInsuranceProviders: Tool<HealthcareContext, HealthcareData, [], string[]> = {
46
45
  id: "healthcare_insurance_providers",
47
46
  description: "Retrieves list of accepted insurance providers",
48
47
  parameters: {
@@ -58,6 +57,7 @@ const getInsuranceProviders: Tool<HealthcareContext, [], string[]> = {
58
57
 
59
58
  const getAvailableSlots: Tool<
60
59
  HealthcareContext,
60
+ HealthcareData,
61
61
  [],
62
62
  { date: string; time: string }[]
63
63
  > = {
@@ -80,6 +80,7 @@ const getAvailableSlots: Tool<
80
80
 
81
81
  const getLabResults: Tool<
82
82
  HealthcareContext,
83
+ HealthcareData,
83
84
  [],
84
85
  { report: string; status: string }
85
86
  > = {
@@ -89,19 +90,12 @@ const getLabResults: Tool<
89
90
  type: "object",
90
91
  properties: {},
91
92
  },
92
- handler: ({
93
- context,
94
- data,
95
- }: {
96
- context: HealthcareContext;
97
- data?: Partial<LabData>;
98
- }) => {
93
+ handler: ({ context, data }) => {
99
94
  // Tools can access collected data and context
100
- const labData = data as Partial<LabData>;
101
- if (labData?.testType) {
95
+ if (data?.testType) {
102
96
  return {
103
97
  data: {
104
- report: `${labData.testType} results for ${context.patientName}`,
98
+ report: `${data.testType} results for ${context.patientName}`,
105
99
  status: "All values within normal range",
106
100
  },
107
101
  };
@@ -118,6 +112,7 @@ const getLabResults: Tool<
118
112
 
119
113
  const scheduleAppointment: Tool<
120
114
  HealthcareContext,
115
+ HealthcareData,
121
116
  [],
122
117
  { confirmation: string }
123
118
  > = {
@@ -127,21 +122,15 @@ const scheduleAppointment: Tool<
127
122
  type: "object",
128
123
  properties: {},
129
124
  },
130
- handler: ({
131
- data,
132
- }: {
133
- context: HealthcareContext;
134
- data?: Partial<AppointmentData>;
135
- }) => {
125
+ handler: ({ data }) => {
136
126
  // Tools access collected appointment data
137
- const appointment = data as Partial<AppointmentData>;
138
- if (!appointment?.preferredDate || !appointment?.preferredTime) {
127
+ if (!data?.preferredDate || !data?.preferredTime) {
139
128
  return { data: { confirmation: "Please provide appointment details" } };
140
129
  }
141
130
 
142
131
  return {
143
132
  data: {
144
- confirmation: `Appointment scheduled for ${appointment.preferredDate} at ${appointment.preferredTime}`,
133
+ confirmation: `Appointment scheduled for ${data.preferredDate} at ${data.preferredTime}`,
145
134
  },
146
135
  };
147
136
  },
@@ -186,40 +175,16 @@ const guidelines: Guideline<HealthcareContext>[] = [
186
175
  },
187
176
  ];
188
177
 
189
- const routes: RouteOptions<HealthcareContext>[] = [
178
+ const routes: RouteOptions<HealthcareContext, HealthcareData>[] = [
190
179
  {
191
180
  id: "route_schedule_appointment",
192
181
  title: "Schedule Appointment",
193
182
  description: "Helps the patient schedule an appointment",
194
183
  conditions: ["The patient wants to schedule an appointment"],
195
- schema: {
196
- type: "object",
197
- properties: {
198
- appointmentType: {
199
- type: "string",
200
- enum: ["checkup", "consultation", "followup"],
201
- description: "Type of appointment needed",
202
- },
203
- preferredDate: {
204
- type: "string",
205
- description: "Preferred appointment date",
206
- },
207
- preferredTime: {
208
- type: "string",
209
- description: "Preferred appointment time",
210
- },
211
- symptoms: {
212
- type: "string",
213
- description: "Description of symptoms (if applicable)",
214
- },
215
- urgency: {
216
- type: "string",
217
- enum: ["low", "medium", "high"],
218
- default: "medium",
219
- },
220
- },
221
- required: ["appointmentType", "preferredDate", "preferredTime"],
222
- },
184
+ // NEW: Required fields for route completion (instead of schema)
185
+ requiredFields: ["appointmentType", "preferredDate", "preferredTime"],
186
+ // NEW: Optional fields that enhance the experience
187
+ optionalFields: ["symptoms", "urgency"],
223
188
  guidelines: [
224
189
  {
225
190
  condition: "The patient says their visit is urgent",
@@ -249,7 +214,7 @@ const routes: RouteOptions<HealthcareContext>[] = [
249
214
  description: "Ask about symptoms",
250
215
  prompt: "Are you experiencing any symptoms?",
251
216
  collect: ["symptoms"],
252
- skipIf: (data: Partial<AppointmentData>) =>
217
+ skipIf: (data: Partial<HealthcareData>) =>
253
218
  data.appointmentType === "checkup", // Skip for checkups
254
219
  },
255
220
  {
@@ -283,25 +248,10 @@ const routes: RouteOptions<HealthcareContext>[] = [
283
248
  title: "Check Lab Results",
284
249
  description: "Retrieves and explains patient lab results",
285
250
  conditions: ["The patient wants to see their lab results"],
286
- schema: {
287
- type: "object",
288
- properties: {
289
- testType: {
290
- type: "string",
291
- description: "Type of lab test",
292
- },
293
- testDate: {
294
- type: "string",
295
- description: "Date of the lab test",
296
- },
297
- resultsNeeded: {
298
- type: "boolean",
299
- default: true,
300
- description: "Whether detailed results are needed",
301
- },
302
- },
303
- required: ["testType"],
304
- },
251
+ // NEW: Required fields for route completion
252
+ requiredFields: ["testType"],
253
+ // NEW: Optional fields
254
+ optionalFields: ["testDate", "resultsNeeded"],
305
255
  guidelines: [
306
256
  {
307
257
  condition: "The patient presses for more conclusions about results",
@@ -316,12 +266,58 @@ const routes: RouteOptions<HealthcareContext>[] = [
316
266
  title: "General Healthcare Questions",
317
267
  description: "Answer general healthcare questions",
318
268
  conditions: ["Patient asks general healthcare questions"],
319
- // No schema - conversational Q&A
269
+ // No required fields - conversational Q&A
320
270
  },
321
271
  ];
322
272
 
323
- // Create the fully configured agent
324
- const agent = new Agent<HealthcareContext>({
273
+ // Define a unified data schema for all healthcare interactions
274
+ interface HealthcareData extends AppointmentData, LabData {}
275
+
276
+ const healthcareSchema = {
277
+ type: "object",
278
+ properties: {
279
+ // Appointment fields
280
+ appointmentType: {
281
+ type: "string",
282
+ enum: ["checkup", "consultation", "followup"],
283
+ description: "Type of appointment needed",
284
+ },
285
+ preferredDate: {
286
+ type: "string",
287
+ description: "Preferred appointment date",
288
+ },
289
+ preferredTime: {
290
+ type: "string",
291
+ description: "Preferred appointment time",
292
+ },
293
+ symptoms: {
294
+ type: "string",
295
+ description: "Description of symptoms (if applicable)",
296
+ },
297
+ urgency: {
298
+ type: "string",
299
+ enum: ["low", "medium", "high"],
300
+ default: "medium",
301
+ },
302
+ // Lab fields
303
+ testType: {
304
+ type: "string",
305
+ description: "Type of lab test",
306
+ },
307
+ testDate: {
308
+ type: "string",
309
+ description: "Date of the lab test",
310
+ },
311
+ resultsNeeded: {
312
+ type: "boolean",
313
+ default: true,
314
+ description: "Whether detailed results are needed",
315
+ },
316
+ },
317
+ };
318
+
319
+ // Create the fully configured agent with agent-level schema
320
+ const agent = new Agent<HealthcareContext, HealthcareData>({
325
321
  name: "HealthBot",
326
322
  description: "A compassionate healthcare assistant",
327
323
  goal: "Provide helpful information and assist with appointments",
@@ -333,6 +329,8 @@ const agent = new Agent<HealthcareContext>({
333
329
  apiKey: process.env.GEMINI_API_KEY || "demo-key",
334
330
  model: "models/gemini-2.5-flash",
335
331
  }),
332
+ // NEW: Agent-level schema
333
+ schema: healthcareSchema,
336
334
  // Declarative initialization
337
335
  terms,
338
336
  guidelines,
@@ -381,7 +379,7 @@ async function main() {
381
379
  });
382
380
 
383
381
  console.log("šŸ¤– Agent:", response2.message);
384
- console.log("šŸ“Š Collected data:", agent.session.getData<AppointmentData | LabData>());
382
+ console.log("šŸ“Š Collected data:", agent.session.getData());
385
383
  console.log("šŸ“ Current step:", response2.session?.currentStep?.id);
386
384
 
387
385
  await agent.session.addMessage("assistant", response2.message);
@@ -396,7 +394,7 @@ async function main() {
396
394
  });
397
395
 
398
396
  console.log("šŸ¤– Agent:", response3.message);
399
- console.log("šŸ“Š Updated data:", agent.session.getData<AppointmentData | LabData>());
397
+ console.log("šŸ“Š Updated data:", agent.session.getData());
400
398
  console.log("šŸ“ Current step:", response3.session?.currentStep?.id);
401
399
 
402
400
  await agent.session.addMessage("assistant", response3.message);
@@ -405,7 +403,7 @@ async function main() {
405
403
  if (response3.isRouteComplete && response3.session) {
406
404
  console.log("\nāœ… Appointment scheduling complete!");
407
405
  await sendAppointmentConfirmation(
408
- agent.getData<AppointmentData>(response3.session.id) as AppointmentData
406
+ agent.getCollectedData() as HealthcareData
409
407
  );
410
408
  }
411
409
 
@@ -424,9 +422,9 @@ async function main() {
424
422
 
425
423
  /**
426
424
  * Mock function to send an appointment confirmation.
427
- * @param data - The appointment data.
425
+ * @param data - The healthcare data.
428
426
  */
429
- async function sendAppointmentConfirmation(data: AppointmentData) {
427
+ async function sendAppointmentConfirmation(data: HealthcareData) {
430
428
  console.log("\n" + "=".repeat(60));
431
429
  console.log("šŸš€ Sending Appointment Confirmation...");
432
430
  console.log("=".repeat(60));