@falai/agent 0.4.1 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (285) hide show
  1. package/README.md +21 -74
  2. package/dist/cjs/core/Agent.d.ts +22 -29
  3. package/dist/cjs/core/Agent.d.ts.map +1 -1
  4. package/dist/cjs/core/Agent.js +464 -291
  5. package/dist/cjs/core/Agent.js.map +1 -1
  6. package/dist/cjs/core/Events.d.ts +10 -1
  7. package/dist/cjs/core/Events.d.ts.map +1 -1
  8. package/dist/cjs/core/Events.js +3 -2
  9. package/dist/cjs/core/Events.js.map +1 -1
  10. package/dist/cjs/core/PersistenceManager.d.ts +19 -0
  11. package/dist/cjs/core/PersistenceManager.d.ts.map +1 -1
  12. package/dist/cjs/core/PersistenceManager.js +55 -0
  13. package/dist/cjs/core/PersistenceManager.js.map +1 -1
  14. package/dist/cjs/core/PromptComposer.d.ts +24 -0
  15. package/dist/cjs/core/PromptComposer.d.ts.map +1 -0
  16. package/dist/cjs/core/PromptComposer.js +127 -0
  17. package/dist/cjs/core/PromptComposer.js.map +1 -0
  18. package/dist/cjs/core/ResponseEngine.d.ts +19 -0
  19. package/dist/cjs/core/ResponseEngine.d.ts.map +1 -0
  20. package/dist/cjs/core/ResponseEngine.js +51 -0
  21. package/dist/cjs/core/ResponseEngine.js.map +1 -0
  22. package/dist/cjs/core/Route.d.ts +18 -12
  23. package/dist/cjs/core/Route.d.ts.map +1 -1
  24. package/dist/cjs/core/Route.js +15 -9
  25. package/dist/cjs/core/Route.js.map +1 -1
  26. package/dist/cjs/core/RoutingEngine.d.ts +38 -0
  27. package/dist/cjs/core/RoutingEngine.d.ts.map +1 -0
  28. package/dist/cjs/core/RoutingEngine.js +110 -0
  29. package/dist/cjs/core/RoutingEngine.js.map +1 -0
  30. package/dist/cjs/core/State.d.ts +15 -4
  31. package/dist/cjs/core/State.d.ts.map +1 -1
  32. package/dist/cjs/core/State.js +21 -2
  33. package/dist/cjs/core/State.js.map +1 -1
  34. package/dist/cjs/core/ToolExecutor.d.ts +29 -0
  35. package/dist/cjs/core/ToolExecutor.d.ts.map +1 -0
  36. package/dist/cjs/core/ToolExecutor.js +73 -0
  37. package/dist/cjs/core/ToolExecutor.js.map +1 -0
  38. package/dist/cjs/core/Transition.d.ts +5 -5
  39. package/dist/cjs/core/Transition.d.ts.map +1 -1
  40. package/dist/cjs/core/Transition.js.map +1 -1
  41. package/dist/cjs/index.d.ts +6 -8
  42. package/dist/cjs/index.d.ts.map +1 -1
  43. package/dist/cjs/index.js +8 -10
  44. package/dist/cjs/index.js.map +1 -1
  45. package/dist/cjs/providers/AnthropicProvider.d.ts.map +1 -1
  46. package/dist/cjs/providers/AnthropicProvider.js +10 -13
  47. package/dist/cjs/providers/AnthropicProvider.js.map +1 -1
  48. package/dist/cjs/providers/GeminiProvider.d.ts.map +1 -1
  49. package/dist/cjs/providers/GeminiProvider.js +12 -8
  50. package/dist/cjs/providers/GeminiProvider.js.map +1 -1
  51. package/dist/cjs/providers/OpenAIProvider.d.ts.map +1 -1
  52. package/dist/cjs/providers/OpenAIProvider.js +10 -53
  53. package/dist/cjs/providers/OpenAIProvider.js.map +1 -1
  54. package/dist/cjs/providers/OpenRouterProvider.d.ts.map +1 -1
  55. package/dist/cjs/providers/OpenRouterProvider.js +10 -53
  56. package/dist/cjs/providers/OpenRouterProvider.js.map +1 -1
  57. package/dist/cjs/types/agent.d.ts +13 -12
  58. package/dist/cjs/types/agent.d.ts.map +1 -1
  59. package/dist/cjs/types/ai.d.ts +8 -2
  60. package/dist/cjs/types/ai.d.ts.map +1 -1
  61. package/dist/cjs/types/history.d.ts +8 -0
  62. package/dist/cjs/types/history.d.ts.map +1 -1
  63. package/dist/cjs/types/index.d.ts +0 -3
  64. package/dist/cjs/types/index.d.ts.map +1 -1
  65. package/dist/cjs/types/index.js +1 -3
  66. package/dist/cjs/types/index.js.map +1 -1
  67. package/dist/cjs/types/route.d.ts +39 -4
  68. package/dist/cjs/types/route.d.ts.map +1 -1
  69. package/dist/cjs/types/routing.d.ts +16 -0
  70. package/dist/cjs/types/routing.d.ts.map +1 -0
  71. package/dist/cjs/types/routing.js +3 -0
  72. package/dist/cjs/types/routing.js.map +1 -0
  73. package/dist/cjs/types/schema.d.ts +22 -0
  74. package/dist/cjs/types/schema.d.ts.map +1 -0
  75. package/dist/cjs/types/schema.js +3 -0
  76. package/dist/cjs/types/schema.js.map +1 -0
  77. package/dist/cjs/types/session.d.ts +77 -0
  78. package/dist/cjs/types/session.d.ts.map +1 -0
  79. package/dist/cjs/types/session.js +146 -0
  80. package/dist/cjs/types/session.js.map +1 -0
  81. package/dist/cjs/types/tool.d.ts +11 -5
  82. package/dist/cjs/types/tool.d.ts.map +1 -1
  83. package/dist/cjs/utils/id.d.ts +0 -5
  84. package/dist/cjs/utils/id.d.ts.map +1 -1
  85. package/dist/cjs/utils/id.js +0 -10
  86. package/dist/cjs/utils/id.js.map +1 -1
  87. package/dist/cjs/utils/schema.d.ts +17 -0
  88. package/dist/cjs/utils/schema.d.ts.map +1 -0
  89. package/dist/cjs/utils/schema.js +32 -0
  90. package/dist/cjs/utils/schema.js.map +1 -0
  91. package/dist/core/Agent.d.ts +22 -29
  92. package/dist/core/Agent.d.ts.map +1 -1
  93. package/dist/core/Agent.js +464 -291
  94. package/dist/core/Agent.js.map +1 -1
  95. package/dist/core/Events.d.ts +10 -1
  96. package/dist/core/Events.d.ts.map +1 -1
  97. package/dist/core/Events.js +3 -2
  98. package/dist/core/Events.js.map +1 -1
  99. package/dist/core/PersistenceManager.d.ts +19 -0
  100. package/dist/core/PersistenceManager.d.ts.map +1 -1
  101. package/dist/core/PersistenceManager.js +55 -0
  102. package/dist/core/PersistenceManager.js.map +1 -1
  103. package/dist/core/PromptComposer.d.ts +24 -0
  104. package/dist/core/PromptComposer.d.ts.map +1 -0
  105. package/dist/core/PromptComposer.js +123 -0
  106. package/dist/core/PromptComposer.js.map +1 -0
  107. package/dist/core/ResponseEngine.d.ts +19 -0
  108. package/dist/core/ResponseEngine.d.ts.map +1 -0
  109. package/dist/core/ResponseEngine.js +47 -0
  110. package/dist/core/ResponseEngine.js.map +1 -0
  111. package/dist/core/Route.d.ts +18 -12
  112. package/dist/core/Route.d.ts.map +1 -1
  113. package/dist/core/Route.js +15 -9
  114. package/dist/core/Route.js.map +1 -1
  115. package/dist/core/RoutingEngine.d.ts +38 -0
  116. package/dist/core/RoutingEngine.d.ts.map +1 -0
  117. package/dist/core/RoutingEngine.js +106 -0
  118. package/dist/core/RoutingEngine.js.map +1 -0
  119. package/dist/core/State.d.ts +15 -4
  120. package/dist/core/State.d.ts.map +1 -1
  121. package/dist/core/State.js +21 -2
  122. package/dist/core/State.js.map +1 -1
  123. package/dist/core/ToolExecutor.d.ts +29 -0
  124. package/dist/core/ToolExecutor.d.ts.map +1 -0
  125. package/dist/core/ToolExecutor.js +69 -0
  126. package/dist/core/ToolExecutor.js.map +1 -0
  127. package/dist/core/Transition.d.ts +5 -5
  128. package/dist/core/Transition.d.ts.map +1 -1
  129. package/dist/core/Transition.js.map +1 -1
  130. package/dist/index.d.ts +6 -8
  131. package/dist/index.d.ts.map +1 -1
  132. package/dist/index.js +3 -5
  133. package/dist/index.js.map +1 -1
  134. package/dist/providers/AnthropicProvider.d.ts.map +1 -1
  135. package/dist/providers/AnthropicProvider.js +10 -13
  136. package/dist/providers/AnthropicProvider.js.map +1 -1
  137. package/dist/providers/GeminiProvider.d.ts.map +1 -1
  138. package/dist/providers/GeminiProvider.js +12 -8
  139. package/dist/providers/GeminiProvider.js.map +1 -1
  140. package/dist/providers/OpenAIProvider.d.ts.map +1 -1
  141. package/dist/providers/OpenAIProvider.js +10 -53
  142. package/dist/providers/OpenAIProvider.js.map +1 -1
  143. package/dist/providers/OpenRouterProvider.d.ts.map +1 -1
  144. package/dist/providers/OpenRouterProvider.js +10 -53
  145. package/dist/providers/OpenRouterProvider.js.map +1 -1
  146. package/dist/types/agent.d.ts +13 -12
  147. package/dist/types/agent.d.ts.map +1 -1
  148. package/dist/types/ai.d.ts +8 -2
  149. package/dist/types/ai.d.ts.map +1 -1
  150. package/dist/types/history.d.ts +8 -0
  151. package/dist/types/history.d.ts.map +1 -1
  152. package/dist/types/index.d.ts +0 -3
  153. package/dist/types/index.d.ts.map +1 -1
  154. package/dist/types/index.js +0 -1
  155. package/dist/types/index.js.map +1 -1
  156. package/dist/types/route.d.ts +39 -4
  157. package/dist/types/route.d.ts.map +1 -1
  158. package/dist/types/routing.d.ts +16 -0
  159. package/dist/types/routing.d.ts.map +1 -0
  160. package/dist/types/routing.js +2 -0
  161. package/dist/types/routing.js.map +1 -0
  162. package/dist/types/schema.d.ts +22 -0
  163. package/dist/types/schema.d.ts.map +1 -0
  164. package/dist/types/schema.js +2 -0
  165. package/dist/types/schema.js.map +1 -0
  166. package/dist/types/session.d.ts +77 -0
  167. package/dist/types/session.d.ts.map +1 -0
  168. package/dist/types/session.js +138 -0
  169. package/dist/types/session.js.map +1 -0
  170. package/dist/types/tool.d.ts +11 -5
  171. package/dist/types/tool.d.ts.map +1 -1
  172. package/dist/utils/id.d.ts +0 -5
  173. package/dist/utils/id.d.ts.map +1 -1
  174. package/dist/utils/id.js +0 -9
  175. package/dist/utils/id.js.map +1 -1
  176. package/dist/utils/schema.d.ts +17 -0
  177. package/dist/utils/schema.d.ts.map +1 -0
  178. package/dist/utils/schema.js +27 -0
  179. package/dist/utils/schema.js.map +1 -0
  180. package/docs/ADAPTERS.md +83 -3
  181. package/docs/API_REFERENCE.md +329 -104
  182. package/docs/ARCHITECTURE.md +284 -286
  183. package/docs/CONSTRUCTOR_OPTIONS.md +192 -135
  184. package/docs/CONTEXT_MANAGEMENT.md +311 -28
  185. package/docs/CONTRIBUTING.md +1 -1
  186. package/docs/DOMAINS.md +61 -0
  187. package/docs/GETTING_STARTED.md +177 -88
  188. package/docs/PERSISTENCE.md +170 -23
  189. package/docs/README.md +7 -10
  190. package/examples/business-onboarding.ts +21 -9
  191. package/examples/company-qna-agent.ts +508 -0
  192. package/examples/declarative-agent.ts +143 -26
  193. package/examples/domain-scoping.ts +31 -10
  194. package/examples/extracted-data-modification.ts +415 -0
  195. package/examples/healthcare-agent.ts +194 -90
  196. package/examples/openai-agent.ts +67 -25
  197. package/examples/opensearch-persistence.ts +455 -151
  198. package/examples/persistent-onboarding.ts +162 -96
  199. package/examples/prisma-persistence.ts +371 -125
  200. package/examples/redis-persistence.ts +393 -23
  201. package/examples/rules-prohibitions.ts +32 -11
  202. package/examples/streaming-agent.ts +61 -13
  203. package/examples/travel-agent.ts +266 -133
  204. package/package.json +1 -1
  205. package/src/core/Agent.ts +668 -356
  206. package/src/core/Events.ts +12 -2
  207. package/src/core/PersistenceManager.ts +81 -0
  208. package/src/core/PromptComposer.ts +143 -0
  209. package/src/core/ResponseEngine.ts +82 -0
  210. package/src/core/Route.ts +32 -17
  211. package/src/core/RoutingEngine.ts +165 -0
  212. package/src/core/State.ts +55 -15
  213. package/src/core/ToolExecutor.ts +117 -0
  214. package/src/core/Transition.ts +5 -5
  215. package/src/index.ts +12 -21
  216. package/src/providers/AnthropicProvider.ts +10 -13
  217. package/src/providers/GeminiProvider.ts +12 -8
  218. package/src/providers/OpenAIProvider.ts +10 -56
  219. package/src/providers/OpenRouterProvider.ts +10 -56
  220. package/src/types/agent.ts +16 -13
  221. package/src/types/ai.ts +6 -2
  222. package/src/types/history.ts +8 -0
  223. package/src/types/index.ts +0 -11
  224. package/src/types/route.ts +41 -5
  225. package/src/types/routing.ts +18 -0
  226. package/src/types/schema.ts +23 -0
  227. package/src/types/session.ts +219 -0
  228. package/src/types/tool.ts +29 -7
  229. package/src/utils/id.ts +0 -10
  230. package/src/utils/schema.ts +32 -0
  231. package/dist/cjs/core/ConditionEvaluator.d.ts +0 -72
  232. package/dist/cjs/core/ConditionEvaluator.d.ts.map +0 -1
  233. package/dist/cjs/core/ConditionEvaluator.js +0 -272
  234. package/dist/cjs/core/ConditionEvaluator.js.map +0 -1
  235. package/dist/cjs/core/Observation.d.ts +0 -24
  236. package/dist/cjs/core/Observation.d.ts.map +0 -1
  237. package/dist/cjs/core/Observation.js +0 -39
  238. package/dist/cjs/core/Observation.js.map +0 -1
  239. package/dist/cjs/core/PreparationEngine.d.ts +0 -116
  240. package/dist/cjs/core/PreparationEngine.d.ts.map +0 -1
  241. package/dist/cjs/core/PreparationEngine.js +0 -353
  242. package/dist/cjs/core/PreparationEngine.js.map +0 -1
  243. package/dist/cjs/core/PromptBuilder.d.ts +0 -136
  244. package/dist/cjs/core/PromptBuilder.d.ts.map +0 -1
  245. package/dist/cjs/core/PromptBuilder.js +0 -421
  246. package/dist/cjs/core/PromptBuilder.js.map +0 -1
  247. package/dist/cjs/types/observation.d.ts +0 -27
  248. package/dist/cjs/types/observation.d.ts.map +0 -1
  249. package/dist/cjs/types/observation.js +0 -6
  250. package/dist/cjs/types/observation.js.map +0 -1
  251. package/dist/cjs/types/prompt.d.ts +0 -46
  252. package/dist/cjs/types/prompt.d.ts.map +0 -1
  253. package/dist/cjs/types/prompt.js +0 -19
  254. package/dist/cjs/types/prompt.js.map +0 -1
  255. package/dist/core/ConditionEvaluator.d.ts +0 -72
  256. package/dist/core/ConditionEvaluator.d.ts.map +0 -1
  257. package/dist/core/ConditionEvaluator.js +0 -268
  258. package/dist/core/ConditionEvaluator.js.map +0 -1
  259. package/dist/core/Observation.d.ts +0 -24
  260. package/dist/core/Observation.d.ts.map +0 -1
  261. package/dist/core/Observation.js +0 -35
  262. package/dist/core/Observation.js.map +0 -1
  263. package/dist/core/PreparationEngine.d.ts +0 -116
  264. package/dist/core/PreparationEngine.d.ts.map +0 -1
  265. package/dist/core/PreparationEngine.js +0 -349
  266. package/dist/core/PreparationEngine.js.map +0 -1
  267. package/dist/core/PromptBuilder.d.ts +0 -136
  268. package/dist/core/PromptBuilder.d.ts.map +0 -1
  269. package/dist/core/PromptBuilder.js +0 -417
  270. package/dist/core/PromptBuilder.js.map +0 -1
  271. package/dist/types/observation.d.ts +0 -27
  272. package/dist/types/observation.d.ts.map +0 -1
  273. package/dist/types/observation.js +0 -5
  274. package/dist/types/observation.js.map +0 -1
  275. package/dist/types/prompt.d.ts +0 -46
  276. package/dist/types/prompt.d.ts.map +0 -1
  277. package/dist/types/prompt.js +0 -16
  278. package/dist/types/prompt.js.map +0 -1
  279. package/docs/STRUCTURE.md +0 -58
  280. package/src/core/ConditionEvaluator.ts +0 -381
  281. package/src/core/Observation.ts +0 -47
  282. package/src/core/PreparationEngine.ts +0 -561
  283. package/src/core/PromptBuilder.ts +0 -617
  284. package/src/types/observation.ts +0 -29
  285. package/src/types/prompt.ts +0 -49
@@ -1,8 +1,8 @@
1
1
  /**
2
- * Example: Using Prisma ORM for Persistence
2
+ * Example: Using Prisma ORM for Persistence with Session State
3
3
  *
4
4
  * This example shows how to use @falai/agent with Prisma for automatic
5
- * session and message persistence - as easy as using an AI provider!
5
+ * session state persistence - with the new data-driven architecture!
6
6
  */
7
7
 
8
8
  import {
@@ -11,6 +11,7 @@ import {
11
11
  PrismaAdapter,
12
12
  createMessageEvent,
13
13
  EventSource,
14
+ createSession,
14
15
  } from "../src/index";
15
16
 
16
17
  // @ts-ignore
@@ -38,14 +39,24 @@ import { PrismaClient } from "@prisma/client";
38
39
  // Example context type
39
40
  interface ConversationContext {
40
41
  userId: string;
41
- sessionId: string;
42
42
  userName: string;
43
- preferences: {
44
- language: string;
45
- theme: string;
43
+ currentBooking?: {
44
+ destination?: string;
45
+ departureDate?: string;
46
+ returnDate?: string;
47
+ passengers?: number;
46
48
  };
47
49
  }
48
50
 
51
+ // Extracted data type for flight booking
52
+ interface FlightBookingData {
53
+ destination: string;
54
+ departureDate: string;
55
+ returnDate?: string;
56
+ passengers: number;
57
+ cabinClass: "economy" | "premium" | "business" | "first";
58
+ }
59
+
49
60
  async function example() {
50
61
  // Initialize Prisma client
51
62
  const prisma = new PrismaClient();
@@ -53,32 +64,103 @@ async function example() {
53
64
  const userId = "user_123";
54
65
 
55
66
  /**
56
- * Create Agent with Persistence - Simple Provider Pattern! ✨
67
+ * Create Agent with Persistence - New Session-Based Pattern! ✨
57
68
  */
58
69
  const agent = new Agent<ConversationContext>({
59
- name: "Shopping Assistant",
60
- description: "A helpful shopping assistant",
70
+ name: "Travel Assistant",
71
+ description: "A helpful travel booking assistant",
72
+ goal: "Help users book flights with ease",
61
73
  ai: new GeminiProvider({
62
74
  apiKey: process.env.GEMINI_API_KEY!,
63
75
  model: "models/gemini-2.0-flash-exp",
64
76
  }),
65
77
  context: {
66
78
  userId,
67
- sessionId: "", // Will be set when we create/load a session
68
79
  userName: "Alice",
69
- preferences: {
70
- language: "en",
71
- theme: "light",
72
- },
73
80
  },
74
81
  // ✨ Just pass the adapter - that's it!
75
82
  persistence: {
76
83
  adapter: new PrismaAdapter({ prisma }),
77
- autoSave: true,
84
+ autoSave: true, // Auto-saves session state after each response
78
85
  userId,
79
86
  },
80
87
  });
81
88
 
89
+ /**
90
+ * Create a route with data extraction schema
91
+ */
92
+ const flightRoute = agent.createRoute<FlightBookingData>({
93
+ title: "Book a Flight",
94
+ description: "Help user book a flight ticket",
95
+ conditions: [
96
+ "User wants to book a flight",
97
+ "User mentions travel, flying, or booking tickets",
98
+ ],
99
+ gatherSchema: {
100
+ type: "object",
101
+ properties: {
102
+ destination: {
103
+ type: "string",
104
+ description: "Destination city or airport",
105
+ },
106
+ departureDate: {
107
+ type: "string",
108
+ description: "Departure date (YYYY-MM-DD)",
109
+ },
110
+ returnDate: {
111
+ type: "string",
112
+ description: "Return date (YYYY-MM-DD)",
113
+ },
114
+ passengers: {
115
+ type: "number",
116
+ minimum: 1,
117
+ maximum: 9,
118
+ description: "Number of passengers",
119
+ },
120
+ cabinClass: {
121
+ type: "string",
122
+ enum: ["economy", "premium", "business", "first"],
123
+ default: "economy",
124
+ description: "Cabin class preference",
125
+ },
126
+ },
127
+ required: ["destination", "departureDate", "passengers", "cabinClass"],
128
+ },
129
+ });
130
+
131
+ // State flow with smart data gathering
132
+ const askDestination = flightRoute.initialState.transitionTo({
133
+ chatState: "Ask where they want to fly",
134
+ gather: ["destination"],
135
+ skipIf: (extracted) => !!extracted.destination,
136
+ });
137
+
138
+ const askDates = askDestination.transitionTo({
139
+ chatState: "Ask about travel dates",
140
+ gather: ["departureDate", "returnDate"],
141
+ skipIf: (extracted) => !!extracted.departureDate,
142
+ requiredData: ["destination"],
143
+ });
144
+
145
+ const askPassengers = askDates.transitionTo({
146
+ chatState: "Ask how many passengers",
147
+ gather: ["passengers"],
148
+ skipIf: (extracted) => !!extracted.passengers,
149
+ requiredData: ["destination", "departureDate"],
150
+ });
151
+
152
+ const askCabinClass = askPassengers.transitionTo({
153
+ chatState: "Ask about cabin class preference",
154
+ gather: ["cabinClass"],
155
+ skipIf: (extracted) => !!extracted.cabinClass,
156
+ requiredData: ["destination", "departureDate", "passengers"],
157
+ });
158
+
159
+ const confirmBooking = askCabinClass.transitionTo({
160
+ chatState: "Present options and confirm booking details",
161
+ requiredData: ["destination", "departureDate", "passengers", "cabinClass"],
162
+ });
163
+
82
164
  /**
83
165
  * Get persistence manager from agent
84
166
  */
@@ -89,83 +171,156 @@ async function example() {
89
171
  }
90
172
 
91
173
  /**
92
- * Create or find a session
174
+ * Create or find a session - New Pattern!
93
175
  */
94
- let session = await persistence.findActiveSession(userId);
95
-
96
- if (!session) {
97
- session = await persistence.createSession({
176
+ let sessionResult =
177
+ await persistence.createSessionWithState<FlightBookingData>({
98
178
  userId,
99
- agentName: "Shopping Assistant",
179
+ agentName: "Travel Assistant",
100
180
  initialData: {
101
- language: "en",
102
- theme: "light",
181
+ cabinClass: "economy", // Default value
103
182
  },
104
183
  });
105
- console.log("✨ Created new session:", session.id);
106
- } else {
107
- console.log("📂 Found active session:", session.id);
108
- }
109
184
 
110
- // Update context with session ID
111
- await agent.updateContext({
112
- sessionId: session.id,
113
- } as Partial<ConversationContext>);
185
+ let session = sessionResult.sessionState;
186
+ const dbSessionId = sessionResult.sessionData.id;
187
+
188
+ console.log("✨ Created new session:", dbSessionId);
189
+ console.log("📊 Initial session state:", {
190
+ currentRoute: session.currentRoute,
191
+ extracted: session.extracted,
192
+ });
114
193
 
115
194
  /**
116
195
  * Load conversation history
117
196
  */
118
- const history = await persistence.loadSessionHistory(session.id);
197
+ const history = await persistence.loadSessionHistory(dbSessionId);
119
198
  console.log(`📜 Loaded ${history.length} messages from history`);
120
199
 
121
200
  /**
122
- * Send a message
201
+ * Turn 1: User provides multiple fields at once
123
202
  */
124
- const userMessage = createMessageEvent(
203
+ console.log("\n--- Turn 1 ---");
204
+ const userMessage1 = createMessageEvent(
125
205
  EventSource.CUSTOMER,
126
206
  "Alice",
127
- "I'm looking for a winter jacket"
207
+ "I want to fly to Paris on June 15 with 2 people"
128
208
  );
129
209
 
210
+ history.push(userMessage1);
211
+
212
+ const response1 = await agent.respond({
213
+ history,
214
+ session, // Pass session state
215
+ });
216
+
217
+ console.log("🤖 Agent:", response1.message);
218
+ console.log("📊 Session state after turn 1:", {
219
+ currentRoute: response1.session?.currentRoute?.title,
220
+ currentState: response1.session?.currentState?.id,
221
+ extracted: response1.session?.extracted,
222
+ });
223
+
130
224
  // Save user message
131
225
  await persistence.saveMessage({
132
- sessionId: session.id,
226
+ sessionId: dbSessionId,
133
227
  userId,
134
228
  role: "user",
135
- content: "I'm looking for a winter jacket",
136
- event: userMessage,
229
+ content: userMessage1.data.message,
230
+ event: userMessage1,
231
+ });
232
+
233
+ // Save agent message (session state is auto-saved by Agent!)
234
+ await persistence.saveMessage({
235
+ sessionId: dbSessionId,
236
+ userId,
237
+ role: "agent",
238
+ content: response1.message,
239
+ route: response1.session?.currentRoute?.id,
240
+ state: response1.session?.currentState?.id,
137
241
  });
138
242
 
139
- history.push(userMessage);
243
+ // Update session for next turn
244
+ session = response1.session!;
140
245
 
141
- // Generate agent response
142
- const response = await agent.respond({ history });
143
- console.log("🤖 Agent:", response.message);
246
+ /**
247
+ * Turn 2: User changes their mind
248
+ */
249
+ console.log("\n--- Turn 2 ---");
250
+ const userMessage2 = createMessageEvent(
251
+ EventSource.CUSTOMER,
252
+ "Alice",
253
+ "Actually, make that Tokyo instead, and premium class"
254
+ );
255
+
256
+ history.push(
257
+ createMessageEvent(
258
+ EventSource.AI_AGENT,
259
+ "Travel Assistant",
260
+ response1.message
261
+ )
262
+ );
263
+ history.push(userMessage2);
264
+
265
+ const response2 = await agent.respond({
266
+ history,
267
+ session, // Pass updated session
268
+ });
269
+
270
+ console.log("🤖 Agent:", response2.message);
271
+ console.log("📊 Session state after turn 2:", {
272
+ currentRoute: response2.session?.currentRoute?.title,
273
+ currentState: response2.session?.currentState?.id,
274
+ extracted: response2.session?.extracted,
275
+ });
144
276
 
145
- // Save agent message
277
+ // Save messages
146
278
  await persistence.saveMessage({
147
- sessionId: session.id,
279
+ sessionId: dbSessionId,
280
+ userId,
281
+ role: "user",
282
+ content: userMessage2.data.message,
283
+ event: userMessage2,
284
+ });
285
+
286
+ await persistence.saveMessage({
287
+ sessionId: dbSessionId,
148
288
  userId,
149
289
  role: "agent",
150
- content: response.message,
151
- route: response.route?.id,
152
- state: response.state?.id,
153
- toolCalls: response.toolCalls,
290
+ content: response2.message,
291
+ route: response2.session?.currentRoute?.id,
292
+ state: response2.session?.currentState?.id,
293
+ });
294
+
295
+ session = response2.session!;
296
+
297
+ /**
298
+ * Load session state from database (demonstrates persistence)
299
+ */
300
+ console.log("\n--- Loading Session from Database ---");
301
+ const loadedSession = await persistence.loadSessionState<FlightBookingData>(
302
+ dbSessionId
303
+ );
304
+
305
+ console.log("📥 Loaded session state:", {
306
+ currentRoute: loadedSession?.currentRoute?.title,
307
+ currentState: loadedSession?.currentState?.id,
308
+ extracted: loadedSession?.extracted,
154
309
  });
155
310
 
156
311
  /**
157
312
  * Query sessions and messages
158
313
  */
159
314
  const userSessions = await persistence.getUserSessions(userId);
160
- console.log(`👤 User has ${userSessions.length} total sessions`);
315
+ console.log(`\n👤 User has ${userSessions.length} total sessions`);
161
316
 
162
- const messages = await persistence.getSessionMessages(session.id);
317
+ const messages = await persistence.getSessionMessages(dbSessionId);
163
318
  console.log(`💬 Session has ${messages.length} messages`);
164
319
 
165
320
  /**
166
321
  * Complete the session
167
322
  */
168
- await persistence.completeSession(session.id);
323
+ await persistence.completeSession(dbSessionId);
169
324
  console.log("✅ Session completed");
170
325
 
171
326
  /**
@@ -175,59 +330,67 @@ async function example() {
175
330
  }
176
331
 
177
332
  /**
178
- * Advanced Example: Using with Lifecycle Hooks
333
+ * Advanced Example: Session State with Lifecycle Hooks
179
334
  */
180
335
  async function advancedExample() {
181
336
  const prisma = new PrismaClient();
182
- const userId = "user_123";
337
+ const userId = "user_456";
183
338
 
184
- const agent = new Agent<ConversationContext>({
185
- name: "Smart Assistant",
186
- description: "An intelligent assistant with persistent state",
339
+ interface UserContext {
340
+ userId: string;
341
+ userName: string;
342
+ preferences: {
343
+ currency: string;
344
+ language: string;
345
+ };
346
+ }
347
+
348
+ interface OnboardingData {
349
+ fullName: string;
350
+ email: string;
351
+ phoneNumber: string;
352
+ country: string;
353
+ }
354
+
355
+ const agent = new Agent<UserContext>({
356
+ name: "Onboarding Assistant",
357
+ description: "Help new users get started",
187
358
  ai: new GeminiProvider({
188
359
  apiKey: process.env.GEMINI_API_KEY!,
189
360
  model: "models/gemini-2.0-flash-exp",
190
361
  }),
191
362
  context: {
192
363
  userId,
193
- sessionId: "",
194
- userName: "Alice",
364
+ userName: "Bob",
195
365
  preferences: {
366
+ currency: "USD",
196
367
  language: "en",
197
- theme: "light",
198
368
  },
199
369
  },
200
- // Lifecycle hooks for automatic context sync
370
+ // Lifecycle hooks for session state enrichment
201
371
  hooks: {
202
- // Load fresh context before each response
203
- beforeRespond: async (currentContext) => {
204
- const persistence = agent.getPersistenceManager();
205
- if (!persistence) return currentContext;
206
-
207
- const freshSession = await persistence.getSession(
208
- currentContext.sessionId
209
- );
210
- return {
211
- ...currentContext,
212
- preferences:
213
- (
214
- freshSession?.collectedData as {
215
- preferences?: typeof currentContext.preferences;
216
- }
217
- )?.preferences || currentContext.preferences,
218
- };
372
+ // Enrich extracted data before saving
373
+ onExtractedUpdate: async (extracted, previous) => {
374
+ console.log("🔄 Extracted data updated:", { extracted, previous });
375
+
376
+ // Normalize phone numbers
377
+ if (extracted.phoneNumber) {
378
+ extracted.phoneNumber = extracted.phoneNumber.replace(/\D/g, "");
379
+ }
380
+
381
+ // Validate email
382
+ if (extracted.email && !extracted.email.includes("@")) {
383
+ console.warn("⚠️ Invalid email detected");
384
+ }
385
+
386
+ return extracted;
219
387
  },
220
- // Automatically persist context updates
221
- onContextUpdate: async (newContext) => {
222
- const persistence = agent.getPersistenceManager();
223
- if (!persistence) return;
224
-
225
- await persistence.updateCollectedData(newContext.sessionId, {
226
- preferences: newContext.preferences,
227
- });
388
+
389
+ // Update context when session state changes
390
+ onContextUpdate: async (newContext, oldContext) => {
391
+ console.log("🔄 Context updated:", { newContext, oldContext });
228
392
  },
229
393
  },
230
- // ✨ Same simple adapter pattern!
231
394
  persistence: {
232
395
  adapter: new PrismaAdapter({ prisma }),
233
396
  autoSave: true,
@@ -235,26 +398,79 @@ async function advancedExample() {
235
398
  },
236
399
  });
237
400
 
238
- // Create a session
239
- const persistence = agent.getPersistenceManager();
240
- const session = await persistence!.createSession({
241
- userId,
242
- agentName: "Smart Assistant",
401
+ // Create onboarding route
402
+ const onboardingRoute = agent.createRoute<OnboardingData>({
403
+ title: "User Onboarding",
404
+ description: "Collect user information for account setup",
405
+ gatherSchema: {
406
+ type: "object",
407
+ properties: {
408
+ fullName: { type: "string" },
409
+ email: { type: "string" },
410
+ phoneNumber: { type: "string" },
411
+ country: { type: "string" },
412
+ },
413
+ required: ["fullName", "email", "country"],
414
+ },
243
415
  });
244
416
 
245
- await agent.updateContext({
246
- sessionId: session.id,
247
- } as Partial<ConversationContext>);
417
+ onboardingRoute.initialState
418
+ .transitionTo({
419
+ chatState: "Welcome and ask for name",
420
+ gather: ["fullName"],
421
+ skipIf: (data) => !!data.fullName,
422
+ })
423
+ .transitionTo({
424
+ chatState: "Ask for email",
425
+ gather: ["email"],
426
+ skipIf: (data) => !!data.email,
427
+ })
428
+ .transitionTo({
429
+ chatState: "Ask for phone number (optional)",
430
+ gather: ["phoneNumber"],
431
+ })
432
+ .transitionTo({
433
+ chatState: "Ask for country",
434
+ gather: ["country"],
435
+ skipIf: (data) => !!data.country,
436
+ })
437
+ .transitionTo({
438
+ chatState: "Confirm and complete onboarding",
439
+ });
248
440
 
249
- // Now context updates are automatically persisted!
250
- await agent.updateContext({
251
- preferences: {
252
- language: "es",
253
- theme: "dark",
254
- },
255
- } as Partial<ConversationContext>);
441
+ const persistence = agent.getPersistenceManager()!;
442
+
443
+ // Create session with state
444
+ const { sessionData, sessionState } =
445
+ await persistence.createSessionWithState<OnboardingData>({
446
+ userId,
447
+ agentName: "Onboarding Assistant",
448
+ });
256
449
 
257
- console.log("🎉 Context updates automatically saved to database!");
450
+ console.log(" Created onboarding session:", sessionData.id);
451
+
452
+ // Simulate conversation
453
+ const history = [];
454
+ let session = sessionState;
455
+
456
+ const response = await agent.respond({
457
+ history: [
458
+ createMessageEvent(EventSource.CUSTOMER, "Bob", "Hi, I'm new here!"),
459
+ ],
460
+ session,
461
+ });
462
+
463
+ console.log("🤖 Agent:", response.message);
464
+ console.log("📊 Extracted so far:", response.session?.extracted);
465
+
466
+ await persistence.saveMessage({
467
+ sessionId: sessionData.id,
468
+ userId,
469
+ role: "agent",
470
+ content: response.message,
471
+ });
472
+
473
+ console.log("✅ Session state automatically saved to database!");
258
474
 
259
475
  await prisma.$disconnect();
260
476
  }
@@ -265,42 +481,72 @@ async function advancedExample() {
265
481
  async function quickStart() {
266
482
  const prisma = new PrismaClient();
267
483
 
268
- // That's it! Just create the adapter and pass it
484
+ interface ContactFormData {
485
+ name: string;
486
+ email: string;
487
+ message: string;
488
+ }
489
+
269
490
  const agent = new Agent({
270
- name: "My Agent",
271
- description: "A helpful assistant",
491
+ name: "Support Agent",
272
492
  ai: new GeminiProvider({
273
493
  apiKey: process.env.GEMINI_API_KEY!,
274
- model: "models/gemini-2.5-flash",
494
+ model: "models/gemini-2.0-flash-exp",
275
495
  }),
276
496
  persistence: {
277
- adapter: new PrismaAdapter({ prisma }), // ✨ Simple!
278
- userId: "user_123",
497
+ adapter: new PrismaAdapter({ prisma }),
498
+ userId: "user_789",
499
+ autoSave: true, // ✨ Automatically saves session state!
279
500
  },
280
501
  });
281
502
 
282
- // Get persistence manager
283
- const persistence = agent.getPersistenceManager();
284
- if (!persistence) return;
285
-
286
- // Create session
287
- const session = await persistence.createSession({
288
- userId: "user_123",
289
- agentName: "My Agent",
503
+ // Create a simple contact form route
504
+ const contactRoute = agent.createRoute<ContactFormData>({
505
+ title: "Contact Form",
506
+ gatherSchema: {
507
+ type: "object",
508
+ properties: {
509
+ name: { type: "string" },
510
+ email: { type: "string" },
511
+ message: { type: "string" },
512
+ },
513
+ required: ["name", "email", "message"],
514
+ },
290
515
  });
291
516
 
292
- // Load history and respond
293
- const history = await persistence.loadSessionHistory(session.id);
294
- const response = await agent.respond({ history });
517
+ contactRoute.initialState
518
+ .transitionTo({
519
+ chatState: "Collect all information",
520
+ gather: ["name", "email", "message"],
521
+ })
522
+ .transitionTo({
523
+ chatState: "Confirm submission",
524
+ });
295
525
 
296
- // Save message
297
- await persistence.saveMessage({
298
- sessionId: session.id,
299
- role: "agent",
300
- content: response.message,
526
+ const persistence = agent.getPersistenceManager()!;
527
+
528
+ // Create session with state support
529
+ const { sessionData, sessionState } =
530
+ await persistence.createSessionWithState<ContactFormData>({
531
+ userId: "user_789",
532
+ agentName: "Support Agent",
533
+ });
534
+
535
+ // Chat!
536
+ const response = await agent.respond({
537
+ history: [
538
+ createMessageEvent(
539
+ EventSource.CUSTOMER,
540
+ "User",
541
+ "I need help, my name is John and my email is john@example.com"
542
+ ),
543
+ ],
544
+ session: sessionState,
301
545
  });
302
546
 
303
- console.log("✅ Done! Messages automatically saved to Prisma.");
547
+ console.log("✅ Response:", response.message);
548
+ console.log("📊 Extracted:", response.session?.extracted);
549
+ console.log("💾 Session state auto-saved to Prisma!");
304
550
 
305
551
  await prisma.$disconnect();
306
552
  }