@falai/agent 0.1.0-alpha2

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 (499) hide show
  1. package/README.md +797 -0
  2. package/dist/cjs/package.json +1 -0
  3. package/dist/cjs/src/adapters/MemoryAdapter.d.ts +47 -0
  4. package/dist/cjs/src/adapters/MemoryAdapter.d.ts.map +1 -0
  5. package/dist/cjs/src/adapters/MemoryAdapter.js +202 -0
  6. package/dist/cjs/src/adapters/MemoryAdapter.js.map +1 -0
  7. package/dist/cjs/src/adapters/MongoAdapter.d.ts +97 -0
  8. package/dist/cjs/src/adapters/MongoAdapter.d.ts.map +1 -0
  9. package/dist/cjs/src/adapters/MongoAdapter.js +168 -0
  10. package/dist/cjs/src/adapters/MongoAdapter.js.map +1 -0
  11. package/dist/cjs/src/adapters/OpenSearchAdapter.d.ts +169 -0
  12. package/dist/cjs/src/adapters/OpenSearchAdapter.d.ts.map +1 -0
  13. package/dist/cjs/src/adapters/OpenSearchAdapter.js +458 -0
  14. package/dist/cjs/src/adapters/OpenSearchAdapter.js.map +1 -0
  15. package/dist/cjs/src/adapters/PostgreSQLAdapter.d.ts +71 -0
  16. package/dist/cjs/src/adapters/PostgreSQLAdapter.d.ts.map +1 -0
  17. package/dist/cjs/src/adapters/PostgreSQLAdapter.js +260 -0
  18. package/dist/cjs/src/adapters/PostgreSQLAdapter.js.map +1 -0
  19. package/dist/cjs/src/adapters/PrismaAdapter.d.ts +115 -0
  20. package/dist/cjs/src/adapters/PrismaAdapter.d.ts.map +1 -0
  21. package/dist/cjs/src/adapters/PrismaAdapter.js +366 -0
  22. package/dist/cjs/src/adapters/PrismaAdapter.js.map +1 -0
  23. package/dist/cjs/src/adapters/RedisAdapter.d.ts +71 -0
  24. package/dist/cjs/src/adapters/RedisAdapter.d.ts.map +1 -0
  25. package/dist/cjs/src/adapters/RedisAdapter.js +231 -0
  26. package/dist/cjs/src/adapters/RedisAdapter.js.map +1 -0
  27. package/dist/cjs/src/adapters/SQLiteAdapter.d.ts +69 -0
  28. package/dist/cjs/src/adapters/SQLiteAdapter.d.ts.map +1 -0
  29. package/dist/cjs/src/adapters/SQLiteAdapter.js +312 -0
  30. package/dist/cjs/src/adapters/SQLiteAdapter.js.map +1 -0
  31. package/dist/cjs/src/adapters/index.d.ts +17 -0
  32. package/dist/cjs/src/adapters/index.d.ts.map +1 -0
  33. package/dist/cjs/src/adapters/index.js +21 -0
  34. package/dist/cjs/src/adapters/index.js.map +1 -0
  35. package/dist/cjs/src/constants/index.d.ts +10 -0
  36. package/dist/cjs/src/constants/index.d.ts.map +1 -0
  37. package/dist/cjs/src/constants/index.js +13 -0
  38. package/dist/cjs/src/constants/index.js.map +1 -0
  39. package/dist/cjs/src/core/Agent.d.ts +232 -0
  40. package/dist/cjs/src/core/Agent.d.ts.map +1 -0
  41. package/dist/cjs/src/core/Agent.js +741 -0
  42. package/dist/cjs/src/core/Agent.js.map +1 -0
  43. package/dist/cjs/src/core/Events.d.ts +26 -0
  44. package/dist/cjs/src/core/Events.d.ts.map +1 -0
  45. package/dist/cjs/src/core/Events.js +144 -0
  46. package/dist/cjs/src/core/Events.js.map +1 -0
  47. package/dist/cjs/src/core/PersistenceManager.d.ts +98 -0
  48. package/dist/cjs/src/core/PersistenceManager.d.ts.map +1 -0
  49. package/dist/cjs/src/core/PersistenceManager.js +261 -0
  50. package/dist/cjs/src/core/PersistenceManager.js.map +1 -0
  51. package/dist/cjs/src/core/PromptComposer.d.ts +27 -0
  52. package/dist/cjs/src/core/PromptComposer.d.ts.map +1 -0
  53. package/dist/cjs/src/core/PromptComposer.js +194 -0
  54. package/dist/cjs/src/core/PromptComposer.js.map +1 -0
  55. package/dist/cjs/src/core/ResponseEngine.d.ts +32 -0
  56. package/dist/cjs/src/core/ResponseEngine.d.ts.map +1 -0
  57. package/dist/cjs/src/core/ResponseEngine.js +202 -0
  58. package/dist/cjs/src/core/ResponseEngine.js.map +1 -0
  59. package/dist/cjs/src/core/ResponseModal.d.ts +222 -0
  60. package/dist/cjs/src/core/ResponseModal.d.ts.map +1 -0
  61. package/dist/cjs/src/core/ResponseModal.js +1588 -0
  62. package/dist/cjs/src/core/ResponseModal.js.map +1 -0
  63. package/dist/cjs/src/core/ResponsePipeline.d.ts +175 -0
  64. package/dist/cjs/src/core/ResponsePipeline.d.ts.map +1 -0
  65. package/dist/cjs/src/core/ResponsePipeline.js +549 -0
  66. package/dist/cjs/src/core/ResponsePipeline.js.map +1 -0
  67. package/dist/cjs/src/core/Route.d.ts +181 -0
  68. package/dist/cjs/src/core/Route.d.ts.map +1 -0
  69. package/dist/cjs/src/core/Route.js +541 -0
  70. package/dist/cjs/src/core/Route.js.map +1 -0
  71. package/dist/cjs/src/core/RoutingEngine.d.ts +159 -0
  72. package/dist/cjs/src/core/RoutingEngine.d.ts.map +1 -0
  73. package/dist/cjs/src/core/RoutingEngine.js +961 -0
  74. package/dist/cjs/src/core/RoutingEngine.js.map +1 -0
  75. package/dist/cjs/src/core/SessionManager.d.ts +94 -0
  76. package/dist/cjs/src/core/SessionManager.d.ts.map +1 -0
  77. package/dist/cjs/src/core/SessionManager.js +239 -0
  78. package/dist/cjs/src/core/SessionManager.js.map +1 -0
  79. package/dist/cjs/src/core/Step.d.ts +170 -0
  80. package/dist/cjs/src/core/Step.d.ts.map +1 -0
  81. package/dist/cjs/src/core/Step.js +448 -0
  82. package/dist/cjs/src/core/Step.js.map +1 -0
  83. package/dist/cjs/src/core/ToolManager.d.ts +234 -0
  84. package/dist/cjs/src/core/ToolManager.d.ts.map +1 -0
  85. package/dist/cjs/src/core/ToolManager.js +1117 -0
  86. package/dist/cjs/src/core/ToolManager.js.map +1 -0
  87. package/dist/cjs/src/index.d.ts +44 -0
  88. package/dist/cjs/src/index.d.ts.map +1 -0
  89. package/dist/cjs/src/index.js +88 -0
  90. package/dist/cjs/src/index.js.map +1 -0
  91. package/dist/cjs/src/providers/AnthropicProvider.d.ts +43 -0
  92. package/dist/cjs/src/providers/AnthropicProvider.d.ts.map +1 -0
  93. package/dist/cjs/src/providers/AnthropicProvider.js +377 -0
  94. package/dist/cjs/src/providers/AnthropicProvider.js.map +1 -0
  95. package/dist/cjs/src/providers/GeminiProvider.d.ts +58 -0
  96. package/dist/cjs/src/providers/GeminiProvider.d.ts.map +1 -0
  97. package/dist/cjs/src/providers/GeminiProvider.js +489 -0
  98. package/dist/cjs/src/providers/GeminiProvider.js.map +1 -0
  99. package/dist/cjs/src/providers/OpenAIProvider.d.ts +52 -0
  100. package/dist/cjs/src/providers/OpenAIProvider.d.ts.map +1 -0
  101. package/dist/cjs/src/providers/OpenAIProvider.js +395 -0
  102. package/dist/cjs/src/providers/OpenAIProvider.js.map +1 -0
  103. package/dist/cjs/src/providers/OpenRouterProvider.d.ts +56 -0
  104. package/dist/cjs/src/providers/OpenRouterProvider.d.ts.map +1 -0
  105. package/dist/cjs/src/providers/OpenRouterProvider.js +409 -0
  106. package/dist/cjs/src/providers/OpenRouterProvider.js.map +1 -0
  107. package/dist/cjs/src/providers/index.d.ts +13 -0
  108. package/dist/cjs/src/providers/index.d.ts.map +1 -0
  109. package/dist/cjs/src/providers/index.js +16 -0
  110. package/dist/cjs/src/providers/index.js.map +1 -0
  111. package/dist/cjs/src/types/agent.d.ts +181 -0
  112. package/dist/cjs/src/types/agent.d.ts.map +1 -0
  113. package/dist/cjs/src/types/agent.js +21 -0
  114. package/dist/cjs/src/types/agent.js.map +1 -0
  115. package/dist/cjs/src/types/ai.d.ts +143 -0
  116. package/dist/cjs/src/types/ai.d.ts.map +1 -0
  117. package/dist/cjs/src/types/ai.js +6 -0
  118. package/dist/cjs/src/types/ai.js.map +1 -0
  119. package/dist/cjs/src/types/history.d.ts +178 -0
  120. package/dist/cjs/src/types/history.d.ts.map +1 -0
  121. package/dist/cjs/src/types/history.js +33 -0
  122. package/dist/cjs/src/types/history.js.map +1 -0
  123. package/dist/cjs/src/types/index.d.ts +22 -0
  124. package/dist/cjs/src/types/index.d.ts.map +1 -0
  125. package/dist/cjs/src/types/index.js +37 -0
  126. package/dist/cjs/src/types/index.js.map +1 -0
  127. package/dist/cjs/src/types/persistence.d.ts +209 -0
  128. package/dist/cjs/src/types/persistence.d.ts.map +1 -0
  129. package/dist/cjs/src/types/persistence.js +7 -0
  130. package/dist/cjs/src/types/persistence.js.map +1 -0
  131. package/dist/cjs/src/types/route.d.ts +238 -0
  132. package/dist/cjs/src/types/route.d.ts.map +1 -0
  133. package/dist/cjs/src/types/route.js +6 -0
  134. package/dist/cjs/src/types/route.js.map +1 -0
  135. package/dist/cjs/src/types/routing.d.ts +16 -0
  136. package/dist/cjs/src/types/routing.d.ts.map +1 -0
  137. package/dist/cjs/src/types/routing.js +3 -0
  138. package/dist/cjs/src/types/routing.js.map +1 -0
  139. package/dist/cjs/src/types/schema.d.ts +22 -0
  140. package/dist/cjs/src/types/schema.d.ts.map +1 -0
  141. package/dist/cjs/src/types/schema.js +3 -0
  142. package/dist/cjs/src/types/schema.js.map +1 -0
  143. package/dist/cjs/src/types/session.d.ts +65 -0
  144. package/dist/cjs/src/types/session.d.ts.map +1 -0
  145. package/dist/cjs/src/types/session.js +6 -0
  146. package/dist/cjs/src/types/session.js.map +1 -0
  147. package/dist/cjs/src/types/template.d.ts +88 -0
  148. package/dist/cjs/src/types/template.d.ts.map +1 -0
  149. package/dist/cjs/src/types/template.js +3 -0
  150. package/dist/cjs/src/types/template.js.map +1 -0
  151. package/dist/cjs/src/types/tool.d.ts +130 -0
  152. package/dist/cjs/src/types/tool.d.ts.map +1 -0
  153. package/dist/cjs/src/types/tool.js +19 -0
  154. package/dist/cjs/src/types/tool.js.map +1 -0
  155. package/dist/cjs/src/utils/clone.d.ts +8 -0
  156. package/dist/cjs/src/utils/clone.d.ts.map +1 -0
  157. package/dist/cjs/src/utils/clone.js +32 -0
  158. package/dist/cjs/src/utils/clone.js.map +1 -0
  159. package/dist/cjs/src/utils/condition.d.ts +38 -0
  160. package/dist/cjs/src/utils/condition.d.ts.map +1 -0
  161. package/dist/cjs/src/utils/condition.js +168 -0
  162. package/dist/cjs/src/utils/condition.js.map +1 -0
  163. package/dist/cjs/src/utils/event.d.ts +6 -0
  164. package/dist/cjs/src/utils/event.d.ts.map +1 -0
  165. package/dist/cjs/src/utils/event.js +20 -0
  166. package/dist/cjs/src/utils/event.js.map +1 -0
  167. package/dist/cjs/src/utils/history.d.ts +60 -0
  168. package/dist/cjs/src/utils/history.d.ts.map +1 -0
  169. package/dist/cjs/src/utils/history.js +274 -0
  170. package/dist/cjs/src/utils/history.js.map +1 -0
  171. package/dist/cjs/src/utils/id.d.ts +25 -0
  172. package/dist/cjs/src/utils/id.d.ts.map +1 -0
  173. package/dist/cjs/src/utils/id.js +70 -0
  174. package/dist/cjs/src/utils/id.js.map +1 -0
  175. package/dist/cjs/src/utils/index.d.ts +15 -0
  176. package/dist/cjs/src/utils/index.d.ts.map +1 -0
  177. package/dist/cjs/src/utils/index.js +64 -0
  178. package/dist/cjs/src/utils/index.js.map +1 -0
  179. package/dist/cjs/src/utils/json.d.ts +16 -0
  180. package/dist/cjs/src/utils/json.d.ts.map +1 -0
  181. package/dist/cjs/src/utils/json.js +47 -0
  182. package/dist/cjs/src/utils/json.js.map +1 -0
  183. package/dist/cjs/src/utils/logger.d.ts +10 -0
  184. package/dist/cjs/src/utils/logger.d.ts.map +1 -0
  185. package/dist/cjs/src/utils/logger.js +23 -0
  186. package/dist/cjs/src/utils/logger.js.map +1 -0
  187. package/dist/cjs/src/utils/retry.d.ts +10 -0
  188. package/dist/cjs/src/utils/retry.d.ts.map +1 -0
  189. package/dist/cjs/src/utils/retry.js +76 -0
  190. package/dist/cjs/src/utils/retry.js.map +1 -0
  191. package/dist/cjs/src/utils/session.d.ts +51 -0
  192. package/dist/cjs/src/utils/session.d.ts.map +1 -0
  193. package/dist/cjs/src/utils/session.js +170 -0
  194. package/dist/cjs/src/utils/session.js.map +1 -0
  195. package/dist/cjs/src/utils/template.d.ts +155 -0
  196. package/dist/cjs/src/utils/template.d.ts.map +1 -0
  197. package/dist/cjs/src/utils/template.js +383 -0
  198. package/dist/cjs/src/utils/template.js.map +1 -0
  199. package/dist/src/adapters/MemoryAdapter.d.ts +47 -0
  200. package/dist/src/adapters/MemoryAdapter.d.ts.map +1 -0
  201. package/dist/src/adapters/MemoryAdapter.js +198 -0
  202. package/dist/src/adapters/MemoryAdapter.js.map +1 -0
  203. package/dist/src/adapters/MongoAdapter.d.ts +97 -0
  204. package/dist/src/adapters/MongoAdapter.d.ts.map +1 -0
  205. package/dist/src/adapters/MongoAdapter.js +164 -0
  206. package/dist/src/adapters/MongoAdapter.js.map +1 -0
  207. package/dist/src/adapters/OpenSearchAdapter.d.ts +169 -0
  208. package/dist/src/adapters/OpenSearchAdapter.d.ts.map +1 -0
  209. package/dist/src/adapters/OpenSearchAdapter.js +454 -0
  210. package/dist/src/adapters/OpenSearchAdapter.js.map +1 -0
  211. package/dist/src/adapters/PostgreSQLAdapter.d.ts +71 -0
  212. package/dist/src/adapters/PostgreSQLAdapter.d.ts.map +1 -0
  213. package/dist/src/adapters/PostgreSQLAdapter.js +256 -0
  214. package/dist/src/adapters/PostgreSQLAdapter.js.map +1 -0
  215. package/dist/src/adapters/PrismaAdapter.d.ts +115 -0
  216. package/dist/src/adapters/PrismaAdapter.d.ts.map +1 -0
  217. package/dist/src/adapters/PrismaAdapter.js +362 -0
  218. package/dist/src/adapters/PrismaAdapter.js.map +1 -0
  219. package/dist/src/adapters/RedisAdapter.d.ts +71 -0
  220. package/dist/src/adapters/RedisAdapter.d.ts.map +1 -0
  221. package/dist/src/adapters/RedisAdapter.js +227 -0
  222. package/dist/src/adapters/RedisAdapter.js.map +1 -0
  223. package/dist/src/adapters/SQLiteAdapter.d.ts +69 -0
  224. package/dist/src/adapters/SQLiteAdapter.d.ts.map +1 -0
  225. package/dist/src/adapters/SQLiteAdapter.js +308 -0
  226. package/dist/src/adapters/SQLiteAdapter.js.map +1 -0
  227. package/dist/src/adapters/index.d.ts +17 -0
  228. package/dist/src/adapters/index.d.ts.map +1 -0
  229. package/dist/src/adapters/index.js +11 -0
  230. package/dist/src/adapters/index.js.map +1 -0
  231. package/dist/src/constants/index.d.ts +10 -0
  232. package/dist/src/constants/index.d.ts.map +1 -0
  233. package/dist/src/constants/index.js +10 -0
  234. package/dist/src/constants/index.js.map +1 -0
  235. package/dist/src/core/Agent.d.ts +232 -0
  236. package/dist/src/core/Agent.d.ts.map +1 -0
  237. package/dist/src/core/Agent.js +737 -0
  238. package/dist/src/core/Agent.js.map +1 -0
  239. package/dist/src/core/Events.d.ts +26 -0
  240. package/dist/src/core/Events.d.ts.map +1 -0
  241. package/dist/src/core/Events.js +137 -0
  242. package/dist/src/core/Events.js.map +1 -0
  243. package/dist/src/core/PersistenceManager.d.ts +98 -0
  244. package/dist/src/core/PersistenceManager.d.ts.map +1 -0
  245. package/dist/src/core/PersistenceManager.js +257 -0
  246. package/dist/src/core/PersistenceManager.js.map +1 -0
  247. package/dist/src/core/PromptComposer.d.ts +27 -0
  248. package/dist/src/core/PromptComposer.d.ts.map +1 -0
  249. package/dist/src/core/PromptComposer.js +190 -0
  250. package/dist/src/core/PromptComposer.js.map +1 -0
  251. package/dist/src/core/ResponseEngine.d.ts +32 -0
  252. package/dist/src/core/ResponseEngine.d.ts.map +1 -0
  253. package/dist/src/core/ResponseEngine.js +198 -0
  254. package/dist/src/core/ResponseEngine.js.map +1 -0
  255. package/dist/src/core/ResponseModal.d.ts +222 -0
  256. package/dist/src/core/ResponseModal.d.ts.map +1 -0
  257. package/dist/src/core/ResponseModal.js +1583 -0
  258. package/dist/src/core/ResponseModal.js.map +1 -0
  259. package/dist/src/core/ResponsePipeline.d.ts +175 -0
  260. package/dist/src/core/ResponsePipeline.d.ts.map +1 -0
  261. package/dist/src/core/ResponsePipeline.js +545 -0
  262. package/dist/src/core/ResponsePipeline.js.map +1 -0
  263. package/dist/src/core/Route.d.ts +181 -0
  264. package/dist/src/core/Route.d.ts.map +1 -0
  265. package/dist/src/core/Route.js +537 -0
  266. package/dist/src/core/Route.js.map +1 -0
  267. package/dist/src/core/RoutingEngine.d.ts +159 -0
  268. package/dist/src/core/RoutingEngine.d.ts.map +1 -0
  269. package/dist/src/core/RoutingEngine.js +957 -0
  270. package/dist/src/core/RoutingEngine.js.map +1 -0
  271. package/dist/src/core/SessionManager.d.ts +94 -0
  272. package/dist/src/core/SessionManager.d.ts.map +1 -0
  273. package/dist/src/core/SessionManager.js +235 -0
  274. package/dist/src/core/SessionManager.js.map +1 -0
  275. package/dist/src/core/Step.d.ts +170 -0
  276. package/dist/src/core/Step.d.ts.map +1 -0
  277. package/dist/src/core/Step.js +444 -0
  278. package/dist/src/core/Step.js.map +1 -0
  279. package/dist/src/core/ToolManager.d.ts +234 -0
  280. package/dist/src/core/ToolManager.d.ts.map +1 -0
  281. package/dist/src/core/ToolManager.js +1111 -0
  282. package/dist/src/core/ToolManager.js.map +1 -0
  283. package/dist/src/index.d.ts +44 -0
  284. package/dist/src/index.d.ts.map +1 -0
  285. package/dist/src/index.js +37 -0
  286. package/dist/src/index.js.map +1 -0
  287. package/dist/src/providers/AnthropicProvider.d.ts +43 -0
  288. package/dist/src/providers/AnthropicProvider.d.ts.map +1 -0
  289. package/dist/src/providers/AnthropicProvider.js +370 -0
  290. package/dist/src/providers/AnthropicProvider.js.map +1 -0
  291. package/dist/src/providers/GeminiProvider.d.ts +58 -0
  292. package/dist/src/providers/GeminiProvider.d.ts.map +1 -0
  293. package/dist/src/providers/GeminiProvider.js +485 -0
  294. package/dist/src/providers/GeminiProvider.js.map +1 -0
  295. package/dist/src/providers/OpenAIProvider.d.ts +52 -0
  296. package/dist/src/providers/OpenAIProvider.d.ts.map +1 -0
  297. package/dist/src/providers/OpenAIProvider.js +388 -0
  298. package/dist/src/providers/OpenAIProvider.js.map +1 -0
  299. package/dist/src/providers/OpenRouterProvider.d.ts +56 -0
  300. package/dist/src/providers/OpenRouterProvider.d.ts.map +1 -0
  301. package/dist/src/providers/OpenRouterProvider.js +402 -0
  302. package/dist/src/providers/OpenRouterProvider.js.map +1 -0
  303. package/dist/src/providers/index.d.ts +13 -0
  304. package/dist/src/providers/index.d.ts.map +1 -0
  305. package/dist/src/providers/index.js +9 -0
  306. package/dist/src/providers/index.js.map +1 -0
  307. package/dist/src/types/agent.d.ts +181 -0
  308. package/dist/src/types/agent.d.ts.map +1 -0
  309. package/dist/src/types/agent.js +18 -0
  310. package/dist/src/types/agent.js.map +1 -0
  311. package/dist/src/types/ai.d.ts +143 -0
  312. package/dist/src/types/ai.d.ts.map +1 -0
  313. package/dist/src/types/ai.js +5 -0
  314. package/dist/src/types/ai.js.map +1 -0
  315. package/dist/src/types/history.d.ts +178 -0
  316. package/dist/src/types/history.d.ts.map +1 -0
  317. package/dist/src/types/history.js +30 -0
  318. package/dist/src/types/history.js.map +1 -0
  319. package/dist/src/types/index.d.ts +22 -0
  320. package/dist/src/types/index.d.ts.map +1 -0
  321. package/dist/src/types/index.js +12 -0
  322. package/dist/src/types/index.js.map +1 -0
  323. package/dist/src/types/persistence.d.ts +209 -0
  324. package/dist/src/types/persistence.d.ts.map +1 -0
  325. package/dist/src/types/persistence.js +6 -0
  326. package/dist/src/types/persistence.js.map +1 -0
  327. package/dist/src/types/route.d.ts +238 -0
  328. package/dist/src/types/route.d.ts.map +1 -0
  329. package/dist/src/types/route.js +5 -0
  330. package/dist/src/types/route.js.map +1 -0
  331. package/dist/src/types/routing.d.ts +16 -0
  332. package/dist/src/types/routing.d.ts.map +1 -0
  333. package/dist/src/types/routing.js +2 -0
  334. package/dist/src/types/routing.js.map +1 -0
  335. package/dist/src/types/schema.d.ts +22 -0
  336. package/dist/src/types/schema.d.ts.map +1 -0
  337. package/dist/src/types/schema.js +2 -0
  338. package/dist/src/types/schema.js.map +1 -0
  339. package/dist/src/types/session.d.ts +65 -0
  340. package/dist/src/types/session.d.ts.map +1 -0
  341. package/dist/src/types/session.js +5 -0
  342. package/dist/src/types/session.js.map +1 -0
  343. package/dist/src/types/template.d.ts +88 -0
  344. package/dist/src/types/template.d.ts.map +1 -0
  345. package/dist/src/types/template.js +2 -0
  346. package/dist/src/types/template.js.map +1 -0
  347. package/dist/src/types/tool.d.ts +130 -0
  348. package/dist/src/types/tool.d.ts.map +1 -0
  349. package/dist/src/types/tool.js +16 -0
  350. package/dist/src/types/tool.js.map +1 -0
  351. package/dist/src/utils/clone.d.ts +8 -0
  352. package/dist/src/utils/clone.d.ts.map +1 -0
  353. package/dist/src/utils/clone.js +29 -0
  354. package/dist/src/utils/clone.js.map +1 -0
  355. package/dist/src/utils/condition.d.ts +38 -0
  356. package/dist/src/utils/condition.d.ts.map +1 -0
  357. package/dist/src/utils/condition.js +161 -0
  358. package/dist/src/utils/condition.js.map +1 -0
  359. package/dist/src/utils/event.d.ts +6 -0
  360. package/dist/src/utils/event.d.ts.map +1 -0
  361. package/dist/src/utils/event.js +17 -0
  362. package/dist/src/utils/event.js.map +1 -0
  363. package/dist/src/utils/history.d.ts +60 -0
  364. package/dist/src/utils/history.d.ts.map +1 -0
  365. package/dist/src/utils/history.js +263 -0
  366. package/dist/src/utils/history.js.map +1 -0
  367. package/dist/src/utils/id.d.ts +25 -0
  368. package/dist/src/utils/id.d.ts.map +1 -0
  369. package/dist/src/utils/id.js +64 -0
  370. package/dist/src/utils/id.js.map +1 -0
  371. package/dist/src/utils/index.d.ts +15 -0
  372. package/dist/src/utils/index.d.ts.map +1 -0
  373. package/dist/src/utils/index.js +23 -0
  374. package/dist/src/utils/index.js.map +1 -0
  375. package/dist/src/utils/json.d.ts +16 -0
  376. package/dist/src/utils/json.d.ts.map +1 -0
  377. package/dist/src/utils/json.js +43 -0
  378. package/dist/src/utils/json.js.map +1 -0
  379. package/dist/src/utils/logger.d.ts +10 -0
  380. package/dist/src/utils/logger.d.ts.map +1 -0
  381. package/dist/src/utils/logger.js +17 -0
  382. package/dist/src/utils/logger.js.map +1 -0
  383. package/dist/src/utils/retry.d.ts +10 -0
  384. package/dist/src/utils/retry.d.ts.map +1 -0
  385. package/dist/src/utils/retry.js +71 -0
  386. package/dist/src/utils/retry.js.map +1 -0
  387. package/dist/src/utils/session.d.ts +51 -0
  388. package/dist/src/utils/session.d.ts.map +1 -0
  389. package/dist/src/utils/session.js +160 -0
  390. package/dist/src/utils/session.js.map +1 -0
  391. package/dist/src/utils/template.d.ts +155 -0
  392. package/dist/src/utils/template.d.ts.map +1 -0
  393. package/dist/src/utils/template.js +374 -0
  394. package/dist/src/utils/template.js.map +1 -0
  395. package/docs/CONTRIBUTING.md +521 -0
  396. package/docs/README.md +228 -0
  397. package/docs/api/README.md +3258 -0
  398. package/docs/api/overview.md +1134 -0
  399. package/docs/architecture/data-extraction-flow.md +363 -0
  400. package/docs/core/agent/README.md +902 -0
  401. package/docs/core/agent/context-management.md +796 -0
  402. package/docs/core/agent/session-management.md +641 -0
  403. package/docs/core/ai-integration/prompt-composition.md +220 -0
  404. package/docs/core/ai-integration/providers.md +515 -0
  405. package/docs/core/ai-integration/response-processing.md +287 -0
  406. package/docs/core/conversation-flows/data-collection.md +623 -0
  407. package/docs/core/conversation-flows/route-dsl.md +502 -0
  408. package/docs/core/conversation-flows/routes.md +247 -0
  409. package/docs/core/conversation-flows/step-transitions.md +595 -0
  410. package/docs/core/conversation-flows/steps.md +154 -0
  411. package/docs/core/error-handling.md +638 -0
  412. package/docs/core/persistence/adapters.md +255 -0
  413. package/docs/core/persistence/session-storage.md +644 -0
  414. package/docs/core/routing/intelligent-routing.md +466 -0
  415. package/docs/core/tools/tool-definition.md +970 -0
  416. package/docs/core/tools/tool-scoping.md +819 -0
  417. package/docs/guides/advanced-patterns/publishing.md +186 -0
  418. package/docs/guides/error-handling-patterns.md +578 -0
  419. package/docs/guides/getting-started/README.md +696 -0
  420. package/docs/guides/migration/README.md +72 -0
  421. package/docs/guides/migration/flexible-routing-conditions.md +375 -0
  422. package/docs/guides/migration/response-modal-refactor.md +518 -0
  423. package/examples/advanced-patterns/knowledge-based-agent.ts +735 -0
  424. package/examples/advanced-patterns/persistent-onboarding.ts +728 -0
  425. package/examples/advanced-patterns/route-lifecycle-hooks.ts +556 -0
  426. package/examples/advanced-patterns/streaming-responses.ts +578 -0
  427. package/examples/ai-providers/anthropic-integration.ts +388 -0
  428. package/examples/ai-providers/openai-integration.ts +228 -0
  429. package/examples/condition-patterns/function-only-conditions.ts +365 -0
  430. package/examples/condition-patterns/mixed-array-conditions.ts +477 -0
  431. package/examples/condition-patterns/route-skipif-patterns.ts +468 -0
  432. package/examples/condition-patterns/step-skipif-patterns.ts +0 -0
  433. package/examples/condition-patterns/string-only-conditions.ts +296 -0
  434. package/examples/conversation-flows/completion-transitions.ts +318 -0
  435. package/examples/core-concepts/basic-agent.ts +503 -0
  436. package/examples/core-concepts/modern-streaming-api.ts +309 -0
  437. package/examples/core-concepts/schema-driven-extraction.ts +332 -0
  438. package/examples/core-concepts/session-management.ts +494 -0
  439. package/examples/integrations/database-integration.ts +630 -0
  440. package/examples/integrations/healthcare-integration.ts +595 -0
  441. package/examples/integrations/search-integration.ts +530 -0
  442. package/examples/integrations/server-session-management.ts +307 -0
  443. package/examples/persistence/custom-adapter.ts +529 -0
  444. package/examples/persistence/database-persistence.ts +583 -0
  445. package/examples/persistence/memory-sessions.ts +495 -0
  446. package/examples/persistence/prisma-schema.example.prisma +74 -0
  447. package/examples/persistence/redis-persistence.ts +488 -0
  448. package/examples/tools/basic-tools.ts +765 -0
  449. package/examples/tools/data-enrichment-tools.ts +593 -0
  450. package/package.json +125 -0
  451. package/src/adapters/MemoryAdapter.ts +273 -0
  452. package/src/adapters/MongoAdapter.ts +304 -0
  453. package/src/adapters/OpenSearchAdapter.ts +670 -0
  454. package/src/adapters/PostgreSQLAdapter.ts +428 -0
  455. package/src/adapters/PrismaAdapter.ts +553 -0
  456. package/src/adapters/RedisAdapter.ts +377 -0
  457. package/src/adapters/SQLiteAdapter.ts +459 -0
  458. package/src/adapters/index.ts +43 -0
  459. package/src/constants/index.ts +10 -0
  460. package/src/core/Agent.ts +970 -0
  461. package/src/core/Events.ts +164 -0
  462. package/src/core/PersistenceManager.ts +353 -0
  463. package/src/core/PromptComposer.ts +253 -0
  464. package/src/core/ResponseEngine.ts +306 -0
  465. package/src/core/ResponseModal.ts +2050 -0
  466. package/src/core/ResponsePipeline.ts +864 -0
  467. package/src/core/Route.ts +677 -0
  468. package/src/core/RoutingEngine.ts +1396 -0
  469. package/src/core/SessionManager.ts +297 -0
  470. package/src/core/Step.ts +593 -0
  471. package/src/core/ToolManager.ts +1394 -0
  472. package/src/index.ts +155 -0
  473. package/src/providers/AnthropicProvider.ts +560 -0
  474. package/src/providers/GeminiProvider.ts +683 -0
  475. package/src/providers/OpenAIProvider.ts +602 -0
  476. package/src/providers/OpenRouterProvider.ts +613 -0
  477. package/src/providers/index.ts +16 -0
  478. package/src/types/agent.ts +196 -0
  479. package/src/types/ai.ts +158 -0
  480. package/src/types/history.ts +206 -0
  481. package/src/types/index.ts +119 -0
  482. package/src/types/persistence.ts +251 -0
  483. package/src/types/route.ts +272 -0
  484. package/src/types/routing.ts +18 -0
  485. package/src/types/schema.ts +23 -0
  486. package/src/types/session.ts +74 -0
  487. package/src/types/template.ts +104 -0
  488. package/src/types/tool.ts +174 -0
  489. package/src/utils/clone.ts +34 -0
  490. package/src/utils/condition.ts +190 -0
  491. package/src/utils/event.ts +16 -0
  492. package/src/utils/history.ts +306 -0
  493. package/src/utils/id.ts +73 -0
  494. package/src/utils/index.ts +69 -0
  495. package/src/utils/json.ts +46 -0
  496. package/src/utils/logger.ts +19 -0
  497. package/src/utils/retry.ts +97 -0
  498. package/src/utils/session.ts +204 -0
  499. package/src/utils/template.ts +444 -0
@@ -0,0 +1,3258 @@
1
+ # API Reference
2
+
3
+ Complete API documentation for `@falai/agent`. This framework provides a strongly-typed, modular agent architecture with AI-powered routing and schema-driven data collection.
4
+
5
+ ## 📋 Documentation Structure
6
+
7
+ - **[Complete API Overview](./overview.md)** - Comprehensive reference for all classes, interfaces, and utilities
8
+ - **[Agent Architecture](../core/agent/README.md)** - Agent class, context management, and lifecycle
9
+ - **[AI Routing System](../core/routing/intelligent-routing.md)** - Intelligent route and step selection
10
+ - **[Route DSL](../core/conversation-flows/route-dsl.md)** - Declarative conversation flow design
11
+ - **[Data Collection](../core/conversation-flows/data-collection.md)** - Schema-driven data extraction
12
+ - **[Tool Execution](../core/tools/tool-execution.md)** - Dynamic tool calling and context updates
13
+ - **[Session Storage](../core/persistence/session-storage.md)** - Persistence and session management
14
+ - **[AI Providers](../core/ai-integration/providers.md)** - Provider integrations and configuration
15
+
16
+ ---
17
+
18
+ ## ConditionTemplate System
19
+
20
+ ### `ConditionTemplate<TContext, TData>`
21
+
22
+ **NEW:** Enhanced condition type that supports flexible routing logic with both AI context and programmatic evaluation.
23
+
24
+ ```typescript
25
+ type ConditionTemplate<TContext = unknown, TData = unknown> =
26
+ | string // AI context only - provides context to AI for routing decisions
27
+ | ((params: TemplateContext<TContext, TData>) => boolean | Promise<boolean>) // Programmatic evaluation
28
+ | ConditionTemplate<TContext, TData>[]; // Array of either type
29
+ ```
30
+
31
+ **Key Features:**
32
+
33
+ - **String conditions**: Provide AI context for routing decisions (e.g., `"user wants to book a flight"`)
34
+ - **Function conditions**: Execute programmatic logic returning boolean (e.g., `(ctx) => ctx.data?.isLoggedIn === true`)
35
+ - **Array conditions**: Combine multiple conditions with logical operators
36
+ - **Hybrid approach**: Mix strings and functions for optimal flexibility
37
+
38
+ #### Evaluation Logic
39
+
40
+ **For `when` conditions (AND logic):**
41
+ - **Functions**: All must return `true` for condition to pass
42
+ - **Strings**: Ignored in programmatic evaluation, used for AI context
43
+ - **Arrays**: All functions must return `true`
44
+
45
+ **For `skipIf` conditions (OR logic):**
46
+ - **Functions**: Any returning `true` causes skip
47
+ - **Strings**: Ignored in programmatic evaluation, used for AI context
48
+ - **Arrays**: Any function returning `true` causes skip
49
+
50
+ #### Usage Examples
51
+
52
+ ```typescript
53
+ // String-only condition (AI context)
54
+ when: "User wants to make a reservation"
55
+
56
+ // Function-only condition (programmatic)
57
+ when: (ctx) => ctx.data?.userType === 'premium'
58
+
59
+ // Mixed array condition (hybrid approach)
60
+ when: [
61
+ "User is asking for help", // AI context
62
+ (ctx) => ctx.data?.isLoggedIn === true // Programmatic check
63
+ ]
64
+
65
+ // Route skipIf with OR logic
66
+ skipIf: [
67
+ "System is under maintenance", // AI context
68
+ (ctx) => ctx.data?.maintenanceMode === true // Programmatic check
69
+ ]
70
+ ```
71
+
72
+ ### `ConditionEvaluator<TContext, TData>`
73
+
74
+ **NEW:** Utility class for evaluating ConditionTemplate instances with consistent logic across the framework.
75
+
76
+ #### Constructor
77
+
78
+ ```typescript
79
+ new ConditionEvaluator<TContext, TData>(templateContext: TemplateContext<TContext, TData>)
80
+ ```
81
+
82
+ #### Methods
83
+
84
+ ##### `evaluateCondition(condition, logic?): Promise<ConditionEvaluationResult>`
85
+
86
+ Evaluates a ConditionTemplate and returns detailed results.
87
+
88
+ **Parameters:**
89
+ - `condition`: ConditionTemplate to evaluate
90
+ - `logic`: 'AND' | 'OR' - logical operator for arrays (default: 'AND')
91
+
92
+ **Returns:**
93
+ ```typescript
94
+ interface ConditionEvaluationResult {
95
+ programmaticResult: boolean; // Result of function evaluations only
96
+ aiContextStrings: string[]; // String values for AI context
97
+ hasProgrammaticConditions: boolean; // Whether any functions were evaluated
98
+ }
99
+ ```
100
+
101
+ **Example:**
102
+
103
+ ```typescript
104
+ const evaluator = new ConditionEvaluator(templateContext);
105
+
106
+ const result = await evaluator.evaluateCondition([
107
+ "User needs premium support", // AI context
108
+ (ctx) => ctx.data?.userType === 'premium' // Programmatic
109
+ ]);
110
+
111
+ console.log(result.programmaticResult); // true/false from function
112
+ console.log(result.aiContextStrings); // ["User needs premium support"]
113
+ console.log(result.hasProgrammaticConditions); // true
114
+ ```
115
+
116
+ ---
117
+
118
+ ## Core Classes
119
+
120
+ ### `Agent<TContext, TData>`
121
+
122
+ Main agent class for managing conversational AI with agent-level data collection.
123
+
124
+ #### Constructor
125
+
126
+ ```typescript
127
+ new Agent<TContext, TData>(options: AgentOptions<TContext, TData>)
128
+ ```
129
+
130
+ See [Agent](./AGENT.md) for full details.
131
+
132
+ #### Methods
133
+
134
+ ##### `createRoute(options: RouteOptions): Route`
135
+
136
+ Creates a new conversation route with required fields specification.
137
+
138
+ ##### `getCollectedData(): Partial<TData>`
139
+
140
+ Gets the current agent-level collected data.
141
+
142
+ ```typescript
143
+ const data = agent.getCollectedData();
144
+ console.log(data); // { customerName: "John", email: "john@example.com" }
145
+ ```
146
+
147
+ ##### `updateCollectedData(updates: Partial<TData>): Promise<void>`
148
+
149
+ Updates agent-level collected data and triggers validation.
150
+
151
+ ```typescript
152
+ await agent.updateCollectedData({
153
+ customerId: "CUST-12345",
154
+ priority: "high"
155
+ });
156
+ ```
157
+
158
+ ##### `validateData(data: Partial<TData>): ValidationResult`
159
+
160
+ Validates data against the agent-level schema.
161
+
162
+ ```typescript
163
+ const validation = agent.validateData({ email: "invalid-email" });
164
+ if (!validation.valid) {
165
+ console.log(validation.errors); // Detailed validation errors
166
+ }
167
+ ```
168
+
169
+ ##### `createTerm(term: Term): this`
170
+
171
+ Adds a domain glossary term. Returns `this` for chaining.
172
+
173
+ ##### `createGuideline(guideline: Guideline): this`
174
+
175
+ Adds a behavioral guideline. Returns `this` for chaining.
176
+
177
+ ##### `addTool(definition: Tool<TContext, TData, TResult>): this`
178
+
179
+ Creates and adds a tool to agent scope using the unified Tool interface. Returns `this` for chaining.
180
+
181
+ ```typescript
182
+ // Simple return value approach
183
+ agent.addTool({
184
+ id: "weather_check",
185
+ description: "Get current weather",
186
+ parameters: {
187
+ type: "object",
188
+ properties: {
189
+ location: { type: "string", description: "City name" }
190
+ },
191
+ required: ["location"]
192
+ },
193
+ handler: async ({ context, data }, args) => {
194
+ const weather = await weatherAPI.get(args.location);
195
+ return `Weather in ${args.location}: ${weather.condition}`;
196
+ }
197
+ });
198
+
199
+ // Advanced ToolResult pattern
200
+ agent.addTool({
201
+ id: "user_lookup",
202
+ description: "Look up user information",
203
+ handler: async ({ context, data }, args) => {
204
+ const user = await userAPI.find(args.userId);
205
+ return {
206
+ data: `Found user: ${user.name}`,
207
+ success: true,
208
+ contextUpdate: { currentUser: user },
209
+ dataUpdate: { userName: user.name }
210
+ };
211
+ }
212
+ });
213
+ ```
214
+
215
+ ##### `tool: ToolManager<TContext, TData>`
216
+
217
+ Access to the ToolManager instance for advanced tool operations.
218
+
219
+ ```typescript
220
+ // Register tools for ID-based reference
221
+ agent.tool.register({
222
+ id: "reusable_search",
223
+ description: "Search across data sources",
224
+ handler: async ({ context, data }, args) => "Search results"
225
+ });
226
+
227
+ // Create tools without adding to scope
228
+ const customTool = agent.tool.create({
229
+ id: "standalone_tool",
230
+ handler: async () => "Custom result"
231
+ });
232
+
233
+ // Use pattern helpers
234
+ const enrichmentTool = agent.tool.createDataEnrichment({
235
+ id: "enrich_profile",
236
+ fields: ['name', 'email'],
237
+ enricher: async (context, data) => ({
238
+ displayName: `${data.name} <${data.email}>`
239
+ })
240
+ });
241
+ ```
242
+
243
+ ##### `respond(input: RespondInput<TContext>): Promise<RespondOutput>`
244
+
245
+ Generates an AI response with session step management, tool execution, data extraction, and intelligent routing.
246
+
247
+ **Note:** This method now delegates to the internal `ResponseModal` class for improved architecture and maintainability.
248
+
249
+ **Enhanced Response Pipeline:**
250
+
251
+ 1. **Tool Execution** - Execute tools if current step has `tool` (enriches context before AI response)
252
+ 2. **Always-On Routing** - Score all routes, respect user intent to change direction
253
+ 3. **Step Traversal** - Use `skipIf` and `requires` to determine next step
254
+ 4. **Response Generation** - Build schema with `collect` fields, extract data
255
+ 5. **Session Update** - Merge collected data into session step
256
+
257
+ **Tool Execution (Pre-Response):**
258
+ Tools execute before AI response generation, allowing them to:
259
+
260
+ - Enrich context with external data
261
+ - Update collected session data
262
+ - Perform business logic
263
+ - Access APIs and databases
264
+
265
+ This design enables more intelligent, context-aware responses.
266
+
267
+ ##### `getKnowledgeBase(): Record<string, unknown>`
268
+
269
+ Gets the agent's knowledge base containing any JSON structure the AI should know.
270
+
271
+ ```typescript
272
+ const knowledge = agent.getKnowledgeBase();
273
+ // Returns the agent's knowledge base
274
+ ```
275
+
276
+ ##### `getRoutes(): Route<TContext, unknown>[]`
277
+
278
+ Gets all routes configured in the agent.
279
+
280
+ ```typescript
281
+ const routes = agent.getRoutes();
282
+ // Returns array of all configured routes
283
+ ```
284
+
285
+ ##### `getTerms(): Term<TContext>[]`
286
+
287
+ Gets all terms configured in the agent.
288
+
289
+ ```typescript
290
+ const terms = agent.getTerms();
291
+ // Returns array of all configured terms
292
+ ```
293
+
294
+ ##### `getGuidelines(): Guideline<TContext>[]`
295
+
296
+ Gets all guidelines configured in the agent.
297
+
298
+ ```typescript
299
+ const guidelines = agent.getGuidelines();
300
+ // Returns array of all configured guidelines
301
+ ```
302
+
303
+ ````typescript
304
+
305
+ ##### `getPersistenceManager(): PersistenceManager | undefined`
306
+
307
+ Gets the persistence manager if configured.
308
+
309
+ ```typescript
310
+ const persistence = agent.getPersistenceManager();
311
+ // Returns PersistenceManager instance or undefined if not configured
312
+ ````
313
+
314
+ ##### `hasPersistence(): boolean`
315
+
316
+ Checks if persistence is enabled.
317
+
318
+ ```typescript
319
+ if (agent.hasPersistence()) {
320
+ // Persistence is configured
321
+ }
322
+ ```
323
+
324
+ ##### `nextStepRoute(routeIdOrTitle, session?, condition?, history?): Promise<SessionState>`
325
+
326
+ Manually transition to a different route by setting a pending transition that will be executed on the next `respond()` call.
327
+
328
+ ```typescript
329
+ // Transition to feedback route after completion
330
+ const updatedSession = await agent.nextStepRoute(
331
+ "feedback-collection",
332
+ session
333
+ );
334
+
335
+ // Next respond() call will automatically transition
336
+ const response = await agent.respond({ history, session: updatedSession });
337
+ ```
338
+
339
+ **Parameters:**
340
+
341
+ - `routeIdOrTitle`: Route ID or title to transition to
342
+ - `session`: Session step to update (uses current session if not provided)
343
+ - `condition`: Optional AI-evaluated condition for the transition
344
+ - `history`: Optional history for template context
345
+
346
+ **Returns:** Updated session with pending transition
347
+
348
+ ##### `getData<TData>(routeId?): Partial<TData>`
349
+
350
+ Gets the collected data from current session, optionally for a specific route.
351
+
352
+ ```typescript
353
+ // Option 1: Using current session (set with setCurrentSession)
354
+ agent.setCurrentSession(session);
355
+ const data = agent.getData(); // Uses current session
356
+
357
+ // Option 2: Get data for specific route
358
+ const routeData = agent.getData("onboarding"); // Route-specific data
359
+
360
+ // Option 3: From response (with current session set)
361
+ const response = await agent.respond({ history });
362
+ const data = agent.getData(); // Uses current session
363
+ ```
364
+
365
+ **Parameters:**
366
+
367
+ - `routeId` (optional): Route ID to get data for. If not provided, returns current route data.
368
+
369
+ **Returns:** The collected data from the current session
370
+
371
+ **Note:** Returns empty object if no current session is set.
372
+
373
+ ##### `setCurrentSession(session): void`
374
+
375
+ Sets the current session for convenience methods. Once set, methods like `getData()` don't need the session parameter.
376
+
377
+ ```typescript
378
+ // Set current session
379
+ agent.setCurrentSession(session);
380
+
381
+ // Now methods use the current session automatically
382
+ const data = agent.getData();
383
+ // Get collected data for route
384
+ const routeData = agent.getData("onboarding");
385
+ ```
386
+
387
+ **Parameters:**
388
+
389
+ - `session`: Session step to use as current session
390
+
391
+ ##### `getCurrentSession(): SessionState | undefined`
392
+
393
+ Gets the currently set session.
394
+
395
+ ```typescript
396
+ const current = agent.getCurrentSession();
397
+ if (current) {
398
+ console.log("Current session:", current.id);
399
+ }
400
+ ```
401
+
402
+ **Returns:** Current session or undefined if none set
403
+
404
+ ##### `clearCurrentSession(): void`
405
+
406
+ Clears the current session.
407
+
408
+ ```typescript
409
+ agent.clearCurrentSession();
410
+ ```
411
+
412
+ ##### `respond(input: RespondInput<TContext>): Promise<RespondOutput>`
413
+
414
+ Generates an AI response with session step management, data extraction, and intelligent routing.
415
+
416
+ ```typescript
417
+ interface RespondInput<TContext> {
418
+ history: Event[];
419
+ session?: SessionState; // NEW: Session step for conversation tracking
420
+ contextOverride?: Partial<TContext>;
421
+ signal?: AbortSignal;
422
+ }
423
+
424
+ interface RespondOutput {
425
+ /** The message to send to the user */
426
+ message: string;
427
+ /** Updated session step (includes collected data, current route/step) */
428
+ session?: SessionState;
429
+ /** Tool calls executed during response (for debugging) */
430
+ toolCalls?: Array<{
431
+ toolName: string;
432
+ arguments: Record<string, unknown>;
433
+ }>;
434
+ /**
435
+ * NEW: Indicates if the current route has reached END_ROUTE
436
+ * When true, all required data has been collected and the route is complete.
437
+ * Your application should handle this appropriately (e.g., process collected data,
438
+ * show completion UI, start a new route, etc.)
439
+ */
440
+ isRouteComplete?: boolean;
441
+ }
442
+ ```
443
+
444
+ **Enhanced Response Pipeline:**
445
+
446
+ 1. **Tool Execution** - Execute tools if current step has `tool`
447
+ 2. **Always-On Routing** - Score all routes, respect user intent to change direction
448
+ 3. **Step Traversal** - Use `skipIf` and `requires` to determine next step
449
+ 4. **Response Generation** - Build schema with `collect` fields, extract data
450
+ 5. **Session Update** - Merge collected data into session step
451
+
452
+ **Session Step Management:**
453
+
454
+ - Tracks current route, step, and collected data across turns
455
+ - Enables "I changed my mind" scenarios with context-aware routing
456
+ - Automatically merges new collected data with existing session data
457
+ - **Per-route data preservation** - Collected data is organized by route ID, allowing users to switch routes without losing progress
458
+
459
+ **Example with Automatic Session Management:**
460
+
461
+ ```typescript
462
+ // Server endpoint with automatic session management
463
+ app.post('/chat', async (req, res) => {
464
+ const { sessionId, message } = req.body;
465
+
466
+ const agent = new Agent({
467
+ name: "Travel Agent",
468
+ provider: new OpenAIProvider({ apiKey: process.env.OPENAI_API_KEY }),
469
+ persistence: { adapter: new PrismaAdapter({ prisma }) },
470
+ sessionId // Automatically loads or creates this session
471
+ });
472
+
473
+ const response = await agent.respond(message);
474
+
475
+ res.json({
476
+ message: response.message,
477
+ sessionId: agent.session.id,
478
+ isComplete: response.isRouteComplete
479
+ });
480
+ });
481
+ ```
482
+
483
+ **SessionManager API:**
484
+
485
+ ```typescript
486
+ // Access session manager
487
+ const sessionManager = agent.session;
488
+
489
+ // Get or create session (works for existing, new, or auto-generated IDs)
490
+ await sessionManager.getOrCreate("user-123");
491
+ await sessionManager.getOrCreate(); // Auto-generates ID
492
+
493
+ // Data access
494
+ const data = sessionManager.getData<FlightData>();
495
+ await sessionManager.setData({ destination: "Paris" });
496
+
497
+ // History management
498
+ await sessionManager.addMessage("user", "Hello");
499
+ const history = sessionManager.getHistory();
500
+ sessionManager.clearHistory();
501
+
502
+ // Session operations
503
+ await sessionManager.save(); // Manual save (auto-saves on addMessage)
504
+ await sessionManager.delete();
505
+ const newSession = await sessionManager.reset(true); // Preserve history
506
+ currentRoute: response.session?.currentRoute?.id,
507
+ currentStep: response.session?.currentStep?.id,
508
+ collectedData: {
509
+ data: response.session?.data,
510
+ routeHistory: response.session?.routeHistory,
511
+ currentRouteTitle: response.session?.currentRoute?.title,
512
+ currentStepDescription: response.session?.currentStep?.description,
513
+ metadata: response.session?.metadata,
514
+ },
515
+ lastMessageAt: new Date(),
516
+ });
517
+
518
+ // Save message
519
+ await yourDb.messages.create({
520
+ sessionId: dbSession.id,
521
+ role: "assistant",
522
+ content: response.message,
523
+ route: response.session?.currentRoute?.id,
524
+ step: response.session?.currentStep?.id,
525
+ });
526
+ ```
527
+
528
+ **Handling Route Completion:**
529
+
530
+ When a route reaches its END_ROUTE transition (all required data collected), the response includes `isRouteComplete: true`:
531
+
532
+ ```typescript
533
+ const response = await agent.respond({
534
+ history,
535
+ session,
536
+ });
537
+
538
+ if (response.isRouteComplete) {
539
+ // Route is complete! All data has been collected
540
+ console.log("✅ Route completed!");
541
+
542
+ // Get all the collected data
543
+ const collectedData = agent.getData(response.session!);
544
+ console.log("Collected data:", collectedData);
545
+
546
+ // Handle completion in your application:
547
+ // - Save the collected data to your database
548
+ // - Trigger business logic (e.g., create booking, send email)
549
+ // - Show completion UI to user
550
+ // - Start a new route or conversation
551
+
552
+ await processCompletedData(collectedData);
553
+
554
+ // Optional: Show a custom completion message
555
+ return "Thank you! Your information has been saved.";
556
+ } else {
557
+ // Normal flow - route still in progress
558
+ return response.message;
559
+ }
560
+ ```
561
+
562
+ **Example: Onboarding Flow**
563
+
564
+ ```typescript
565
+ // Onboarding route with skipIf logic for pre-filled data
566
+ const onboardingRoute = agent.createRoute<OnboardingData>({
567
+ id: "onboarding",
568
+ title: "User Onboarding",
569
+ schema: ONBOARDING_SCHEMA,
570
+ initialData: existingUserData, // Pre-fill with existing data
571
+ });
572
+
573
+ // Build steps with skipIf conditions
574
+ const welcome = onboardingRoute.initialStep.nextStep({
575
+ id: "ask_name",
576
+ prompt: "What's your name?",
577
+ collect: ["name"],
578
+ skipIf: (data) => !!data.name, // Skip if name already collected
579
+ });
580
+
581
+ const askEmail = welcome.nextStep({
582
+ id: "ask_email",
583
+ prompt: "What's your email?",
584
+ collect: ["email"],
585
+ skipIf: (data) => !!data.email, // Skip if email already collected
586
+ });
587
+
588
+ const complete = askEmail.nextStep({
589
+ id: "complete",
590
+ prompt: "All done! Thank you.",
591
+ });
592
+
593
+ complete.nextStep({ step: END_ROUTE });
594
+
595
+ // Option 1: Set current session for convenience
596
+ agent.setCurrentSession(session);
597
+
598
+ const response = await agent.respond({ history });
599
+
600
+ if (response.isRouteComplete) {
601
+ // If all data was pre-filled, the route completes immediately!
602
+ // The routing engine recursively skips all steps and reaches END_ROUTE
603
+ const data = agent.getData(); // No need to pass session!
604
+ await saveUserProfile(data);
605
+ return "Profile updated successfully!";
606
+ }
607
+
608
+ return response.message;
609
+ ```
610
+
611
+ **Important Notes:**
612
+
613
+ - `isRouteComplete` is `true` when the route reaches an `END_ROUTE` transition
614
+ - The `message` contains the completion message generated by the AI when `isRouteComplete` is `true`
615
+ - You should check `isRouteComplete` and handle completion appropriately
616
+ - If all steps are skipped (due to `skipIf` conditions), the route can complete immediately on entry
617
+ - Use `agent.getData(session)` to retrieve all collected data
618
+
619
+ See also: [Custom Database Integration Example](../examples/custom-database-persistence.ts)
620
+
621
+ ##### `respondStream(input: RespondInput<TContext>): AsyncGenerator<StreamChunk>`
622
+
623
+ Generates an AI response as a real-time stream for better user experience. Provides the same structured output as `respond()` but delivers it incrementally.
624
+
625
+ **Note:** This method now delegates to the internal `ResponseModal` class for improved architecture and maintainability.
626
+
627
+ ```typescript
628
+ interface StreamChunk {
629
+ /** The incremental text delta */
630
+ delta: string;
631
+ /** Full accumulated text so far */
632
+ accumulated: string;
633
+ /** Whether this is the final chunk */
634
+ done: boolean;
635
+ /** Updated session step (includes collected data, current route/step) */
636
+ session?: SessionState;
637
+ /** Tool calls requested by the agent (only in final chunk) */
638
+ toolCalls?: Array<{
639
+ toolName: string;
640
+ arguments: Record<string, unknown>;
641
+ }>;
642
+ /**
643
+ * Indicates if the current route has reached END_ROUTE (only in final chunk)
644
+ * When true, all required data has been collected and the route is complete.
645
+ */
646
+ isRouteComplete?: boolean;
647
+ }
648
+ ```
649
+
650
+ **Key Features:**
651
+
652
+ - 🌊 Real-time streaming for better perceived performance
653
+ - 📊 Access to route, step, and tool information in final chunk
654
+ - 🛑 Cancellable with AbortSignal
655
+ - ✅ Supported by all providers (Anthropic, OpenAI, Gemini, OpenRouter)
656
+
657
+ **Example:**
658
+
659
+ ```typescript
660
+ // Basic streaming
661
+ for await (const chunk of agent.respondStream({ history, session })) {
662
+ if (chunk.delta) {
663
+ // Display incremental text to user
664
+ process.stdout.write(chunk.delta);
665
+ }
666
+
667
+ if (chunk.done) {
668
+ console.log("\n✅ Complete!");
669
+
670
+ // Check if route is complete
671
+ if (chunk.isRouteComplete) {
672
+ console.log("🎉 Route completed!");
673
+ const data = agent.getData(chunk.session!);
674
+ await handleCompletion(data);
675
+ }
676
+
677
+ // Access session step
678
+ if (chunk.session?.currentRoute) {
679
+ console.log("Route:", chunk.session.currentRoute.title);
680
+ }
681
+ if (chunk.toolCalls) {
682
+ console.log("Tool calls:", chunk.toolCalls.length);
683
+ }
684
+ }
685
+ }
686
+ ```
687
+
688
+ ##### `stream(message?: string, options?: StreamOptions<TContext>): AsyncGenerator<AgentResponseStreamChunk<TData>>`
689
+
690
+ **NEW:** Modern streaming API that provides a simple interface similar to `chat()` but returns a stream. This is the recommended way to implement streaming responses.
691
+
692
+ ```typescript
693
+ interface StreamOptions<TContext = unknown> {
694
+ contextOverride?: Partial<TContext>;
695
+ signal?: AbortSignal;
696
+ history?: History; // Optional: override session history
697
+ }
698
+ ```
699
+
700
+ **Key Features:**
701
+
702
+ - 🎯 **Simple Interface**: Just `agent.stream("message")` - no complex parameters
703
+ - 🔄 **Automatic Session Management**: Handles conversation history automatically
704
+ - 🌊 **Real-time Streaming**: Same performance as `respondStream()` but easier to use
705
+ - 🛑 **Cancellable**: Supports AbortSignal for cancellation
706
+
707
+ **Example:**
708
+
709
+ ```typescript
710
+ // Simple streaming - automatically manages session history
711
+ for await (const chunk of agent.stream("Hello, how are you?")) {
712
+ if (chunk.delta) {
713
+ process.stdout.write(chunk.delta);
714
+ }
715
+
716
+ if (chunk.done) {
717
+ console.log("\n✅ Stream complete!");
718
+ // Session history is automatically updated
719
+ }
720
+ }
721
+
722
+ // With cancellation
723
+ const controller = new AbortController();
724
+ setTimeout(() => controller.abort(), 5000); // Cancel after 5s
725
+
726
+ for await (const chunk of agent.stream("Tell me a long story", {
727
+ signal: controller.signal
728
+ })) {
729
+ process.stdout.write(chunk.delta);
730
+ }
731
+ ```
732
+
733
+ **Migration from `respondStream()`:**
734
+
735
+ ```typescript
736
+ // Old way (still supported)
737
+ for await (const chunk of agent.respondStream({
738
+ history: agent.session.getHistory(),
739
+ session: await agent.session.getOrCreate()
740
+ })) {
741
+ // Handle chunk
742
+ }
743
+
744
+ // New way (recommended)
745
+ for await (const chunk of agent.stream("Your message")) {
746
+ // Handle chunk - session management is automatic
747
+ }
748
+ ```
749
+
750
+ **With Cancellation:**
751
+
752
+ ```typescript
753
+ const abortController = new AbortController();
754
+
755
+ // Cancel after 5 seconds
756
+ setTimeout(() => abortController.abort(), 5000);
757
+
758
+ try {
759
+ for await (const chunk of agent.respondStream({
760
+ history,
761
+ signal: abortController.signal,
762
+ })) {
763
+ console.log(chunk.delta);
764
+ }
765
+ } catch (error) {
766
+ if (error.name === "AbortError") {
767
+ console.log("Stream cancelled");
768
+ }
769
+ }
770
+ ```
771
+
772
+ **Collecting Full Response:**
773
+
774
+ ```typescript
775
+ let fullMessage = "";
776
+ let finalChunk;
777
+
778
+ for await (const chunk of agent.respondStream({ history })) {
779
+ fullMessage += chunk.delta;
780
+ if (chunk.done) {
781
+ finalChunk = chunk;
782
+ }
783
+ }
784
+
785
+ // Save to database
786
+ await db.agentMessages.create({
787
+ sessionId: session.id,
788
+ role: "assistant",
789
+ content: fullMessage,
790
+ route: finalChunk.route?.title,
791
+ toolCalls: finalChunk.toolCalls || [],
792
+ });
793
+ ```
794
+
795
+ **See Also:** [streaming-agent.ts](../examples/streaming-agent.ts) for comprehensive examples.
796
+
797
+ #### Properties
798
+
799
+ ##### `name: string`
800
+
801
+ Agent's name (readonly).
802
+
803
+ ##### `description?: string`
804
+
805
+ Agent's description (readonly).
806
+
807
+ ##### `goal?: string`
808
+
809
+ Agent's goal (readonly).
810
+
811
+ ##### `identity(): Template<TContext> | undefined`
812
+
813
+ Agent's identity template (readonly).
814
+
815
+ ---
816
+
817
+ ### `ResponseModal<TContext, TData>`
818
+
819
+ **NEW:** Internal class that handles all response generation logic for the Agent. This class centralizes response processing, provides unified streaming and non-streaming APIs, and improves maintainability.
820
+
821
+ **Note:** This class is primarily used internally by the Agent class. Most users should use the Agent's response methods (`respond`, `respondStream`, `stream`, `chat`) rather than accessing ResponseModal directly.
822
+
823
+ #### Constructor
824
+
825
+ ```typescript
826
+ new ResponseModal<TContext, TData>(
827
+ agent: Agent<TContext, TData>,
828
+ options?: ResponseModalOptions
829
+ )
830
+
831
+ interface ResponseModalOptions {
832
+ /** Maximum number of tool loops allowed during response generation */
833
+ maxToolLoops?: number;
834
+ /** Enable automatic session saving after response generation */
835
+ enableAutoSave?: boolean;
836
+ /** Enable debug mode for detailed logging */
837
+ debugMode?: boolean;
838
+ }
839
+ ```
840
+
841
+ #### Methods
842
+
843
+ ##### `respond(params: RespondParams<TContext, TData>): Promise<AgentResponse<TData>>`
844
+
845
+ Generates a non-streaming response using unified logic. This method consolidates all response generation logic including routing, tool execution, and data collection.
846
+
847
+ ##### `respondStream(params: RespondParams<TContext, TData>): AsyncGenerator<AgentResponseStreamChunk<TData>>`
848
+
849
+ Generates a streaming response using unified logic. Provides the same functionality as `respond()` but delivers results incrementally.
850
+
851
+ ##### `stream(message?: string, options?: StreamOptions<TContext>): AsyncGenerator<AgentResponseStreamChunk<TData>>`
852
+
853
+ Modern streaming API with automatic session management. This is the recommended way to implement streaming responses.
854
+
855
+ ```typescript
856
+ // Simple usage
857
+ for await (const chunk of responseModal.stream("Hello")) {
858
+ console.log(chunk.delta);
859
+ }
860
+
861
+ // With options
862
+ for await (const chunk of responseModal.stream("Hello", {
863
+ contextOverride: { userId: "123" },
864
+ signal: abortController.signal
865
+ })) {
866
+ console.log(chunk.delta);
867
+ }
868
+ ```
869
+
870
+ ##### `generate(message?: string, options?: GenerateOptions<TContext>): Promise<AgentResponse<TData>>`
871
+
872
+ Modern non-streaming API equivalent to `chat()` but more explicit. Provides automatic session management for non-streaming responses.
873
+
874
+ ```typescript
875
+ // Simple usage
876
+ const response = await responseModal.generate("Hello");
877
+ console.log(response.message);
878
+
879
+ // With options
880
+ const response = await responseModal.generate("Hello", {
881
+ contextOverride: { userId: "123" }
882
+ });
883
+ ```
884
+
885
+ #### Error Handling
886
+
887
+ ResponseModal includes comprehensive error handling with the `ResponseGenerationError` class:
888
+
889
+ ```typescript
890
+ try {
891
+ const response = await responseModal.respond(params);
892
+ } catch (error) {
893
+ if (ResponseGenerationError.isResponseGenerationError(error)) {
894
+ console.log("Response generation failed:", error.message);
895
+ console.log("Phase:", error.details?.phase);
896
+ console.log("Original error:", error.details?.originalError);
897
+ }
898
+ }
899
+ ```
900
+
901
+ #### Architecture Benefits
902
+
903
+ - **Separation of Concerns**: Agent focuses on configuration and orchestration, ResponseModal handles response generation
904
+ - **Unified Logic**: Both streaming and non-streaming responses use the same underlying logic
905
+ - **Modern APIs**: Provides simple `stream()` and `generate()` methods alongside legacy compatibility
906
+ - **Error Handling**: Comprehensive error handling with detailed context
907
+ - **Performance**: Optimized response pipeline with minimal duplication
908
+
909
+ ---
910
+
911
+ ### `Route`
912
+
913
+ Represents a conversation flow with steps and transitions.
914
+
915
+ #### Constructor
916
+
917
+ ```typescript
918
+ new Route(options: RouteOptions)
919
+
920
+ interface RouteOptions<TData = unknown> {
921
+ id?: string; // Optional custom ID (deterministic ID generated from title if not provided)
922
+ title: string; // Route title
923
+ description?: string; // Route description
924
+ identity?: string; // Optional identity prompt defining the agent's role and persona for this route
925
+ personality?: Template; // Optional personality prompt defining the agent's communication style for this route
926
+ when?: ConditionTemplate; // NEW: Conditions that activate this route (replaces conditions)
927
+ skipIf?: ConditionTemplate; // NEW: Conditions that exclude this route from consideration
928
+ guidelines?: Guideline[]; // Initial guidelines for this route
929
+ terms?: Term[]; // Initial terms for the route's domain glossary
930
+ rules?: string[]; // Absolute rules the agent MUST follow in this route
931
+ prohibitions?: string[]; // Absolute prohibitions the agent MUST NEVER do in this route
932
+
933
+ // NEW: Schema-first data extraction
934
+ schema?: {
935
+ type: "object";
936
+ properties: Record<string, any>;
937
+ required?: string[];
938
+ additionalProperties?: boolean;
939
+ };
940
+
941
+ // NEW: Pre-populate collected data when entering route
942
+ initialData?: Partial<TData>;
943
+
944
+ // NEW: Configure the initial step
945
+ initialStep?: {
946
+ id?: string; // Custom ID for the initial step
947
+ prompt?: string; // Description for the initial step
948
+ collect?: string[]; // Fields to collect in the initial step
949
+ skipIf?: (data: Partial<TData>) => boolean; // Skip condition
950
+ requires?: string[]; // Required data prerequisites
951
+ };
952
+
953
+ // NEW: Sequential steps for simple linear flows
954
+ steps?: StepOptions<unknown, TData>[];
955
+ /** Knowledge base specific to this route containing any JSON structure the AI should know */
956
+ knowledgeBase?: Record<string, unknown>;
957
+ /**
958
+ * Route lifecycle hooks
959
+ */
960
+ hooks?: RouteLifecycleHooks<TContext, TData>;
961
+ }
962
+ ```
963
+
964
+ **Note on IDs:** Route IDs are deterministic by default, generated from the title using a hash function. This ensures consistency across server restarts. You can provide a custom ID if you need specific control over the identifier.
965
+
966
+ **Initial Step Configuration:** You can configure the initial step in two ways:
967
+
968
+ 1. Using `initialStep` option when creating the route
969
+ 2. Using `route.initialStep.configure()` method after route creation
970
+
971
+ #### Methods
972
+
973
+ ##### `createGuideline(guideline: Guideline): this`
974
+
975
+ Adds a guideline specific to this route. Returns `this` for chaining.
976
+
977
+ ##### `getGuidelines(): Guideline[]`
978
+
979
+ Returns all guidelines for this route.
980
+
981
+ ##### `createTerm(term: Term): this`
982
+
983
+ Adds a term to the route's domain glossary. Returns `this` for chaining.
984
+
985
+ ##### `getTerms(): Term[]`
986
+
987
+ Returns all terms in the route's domain glossary.
988
+
989
+ ##### `getRules(): string[]`
990
+
991
+ Returns the rules that must be followed in this route.
992
+
993
+ ##### `getProhibitions(): string[]`
994
+
995
+ Returns the prohibitions that must never be done in this route.
996
+
997
+ ##### `getKnowledgeBase(): Record<string, unknown>`
998
+
999
+ Gets the route's knowledge base containing any JSON structure the AI should know.
1000
+
1001
+ ```typescript
1002
+ const knowledge = route.getKnowledgeBase();
1003
+ // Returns the route-specific knowledge base
1004
+ ```
1005
+
1006
+ ##### `getRef(): RouteRef`
1007
+
1008
+ Returns a reference to this route.
1009
+
1010
+ ##### `getAllSteps(): Step<TContext, TData>[]`
1011
+
1012
+ Gets all steps in this route via traversal from the initial step.
1013
+
1014
+ ```typescript
1015
+ const steps = route.getAllSteps();
1016
+ // Returns array of all steps in the route
1017
+ ```
1018
+
1019
+ ##### `getStep(stepId: string): Step<TContext, TData> | undefined`
1020
+
1021
+ Gets a specific step by ID.
1022
+
1023
+ ```typescript
1024
+ const step = route.getStep("ask_destination");
1025
+ // Returns the step with the specified ID or undefined
1026
+ ```
1027
+
1028
+ ##### `describe(): string`
1029
+
1030
+ Generates a description of this route's structure for debugging.
1031
+
1032
+ ```typescript
1033
+ const description = route.describe();
1034
+ console.log(description);
1035
+ // Output:
1036
+ // Route: Book Flight
1037
+ // ID: route_book_flight
1038
+ // Description: N/A
1039
+ // When: None
1040
+ //
1041
+ // Steps:
1042
+ // - step_ask_destination: Ask where to fly
1043
+ // -> step_ask_dates: Ask about travel dates
1044
+ // -> step_ask_passengers: How many passengers?
1045
+ ```
1046
+
1047
+ ##### `handleDataUpdate(data, previousCollected): Promise<Partial<TData>>`
1048
+
1049
+ Handles data updates for this route, calling the onDataUpdate hook if configured. Returns modified data after hook processing, or original data if no hook.
1050
+
1051
+ ```typescript
1052
+ const updatedData = await route.handleDataUpdate(newData, previousData);
1053
+ ```
1054
+
1055
+ **Parameters:**
1056
+
1057
+ - `data`: New collected data
1058
+ - `previousCollected`: Previously collected data
1059
+
1060
+ **Returns:** Modified data after hook processing
1061
+
1062
+ ##### `handleContextUpdate(newContext, previousContext): Promise<void>`
1063
+
1064
+ Handles context updates for this route, calling the onContextUpdate hook if configured.
1065
+
1066
+ ```typescript
1067
+ await route.handleContextUpdate(newContext, previousContext);
1068
+ ```
1069
+
1070
+ **Parameters:**
1071
+
1072
+ - `newContext`: New context
1073
+ - `previousContext`: Previous context
1074
+
1075
+ ##### `evaluateOnComplete(session, context?): Promise<RouteTransitionConfig<TContext, TData> | undefined>`
1076
+
1077
+ Evaluates the onComplete handler and returns transition config.
1078
+
1079
+ ```typescript
1080
+ const transition = await route.evaluateOnComplete(
1081
+ { data: session.data },
1082
+ context
1083
+ );
1084
+
1085
+ if (transition) {
1086
+ // Transition to next route
1087
+ console.log(`Next route: ${transition.nextStep}`);
1088
+ }
1089
+ ```
1090
+
1091
+ **Note:** Routes no longer have a `getData()` method. Use `agent.getData()` or `agent.getData(routeId)` instead.
1092
+
1093
+ #### Properties
1094
+
1095
+ ##### `id: string`
1096
+
1097
+ Unique route identifier (readonly).
1098
+
1099
+ ##### `title: string`
1100
+
1101
+ Route title (readonly).
1102
+
1103
+ ##### `description?: string`
1104
+
1105
+ Route description (readonly).
1106
+
1107
+ ##### `when?: ConditionTemplate`
1108
+
1109
+ **NEW:** Conditions that trigger this route (readonly). Can be a string, function, or array of either.
1110
+
1111
+ ##### `skipIf?: ConditionTemplate`
1112
+
1113
+ **NEW:** Conditions that exclude this route from consideration (readonly). Can be a string, function, or array of either.
1114
+
1115
+ ##### `initialStep: Step`
1116
+
1117
+ Starting step of the route (readonly).
1118
+
1119
+ ##### `hooks?: RouteLifecycleHooks<TContext, TData>`
1120
+
1121
+ Route lifecycle hooks for managing route-specific data and behavior (readonly).
1122
+
1123
+ ---
1124
+
1125
+ ### `Step`
1126
+
1127
+ Represents a step within a conversation route.
1128
+
1129
+ #### Methods
1130
+
1131
+ ##### `nextStep(spec: StepOptions): Step`
1132
+
1133
+ Creates a transition from this step and returns a chainable result.
1134
+
1135
+ ```typescript
1136
+ interface StepOptions<TData = unknown> {
1137
+ id?: string; // step id
1138
+ description?: string; // Step description
1139
+ prompt?: string; // Transition to a chat interaction
1140
+ tool?: ToolRef; // Transition to execute a tool
1141
+ step?: StepRef | symbol; // Transition to specific step or END_ROUTE
1142
+
1143
+ // NEW: Data extraction fields for this step
1144
+ collect?: string[];
1145
+
1146
+ // ENHANCED: Flexible condition to determine when this step should be active
1147
+ when?: ConditionTemplate<TContext, TData>;
1148
+
1149
+ // ENHANCED: Flexible condition to skip this step
1150
+ skipIf?: ConditionTemplate<TContext, TData>;
1151
+
1152
+ // NEW: Prerequisites that must be met to enter this step
1153
+ requires?: string[];
1154
+ }
1155
+
1156
+ interface Step<TContext = unknown, TData = unknown> {
1157
+ id: string; // Step identifier
1158
+ routeId: string; // Route identifier
1159
+ nextStep: (spec: StepOptions<TContext, TData>) => Step<TContext, TData>;
1160
+ description?: string; // Step description
1161
+ collect?: (keyof TData)[]; // Fields to collect in this step
1162
+ when?: ConditionTemplate<TContext, TData>; // ENHANCED: Flexible condition for step activation
1163
+ skipIf?: ConditionTemplate<TContext, TData>; // ENHANCED: Flexible condition to skip step
1164
+ requires?: (keyof TData)[]; // Required data prerequisites
1165
+ }
1166
+ ```
1167
+
1168
+ **Parameters:**
1169
+
1170
+ - `spec`: The transition specification (see `StepOptions` above). Can include an optional `condition` property for AI-evaluated step selection guidance.
1171
+
1172
+ **Returns:** A `Step` that includes the target step's reference (`id`, `routeId`) and a `nextStep` method for chaining additional transitions.
1173
+
1174
+ **Example:**
1175
+
1176
+ ```typescript
1177
+ // Define your data extraction type
1178
+ interface FlightData {
1179
+ destination: string;
1180
+ departureDate: string;
1181
+ passengers: number;
1182
+ }
1183
+
1184
+ // Create a data-driven route
1185
+ const flightRoute = agent.createRoute<FlightData>({
1186
+ title: "Book Flight",
1187
+ schema: {
1188
+ type: "object",
1189
+ properties: {
1190
+ destination: { type: "string" },
1191
+ departureDate: { type: "string" },
1192
+ passengers: { type: "number", minimum: 1, maximum: 9 },
1193
+ },
1194
+ required: ["destination", "departureDate", "passengers"],
1195
+ },
1196
+ });
1197
+
1198
+ // Approach 1: Step-by-step with data extraction and text conditions
1199
+ const askDestination = flightRoute.initialStep.nextStep({
1200
+ prompt: "Ask where they want to fly",
1201
+ collect: ["destination"],
1202
+ skipIf: (data) => !!data.destination, // Skip if already have destination
1203
+ condition: "Customer hasn't specified destination yet", // AI-evaluated condition
1204
+ });
1205
+
1206
+ const askDates = askDestination.nextStep({
1207
+ prompt: "Ask about travel dates",
1208
+ collect: ["departureDate"],
1209
+ skipIf: (data) => !!data.departureDate,
1210
+ requires: ["destination"], // Must have destination first
1211
+ condition: "Destination confirmed, need travel dates",
1212
+ });
1213
+
1214
+ const askPassengers = askDates.nextStep({
1215
+ prompt: "How many passengers?",
1216
+ collect: ["passengers"],
1217
+ skipIf: (data) => !!data.passengers,
1218
+ });
1219
+
1220
+ // Access step properties
1221
+ console.log(askDestination.id); // Step ID
1222
+ console.log(askDestination.routeId); // Route ID
1223
+
1224
+ // Approach 2: Fluent chaining for linear flows
1225
+ flightRoute.initialStep
1226
+ .nextStep({
1227
+ prompt: "Extract travel details",
1228
+ collect: ["destination", "departureDate", "passengers"],
1229
+ })
1230
+ .nextStep({
1231
+ prompt: "Present available flights",
1232
+ })
1233
+ .nextStep({ step: END_ROUTE });
1234
+
1235
+ // Automatic session management
1236
+ const agent = new Agent({
1237
+ name: "Travel Agent",
1238
+ provider: new OpenAIProvider({ apiKey: process.env.OPENAI_API_KEY }),
1239
+ persistence: { adapter: new PrismaAdapter({ prisma }) },
1240
+ sessionId: "user-123" // Automatically loads or creates session
1241
+ });
1242
+
1243
+ const response = await agent.respond("I want to book a flight to Paris");
1244
+ console.log(agent.session.getData<FlightData>()); // { destination: "Paris", ... }
1245
+ ```
1246
+
1247
+ ##### `addGuideline(guideline: Guideline): void`
1248
+
1249
+ Adds a guideline specific to this step.
1250
+
1251
+ ##### `getGuidelines(): Guideline<TContext>[]`
1252
+
1253
+ Gets all guidelines for this step.
1254
+
1255
+ ```typescript
1256
+ const guidelines = step.getGuidelines();
1257
+ // Returns array of guidelines specific to this step
1258
+ ```
1259
+
1260
+ ##### `getTransitions(): Step<TContext, TData>[]`
1261
+
1262
+ Gets all transitions from this step.
1263
+
1264
+ ```typescript
1265
+ const nextSteps = step.getTransitions();
1266
+ // Returns array of possible next steps
1267
+ ```
1268
+
1269
+ ##### `shouldSkip(data: Partial<TData>): boolean`
1270
+
1271
+ Checks if this step should be skipped based on collected data.
1272
+
1273
+ ```typescript
1274
+ if (step.shouldSkip(session.data)) {
1275
+ // Skip this step
1276
+ }
1277
+ ```
1278
+
1279
+ ##### `hasRequires(data: Partial<TData>): boolean`
1280
+
1281
+ Checks if this step has all required data to proceed.
1282
+
1283
+ ```typescript
1284
+ if (step.hasRequires(session.data)) {
1285
+ // Step can proceed
1286
+ }
1287
+ ```
1288
+
1289
+
1290
+
1291
+ ##### `configure(config): this`
1292
+
1293
+ Configure the step properties after creation. Useful for overriding initial step configuration. Returns `this` for chaining.
1294
+
1295
+ ```typescript
1296
+ // Configure initial step after route creation
1297
+ route.initialStep.configure({
1298
+ description: "Welcome! Let's get started",
1299
+ collect: ["name", "email"],
1300
+ skipIf: (data) => !!data.name && !!data.email,
1301
+ requires: [],
1302
+ prompt: "Hello! Let's get started with your information.",
1303
+ });
1304
+
1305
+ // Or configure any step
1306
+ const askName = route.initialStep.nextStep({ prompt: "Ask for name" });
1307
+ askName.configure({
1308
+ collect: ["firstName", "lastName"],
1309
+ });
1310
+ ```
1311
+
1312
+ **Parameters:**
1313
+
1314
+ - `config`: Configuration object with optional properties:
1315
+ - `description?: string` - Step description
1316
+ - `collect?: string[]` - Fields to collect in this step
1317
+ - `skipIf?: (data: Partial<TData>) => boolean` - Skip condition function
1318
+ - `requires?: string[]` - Required data prerequisites
1319
+ - `prompt?: Template<TContext, TData>` - Step prompt template
1320
+
1321
+ **Returns:** `this` for method chaining
1322
+
1323
+ #### Properties
1324
+
1325
+ ##### `id: string`
1326
+
1327
+ Unique step identifier (readonly).
1328
+
1329
+ ##### `routeId: string`
1330
+
1331
+ ID of the route this step belongs to (readonly).
1332
+
1333
+ ##### `description: string`
1334
+
1335
+ Step description (readonly).
1336
+
1337
+ ---
1338
+
1339
+ ### `StepResult`
1340
+
1341
+ Result interface returned by step transition methods that enables fluent chaining of conversation flows. Combines step reference with the ability to chain transitions and create branches.
1342
+
1343
+ #### Interface
1344
+
1345
+ ```typescript
1346
+ interface StepResult<TContext = unknown, TData = unknown> extends StepRef {
1347
+ /** Allow chaining transitions */
1348
+ nextStep: (spec: StepOptions<TContext, TData>) => StepResult<TContext, TData>;
1349
+ /** Create multiple branches from this step */
1350
+ branch: (
1351
+ branches: BranchSpec<TContext, TData>[]
1352
+ ) => BranchResult<TContext, TData>;
1353
+ /** Shortcut to end the current route */
1354
+ endRoute: (options?: Omit<StepOptions<TContext, TData>, "step">) => StepResult<TContext, TData>;
1355
+ }
1356
+ ```
1357
+
1358
+ #### Methods
1359
+
1360
+ ##### `nextStep(spec: StepOptions<TContext, TData>): StepResult<TContext, TData>`
1361
+
1362
+ Creates a transition from this step and returns a chainable result for building linear flows.
1363
+
1364
+ **Example:**
1365
+
1366
+ ```typescript
1367
+ // Linear flow chaining
1368
+ const flow = route.initialStep
1369
+ .nextStep({
1370
+ prompt: "Ask for destination",
1371
+ collect: ["destination"]
1372
+ })
1373
+ .nextStep({
1374
+ prompt: "Ask for dates",
1375
+ collect: ["departureDate", "returnDate"]
1376
+ })
1377
+ .nextStep({
1378
+ prompt: "Confirm booking details"
1379
+ });
1380
+ ```
1381
+
1382
+ ##### `branch(branches: BranchSpec<TContext, TData>[]): BranchResult<TContext, TData>`
1383
+
1384
+ Creates multiple conditional branches from this step for complex conversation flows.
1385
+
1386
+ **Example:**
1387
+
1388
+ ```typescript
1389
+ // Branching flow
1390
+ const branches = askIssueType.branch([
1391
+ {
1392
+ name: "technical",
1393
+ step: {
1394
+ prompt: "Let me help with your technical issue",
1395
+ when: "issue type is technical"
1396
+ }
1397
+ },
1398
+ {
1399
+ name: "billing",
1400
+ step: {
1401
+ prompt: "I'll connect you with billing support",
1402
+ when: "issue type is billing"
1403
+ }
1404
+ }
1405
+ ]);
1406
+
1407
+ // Continue each branch independently
1408
+ branches.technical.nextStep({ prompt: "What device are you using?" });
1409
+ branches.billing.nextStep({ prompt: "What's your account number?" });
1410
+ ```
1411
+
1412
+ ##### `endRoute(options?: Omit<StepOptions<TContext, TData>, "step">): StepResult<TContext, TData>`
1413
+
1414
+ Shortcut method to end the current route with optional completion configuration.
1415
+
1416
+ **Example:**
1417
+
1418
+ ```typescript
1419
+ // Simple route completion
1420
+ askConfirmation.endRoute();
1421
+
1422
+ // Route completion with final message
1423
+ askConfirmation.endRoute({
1424
+ prompt: "Thank you! Your booking is confirmed."
1425
+ });
1426
+ ```
1427
+
1428
+ #### Properties
1429
+
1430
+ Inherits all properties from `StepRef`:
1431
+
1432
+ ##### `id: string`
1433
+
1434
+ Step identifier (readonly).
1435
+
1436
+ ##### `routeId: string`
1437
+
1438
+ Route this step belongs to (readonly).
1439
+
1440
+ ---
1441
+
1442
+ ---
1443
+
1444
+ ## Tool Execution
1445
+
1446
+ Tools provide a powerful way to execute custom logic, access external APIs, and enrich conversation context before AI response generation.
1447
+
1448
+ **See Also:** [TOOLS.md](./TOOLS.md) - Complete guide to tool execution, lifecycle, and best practices
1449
+
1450
+ ---
1451
+
1452
+ ### `AnthropicProvider`
1453
+
1454
+ AI provider implementation for Anthropic (Claude models).
1455
+
1456
+ #### Constructor
1457
+
1458
+ ```typescript
1459
+ new AnthropicProvider(options: AnthropicProviderOptions)
1460
+
1461
+ interface AnthropicProviderOptions {
1462
+ apiKey: string;
1463
+ model: string; // Required: e.g., "claude-sonnet-4-5"
1464
+ backupModels?: string[]; // Fallback models
1465
+ config?: Partial<Omit<MessageCreateParamsNonStreaming, "model" | "messages" | "max_tokens">>;
1466
+ retryConfig?: {
1467
+ timeout?: number; // Default: 60000ms
1468
+ retries?: number; // Default: 3
1469
+ };
1470
+ }
1471
+ ```
1472
+
1473
+ **Note:** `model` is required for AnthropicProvider. Available models include:
1474
+
1475
+ - `claude-sonnet-4-5` - Latest Claude Sonnet 4.5 (most capable)
1476
+ - `claude-opus-4-1` - Claude Opus 4.1 (powerful for complex tasks)
1477
+ - `claude-sonnet-4-0` - Claude Sonnet 4.0 (stable, production-ready)
1478
+
1479
+ #### Methods
1480
+
1481
+ ##### `generateMessage<TContext>(input: GenerateMessageInput<TContext>): Promise<GenerateMessageOutput>`
1482
+
1483
+ Generates a message with retry logic and backup models using Anthropic's API.
1484
+
1485
+ **Example:**
1486
+
1487
+ ```typescript
1488
+ import { AnthropicProvider } from "@falai/agent";
1489
+
1490
+ const provider = new AnthropicProvider({
1491
+ apiKey: process.env.ANTHROPIC_API_KEY!,
1492
+ model: "claude-sonnet-4-5",
1493
+ backupModels: ["claude-opus-4-1", "claude-sonnet-4-0"],
1494
+ config: {
1495
+ temperature: 0.7,
1496
+ top_p: 0.9,
1497
+ },
1498
+ retryConfig: {
1499
+ timeout: 60000,
1500
+ retries: 3,
1501
+ },
1502
+ });
1503
+ ```
1504
+
1505
+ ---
1506
+
1507
+ ### `GeminiProvider`
1508
+
1509
+ AI provider implementation for Google Gemini.
1510
+
1511
+ #### Constructor
1512
+
1513
+ ```typescript
1514
+ new GeminiProvider(options: GeminiProviderOptions)
1515
+
1516
+ interface GeminiProviderOptions {
1517
+ apiKey: string;
1518
+ model?: string; // Default: "models/gemini-2.5-flash"
1519
+ backupModels?: string[]; // Fallback models
1520
+ retryConfig?: {
1521
+ timeout?: number; // Default: 60000ms
1522
+ retries?: number; // Default: 3
1523
+ };
1524
+ }
1525
+ ```
1526
+
1527
+ #### Methods
1528
+
1529
+ ##### `generateMessage<TContext>(input: GenerateMessageInput<TContext>): Promise<GenerateMessageOutput>`
1530
+
1531
+ Generates a message with retry logic and backup models.
1532
+
1533
+ ---
1534
+
1535
+ ### `OpenAIProvider`
1536
+
1537
+ AI provider implementation for OpenAI (GPT models).
1538
+
1539
+ #### Constructor
1540
+
1541
+ ```typescript
1542
+ new OpenAIProvider(options: OpenAIProviderOptions)
1543
+
1544
+ interface OpenAIProviderOptions {
1545
+ apiKey: string;
1546
+ model: string; // Required: e.g., "gpt-4o", "gpt-5"
1547
+ backupModels?: string[]; // Fallback models
1548
+ retryConfig?: {
1549
+ timeout?: number; // Default: 60000ms
1550
+ retries?: number; // Default: 3
1551
+ };
1552
+ }
1553
+ ```
1554
+
1555
+ **Note:** Unlike GeminiProvider, `model` is required for OpenAIProvider. Choose from available OpenAI models like "gpt-4o", "gpt-5", "gpt-4-turbo", etc.
1556
+
1557
+ #### Methods
1558
+
1559
+ ##### `generateMessage<TContext>(input: GenerateMessageInput<TContext>): Promise<GenerateMessageOutput>`
1560
+
1561
+ Generates a message with retry logic and backup models using OpenAI's API.
1562
+
1563
+ **Example:**
1564
+
1565
+ ```typescript
1566
+ import { OpenAIProvider } from "@falai/agent";
1567
+
1568
+ const provider = new OpenAIProvider({
1569
+ apiKey: process.env.OPENAI_API_KEY!,
1570
+ model: "gpt-5",
1571
+ backupModels: ["gpt-4o", "gpt-4-turbo"],
1572
+ retryConfig: {
1573
+ timeout: 60000,
1574
+ retries: 3,
1575
+ },
1576
+ });
1577
+ ```
1578
+
1579
+ ---
1580
+
1581
+ ### `OpenRouterProvider`
1582
+
1583
+ AI provider implementation for OpenRouter (access to 200+ models).
1584
+
1585
+ #### Constructor
1586
+
1587
+ ```typescript
1588
+ new OpenRouterProvider(options: OpenRouterProviderOptions)
1589
+
1590
+ interface OpenRouterProviderOptions {
1591
+ apiKey: string;
1592
+ model: string; // Required: e.g., "openai/gpt-5", "anthropic/claude-sonnet-4-5"
1593
+ backupModels?: string[]; // Fallback models
1594
+ siteUrl?: string; // Optional: your app URL for OpenRouter rankings
1595
+ siteName?: string; // Optional: your app name for OpenRouter rankings
1596
+ retryConfig?: {
1597
+ timeout?: number; // Default: 60000ms
1598
+ retries?: number; // Default: 3
1599
+ };
1600
+ }
1601
+ ```
1602
+
1603
+ **Note:** OpenRouter provides access to models from multiple providers. Model names follow the format `provider/model-name` (e.g., "openai/gpt-5", "anthropic/claude-sonnet-4-5", "google/gemini-pro").
1604
+
1605
+ #### Methods
1606
+
1607
+ ##### `generateMessage<TContext>(input: GenerateMessageInput<TContext>): Promise<GenerateMessageOutput>`
1608
+
1609
+ Generates a message with retry logic and backup models using OpenRouter's API.
1610
+
1611
+ **Example:**
1612
+
1613
+ ```typescript
1614
+ import { OpenRouterProvider } from "@falai/agent";
1615
+
1616
+ const provider = new OpenRouterProvider({
1617
+ apiKey: process.env.OPENROUTER_API_KEY!,
1618
+ model: "openai/gpt-5",
1619
+ backupModels: ["anthropic/claude-sonnet-4-5", "google/gemini-pro"],
1620
+ siteUrl: "https://yourapp.com",
1621
+ siteName: "Your App Name",
1622
+ retryConfig: {
1623
+ timeout: 60000,
1624
+ retries: 3,
1625
+ },
1626
+ });
1627
+ ```
1628
+
1629
+ **See Also:** [Providers Guide](./PROVIDERS.md) for detailed provider comparison and configuration examples.
1630
+
1631
+ ---
1632
+
1633
+ ## Persistence Adapters
1634
+
1635
+ Optional persistence for auto-saving sessions and messages. All adapters implement the `PersistenceAdapter` interface.
1636
+
1637
+ ### `PersistenceManager`
1638
+
1639
+ Manages persistence operations for sessions and messages.
1640
+
1641
+ #### Constructor
1642
+
1643
+ ```typescript
1644
+ new PersistenceManager(config: PersistenceConfig)
1645
+
1646
+ interface PersistenceConfig {
1647
+ adapter: PersistenceAdapter;
1648
+ autoSave?: boolean; // Default: true
1649
+ userId?: string; // Optional: associate with user
1650
+ }
1651
+ ```
1652
+
1653
+ #### Methods
1654
+
1655
+ ##### `createSession(data: Partial<SessionData>): Promise<SessionData>`
1656
+
1657
+ Creates a new conversation session.
1658
+
1659
+ ```typescript
1660
+ const session = await persistence.createSession({
1661
+ userId: "user_123",
1662
+ agentName: "Support Bot",
1663
+ initialData: { channel: "web" },
1664
+ });
1665
+ ```
1666
+
1667
+ ##### `getSession(sessionId: string): Promise<SessionData | null>`
1668
+
1669
+ Retrieves a session by ID.
1670
+
1671
+ ##### `findActiveSession(userId: string): Promise<SessionData | null>`
1672
+
1673
+ Finds the active session for a user.
1674
+
1675
+ ##### `getUserSessions(userId: string, limit?: number): Promise<SessionData[]>`
1676
+
1677
+ Gets all sessions for a user.
1678
+
1679
+ ##### `updateSessionStatus(sessionId: string, status: SessionStatus): Promise<SessionData | null>`
1680
+
1681
+ Updates session status ("active" | "completed" | "abandoned").
1682
+
1683
+ ##### `saveMessage(data: Partial<MessageData>): Promise<MessageData>`
1684
+
1685
+ Saves a message to the database.
1686
+
1687
+ ```typescript
1688
+ await persistence.saveMessage({
1689
+ sessionId: session.id,
1690
+ role: "user",
1691
+ content: "Hello!",
1692
+ });
1693
+ ```
1694
+
1695
+ ##### `getSessionMessages(sessionId: string, limit?: number): Promise<MessageData[]>`
1696
+
1697
+ Gets all messages for a session.
1698
+
1699
+ ##### `loadSessionHistory(sessionId: string, limit?: number): Promise<Event[]>`
1700
+
1701
+ Loads session history in Event format for agent.respond().
1702
+
1703
+ ```typescript
1704
+ const history = await persistence.loadSessionHistory(sessionId);
1705
+ const response = await agent.respond({ history });
1706
+ ```
1707
+
1708
+ ##### `completeSession(sessionId: string): Promise<SessionData | null>`
1709
+
1710
+ Marks a session as completed.
1711
+
1712
+ ##### `abandonSession(sessionId: string): Promise<SessionData | null>`
1713
+
1714
+ Marks a session as abandoned.
1715
+
1716
+ ##### `updateCollectedData(sessionId: string, collectedData: Record<string, unknown>): Promise<SessionData | null>`
1717
+
1718
+ Updates collected data in session.
1719
+
1720
+ ##### `updateRouteStep(sessionId: string, route?: string, step?: string): Promise<SessionData | null>`
1721
+
1722
+ Updates current route and step in session.
1723
+
1724
+ ##### `getUserMessages(userId?: string, limit?: number): Promise<MessageData[]>`
1725
+
1726
+ Gets messages for a user.
1727
+
1728
+ ##### `deleteSession(sessionId: string): Promise<boolean>`
1729
+
1730
+ Deletes a session and all its messages.
1731
+
1732
+ ##### `messageToEvent(message: MessageData): Event | undefined`
1733
+
1734
+ Helper: Convert message data to Event format.
1735
+
1736
+ ##### `saveSessionState(sessionId: string, sessionStep: SessionState): Promise<SessionData | null>`
1737
+
1738
+ Saves SessionState to database by converting to SessionData.
1739
+
1740
+ ```typescript
1741
+ const saved = await persistence.saveSessionState(sessionId, sessionState);
1742
+ ```
1743
+
1744
+ ##### `loadSessionState(sessionId: string): Promise<SessionState | null>`
1745
+
1746
+ Loads SessionState from database by converting from SessionData.
1747
+
1748
+ ```typescript
1749
+ const sessionState = await persistence.loadSessionState(sessionId);
1750
+ ```
1751
+
1752
+ ##### `createSessionWithStep(options: CreateSessionOptions): Promise<{ sessionData: SessionData; sessionStep: SessionState }>`
1753
+
1754
+ Creates a new session with both SessionData and initialized SessionState.
1755
+
1756
+ ```typescript
1757
+ const { sessionData, sessionStep } = await persistence.createSessionWithStep({
1758
+ userId: "user_123",
1759
+ agentName: "Travel Agent",
1760
+ initialData: { channel: "web" },
1761
+ });
1762
+ ```
1763
+
1764
+ ---
1765
+
1766
+ ### `RoutingEngine<TContext, TData>`
1767
+
1768
+ Handles route and step selection logic for conversation orchestration.
1769
+
1770
+ #### Constructor
1771
+
1772
+ ```typescript
1773
+ new RoutingEngine<TContext, TData>(options?: RoutingEngineOptions)
1774
+
1775
+ interface RoutingEngineOptions {
1776
+ allowRouteSwitch?: boolean; // Default: true
1777
+ switchThreshold?: number; // Default: 70 (0-100)
1778
+ maxCandidates?: number; // Default: 5
1779
+ }
1780
+ ```
1781
+
1782
+ #### Methods
1783
+
1784
+ ##### `decideRouteAndStep(params): Promise<RoutingDecision>`
1785
+
1786
+ Combines route selection and step selection into a single orchestrated decision.
1787
+
1788
+ **Parameters:**
1789
+
1790
+ - `routes`: Array of available routes
1791
+ - `session`: Current session state
1792
+ - `history`: Conversation history
1793
+ - `agentOptions`: Agent metadata
1794
+ - `provider`: AI provider for scoring
1795
+ - `context`: Agent context
1796
+ - `signal`: Optional abort signal
1797
+
1798
+ **Returns:** Routing decision with selected route, step, directives, and updated session
1799
+
1800
+ ---
1801
+
1802
+ ### `ResponseEngine<TContext>`
1803
+
1804
+ Builds prompts and response schemas for AI message generation.
1805
+
1806
+ #### Constructor
1807
+
1808
+ ```typescript
1809
+ new ResponseEngine<TContext>();
1810
+ ```
1811
+
1812
+ #### Methods
1813
+
1814
+ ##### `responseSchemaForRoute(route, currentStep?): StructuredSchema`
1815
+
1816
+ Builds JSON schema for AI responses based on route and current step.
1817
+
1818
+ ##### `buildResponsePrompt(params): Promise<string>`
1819
+
1820
+ Builds a comprehensive prompt for AI response generation including context, guidelines, and route information.
1821
+
1822
+ **Parameters:**
1823
+
1824
+ - `route`: Current route
1825
+ - `currentStep`: Current step in route
1826
+ - `rules`: Route-specific rules
1827
+ - `prohibitions`: Route-specific prohibitions
1828
+ - `directives`: Response directives
1829
+ - `history`: Conversation history
1830
+ - `lastMessage`: Last user message
1831
+ - `agentOptions`: Agent metadata
1832
+ - `context`: Agent context
1833
+ - `session`: Current session state
1834
+
1835
+ ##### `buildFallbackPrompt(params): Promise<string>`
1836
+
1837
+ Builds a fallback prompt when no routes are configured.
1838
+
1839
+ ---
1840
+
1841
+ ### `Events`
1842
+
1843
+ Utility functions for creating and adapting conversation events.
1844
+
1845
+ #### Functions
1846
+
1847
+ ##### `adaptEvent(event): string`
1848
+
1849
+ Adapts an event for inclusion in AI prompts by transforming it into serializable format.
1850
+
1851
+ ```typescript
1852
+ const promptText = adaptEvent(messageEvent);
1853
+ ```
1854
+
1855
+ ##### History Format
1856
+
1857
+ For conversation history, use the simplified `History` type instead of manually creating events. See the [History Format](#history-format) section below for details.
1858
+
1859
+ ##### `createToolEvent(source, toolCalls, timestamp?): Event`
1860
+
1861
+ Creates a tool execution event.
1862
+
1863
+ ```typescript
1864
+ const toolEvent = createToolEvent(MessageRole.AGENT, [
1865
+ { tool_id: "search_flights", arguments: { from: "NYC", to: "LAX" }, result: { flights: [...] } }
1866
+ ]);
1867
+ ```
1868
+
1869
+ ---
1870
+
1871
+ ### `PrismaAdapter`
1872
+
1873
+ Type-safe ORM adapter with migrations support.
1874
+
1875
+ #### Constructor
1876
+
1877
+ ```typescript
1878
+ new PrismaAdapter(options: PrismaAdapterOptions)
1879
+
1880
+ interface PrismaAdapterOptions {
1881
+ prisma: PrismaClient;
1882
+ autoMigrate?: boolean; // Default: false
1883
+ tables?: {
1884
+ sessions?: string; // Default: "AgentSession"
1885
+ messages?: string; // Default: "AgentMessage"
1886
+ };
1887
+ fieldMappings?: FieldMappings; // Custom field names
1888
+ }
1889
+ ```
1890
+
1891
+ #### Example
1892
+
1893
+ ```typescript
1894
+ import { PrismaAdapter } from "@falai/agent";
1895
+ import { PrismaClient } from "@prisma/client";
1896
+
1897
+ const prisma = new PrismaClient();
1898
+
1899
+ const agent = new Agent({
1900
+ persistence: {
1901
+ adapter: new PrismaAdapter({
1902
+ prisma,
1903
+ autoMigrate: true, // Auto-run migrations
1904
+ tables: {
1905
+ sessions: "CustomSessions",
1906
+ messages: "CustomMessages",
1907
+ },
1908
+ }),
1909
+ userId: "user_123",
1910
+ },
1911
+ });
1912
+ ```
1913
+
1914
+ **Schema Example:** See [examples/prisma-schema.example.prisma](../examples/prisma-schema.example.prisma)
1915
+
1916
+ **Full Example:** See [examples/prisma-persistence.ts](../examples/prisma-persistence.ts)
1917
+
1918
+ ---
1919
+
1920
+ ### `RedisAdapter`
1921
+
1922
+ Fast, in-memory persistence for high-throughput applications.
1923
+
1924
+ #### Constructor
1925
+
1926
+ ```typescript
1927
+ new RedisAdapter(options: RedisAdapterOptions)
1928
+
1929
+ interface RedisAdapterOptions {
1930
+ redis: RedisClient; // ioredis or redis client
1931
+ keyPrefix?: string; // Default: "agent:"
1932
+ sessionTTL?: number; // Default: 7 days (in seconds)
1933
+ messageTTL?: number; // Default: 30 days (in seconds)
1934
+ }
1935
+ ```
1936
+
1937
+ #### Example
1938
+
1939
+ ```typescript
1940
+ import { RedisAdapter } from "@falai/agent";
1941
+ import Redis from "ioredis";
1942
+
1943
+ const redis = new Redis();
1944
+
1945
+ const agent = new Agent({
1946
+ persistence: {
1947
+ adapter: new RedisAdapter({
1948
+ redis,
1949
+ keyPrefix: "chat:",
1950
+ sessionTTL: 24 * 60 * 60, // 24 hours
1951
+ messageTTL: 7 * 24 * 60 * 60, // 7 days
1952
+ }),
1953
+ },
1954
+ });
1955
+ ```
1956
+
1957
+ **Install:** `npm install ioredis` or `npm install redis`
1958
+
1959
+ **Full Example:** See [examples/redis-persistence.ts](../examples/redis-persistence.ts)
1960
+
1961
+ ---
1962
+
1963
+ ### `MongoAdapter`
1964
+
1965
+ Document-based storage with flexible schema.
1966
+
1967
+ #### Constructor
1968
+
1969
+ ```typescript
1970
+ new MongoAdapter(options: MongoAdapterOptions)
1971
+
1972
+ interface MongoAdapterOptions {
1973
+ client: MongoClient;
1974
+ databaseName: string;
1975
+ collections?: {
1976
+ sessions?: string; // Default: "agent_sessions"
1977
+ messages?: string; // Default: "agent_messages"
1978
+ };
1979
+ }
1980
+ ```
1981
+
1982
+ #### Example
1983
+
1984
+ ```typescript
1985
+ import { MongoAdapter } from "@falai/agent";
1986
+ import { MongoClient } from "mongodb";
1987
+
1988
+ const client = new MongoClient("mongodb://localhost:27017");
1989
+ await client.connect();
1990
+
1991
+ const agent = new Agent({
1992
+ persistence: {
1993
+ adapter: new MongoAdapter({
1994
+ client,
1995
+ databaseName: "myapp",
1996
+ collections: {
1997
+ sessions: "chat_sessions",
1998
+ messages: "chat_messages",
1999
+ },
2000
+ }),
2001
+ },
2002
+ });
2003
+ ```
2004
+
2005
+ **Install:** `npm install mongodb`
2006
+
2007
+ ---
2008
+
2009
+ ### `PostgreSQLAdapter`
2010
+
2011
+ Raw SQL adapter with auto table/index creation.
2012
+
2013
+ #### Constructor
2014
+
2015
+ ```typescript
2016
+ new PostgreSQLAdapter(options: PostgreSQLAdapterOptions)
2017
+
2018
+ interface PostgreSQLAdapterOptions {
2019
+ client: PgClient; // pg client
2020
+ tables?: {
2021
+ sessions?: string; // Default: "agent_sessions"
2022
+ messages?: string; // Default: "agent_messages"
2023
+ };
2024
+ }
2025
+ ```
2026
+
2027
+ #### Methods
2028
+
2029
+ ##### `initialize(): Promise<void>`
2030
+
2031
+ Creates tables and indexes if they don't exist.
2032
+
2033
+ #### Example
2034
+
2035
+ ```typescript
2036
+ import { PostgreSQLAdapter } from "@falai/agent";
2037
+ import { Client } from "pg";
2038
+
2039
+ const client = new Client({
2040
+ host: "localhost",
2041
+ database: "myapp",
2042
+ user: "postgres",
2043
+ password: "password",
2044
+ });
2045
+ await client.connect();
2046
+
2047
+ const adapter = new PostgreSQLAdapter({ client });
2048
+
2049
+ // Auto-create tables
2050
+ await adapter.initialize();
2051
+
2052
+ const agent = new Agent({
2053
+ persistence: { adapter },
2054
+ });
2055
+ ```
2056
+
2057
+ **Install:** `npm install pg`
2058
+
2059
+ ---
2060
+
2061
+ ### `SQLiteAdapter`
2062
+
2063
+ Lightweight, file-based database for local development.
2064
+
2065
+ #### Constructor
2066
+
2067
+ ```typescript
2068
+ new SQLiteAdapter(options: SQLiteAdapterOptions)
2069
+
2070
+ interface SQLiteAdapterOptions {
2071
+ db: SqliteDatabase; // better-sqlite3 database
2072
+ tables?: {
2073
+ sessions?: string; // Default: "agent_sessions"
2074
+ messages?: string; // Default: "agent_messages"
2075
+ };
2076
+ }
2077
+ ```
2078
+
2079
+ #### Methods
2080
+
2081
+ ##### `initialize(): Promise<void>`
2082
+
2083
+ Creates tables and indexes if they don't exist.
2084
+
2085
+ #### Example
2086
+
2087
+ ```typescript
2088
+ import { SQLiteAdapter } from "@falai/agent";
2089
+ import Database from "better-sqlite3";
2090
+
2091
+ const db = new Database("agent.db");
2092
+ const adapter = new SQLiteAdapter({ db });
2093
+
2094
+ // Auto-create tables
2095
+ await adapter.initialize();
2096
+
2097
+ const agent = new Agent({
2098
+ persistence: { adapter },
2099
+ });
2100
+ ```
2101
+
2102
+ **Install:** `npm install better-sqlite3`
2103
+
2104
+ **Perfect for:** Local development, testing, desktop apps, single-user applications
2105
+
2106
+ ---
2107
+
2108
+ ### `OpenSearchAdapter`
2109
+
2110
+ Full-text search and analytics-powered persistence. Compatible with OpenSearch and Elasticsearch 7.x.
2111
+
2112
+ #### Constructor
2113
+
2114
+ ```typescript
2115
+ new OpenSearchAdapter(client: OpenSearchClient, options?: OpenSearchAdapterOptions)
2116
+
2117
+ interface OpenSearchAdapterOptions {
2118
+ indices?: {
2119
+ sessions?: string; // Default: "agent_sessions"
2120
+ messages?: string; // Default: "agent_messages"
2121
+ };
2122
+ autoCreateIndices?: boolean; // Default: true
2123
+ refresh?: boolean | "wait_for"; // Default: false
2124
+ }
2125
+ ```
2126
+
2127
+ #### Methods
2128
+
2129
+ ##### `initialize(): Promise<void>`
2130
+
2131
+ Creates indices with proper mappings if they don't exist.
2132
+
2133
+ ##### `disconnect(): Promise<void>`
2134
+
2135
+ Gracefully disconnect (no-op for OpenSearch - connection pooling is automatic).
2136
+
2137
+ #### Example
2138
+
2139
+ ```typescript
2140
+ import { OpenSearchAdapter } from "@falai/agent";
2141
+ import { Client } from "@opensearch-project/opensearch";
2142
+
2143
+ const client = new Client({
2144
+ node: "https://localhost:9200",
2145
+ auth: {
2146
+ username: "admin",
2147
+ password: "admin",
2148
+ },
2149
+ });
2150
+
2151
+ const adapter = new OpenSearchAdapter(client, {
2152
+ indices: {
2153
+ sessions: "agent_sessions",
2154
+ messages: "agent_messages",
2155
+ },
2156
+ autoCreateIndices: true,
2157
+ refresh: "wait_for", // Wait for documents to be searchable
2158
+ });
2159
+
2160
+ // Auto-create indices with mappings
2161
+ await adapter.initialize();
2162
+
2163
+ const agent = new Agent({
2164
+ persistence: { adapter },
2165
+ });
2166
+ ```
2167
+
2168
+ **Install:** `npm install @opensearch-project/opensearch`
2169
+
2170
+ **Perfect for:** Full-text search, analytics, time-series analysis, AWS OpenSearch Service, Elasticsearch 7.x users
2171
+
2172
+ **Full Example:** See [examples/opensearch-persistence.ts](../examples/opensearch-persistence.ts)
2173
+
2174
+ ---
2175
+
2176
+ ### `MemoryAdapter`
2177
+
2178
+ Zero-dependency in-memory storage for testing and development.
2179
+
2180
+ #### Constructor
2181
+
2182
+ ```typescript
2183
+ new MemoryAdapter();
2184
+ ```
2185
+
2186
+ No options needed - it's ready to go! ✨
2187
+
2188
+ #### Methods
2189
+
2190
+ ##### `clear(): void`
2191
+
2192
+ Clears all stored data (useful for testing).
2193
+
2194
+ ##### `getSnapshot(): { sessions: SessionData[]; messages: MessageData[] }`
2195
+
2196
+ Returns a snapshot of all data (useful for debugging/testing).
2197
+
2198
+ #### Example
2199
+
2200
+ ```typescript
2201
+ import { MemoryAdapter } from "@falai/agent";
2202
+
2203
+ const adapter = new MemoryAdapter();
2204
+
2205
+ const agent = new Agent({
2206
+ persistence: { adapter },
2207
+ });
2208
+
2209
+ // Perfect for unit tests!
2210
+ ```
2211
+
2212
+ **Testing Example:**
2213
+
2214
+ ```typescript
2215
+ describe("Agent", () => {
2216
+ const adapter = new MemoryAdapter();
2217
+
2218
+ afterEach(() => {
2219
+ adapter.clear(); // Reset between tests
2220
+ });
2221
+
2222
+ it("should persist messages", async () => {
2223
+ const agent = new Agent({
2224
+ persistence: { adapter },
2225
+ });
2226
+
2227
+ // ... test logic ...
2228
+
2229
+ const { sessions, messages } = adapter.getSnapshot();
2230
+ expect(sessions).toHaveLength(1);
2231
+ expect(messages).toHaveLength(2);
2232
+ });
2233
+ });
2234
+ ```
2235
+
2236
+ **No installation required** - built into the framework!
2237
+
2238
+ ---
2239
+
2240
+ ### Persistence Types
2241
+
2242
+ #### `SessionData`
2243
+
2244
+ ```typescript
2245
+ interface SessionData {
2246
+ id: string;
2247
+ userId?: string;
2248
+ agentName?: string;
2249
+ status: SessionStatus; // "active" | "completed" | "abandoned"
2250
+ currentRoute?: string;
2251
+ currentStep?: string;
2252
+ collectedData?: Record<string, unknown>;
2253
+ messageCount: number;
2254
+ lastMessageAt?: Date;
2255
+ completedAt?: Date;
2256
+ createdAt: Date;
2257
+ updatedAt: Date;
2258
+ }
2259
+ ```
2260
+
2261
+ #### `MessageData`
2262
+
2263
+ ```typescript
2264
+ interface MessageData {
2265
+ id: string;
2266
+ sessionId: string;
2267
+ userId?: string;
2268
+ role: MessageRole; // "user" | "assistant" | "agent" | "system"
2269
+ content: string;
2270
+ route?: string;
2271
+ step?: string;
2272
+ toolCalls?: Array<{
2273
+ toolName: string;
2274
+ arguments: Record<string, unknown>;
2275
+ result?: unknown;
2276
+ }>;
2277
+ event?: Event;
2278
+ createdAt: Date;
2279
+ }
2280
+ ```
2281
+
2282
+ #### `PersistenceAdapter`
2283
+
2284
+ Interface for creating custom adapters:
2285
+
2286
+ ```typescript
2287
+ interface PersistenceAdapter {
2288
+ sessionRepository: SessionRepository;
2289
+ messageRepository: MessageRepository;
2290
+ initialize?(): Promise<void>; // Optional: setup tables/indexes
2291
+ disconnect?(): Promise<void>; // Optional: cleanup
2292
+ }
2293
+ ```
2294
+
2295
+ **See Also:**
2296
+
2297
+ - [docs/PERSISTENCE.md](./PERSISTENCE.md) - Complete persistence guide
2298
+ - [docs/ADAPTERS.md](./ADAPTERS.md) - Adapter comparison and details
2299
+
2300
+ ---
2301
+
2302
+ ### `PromptBuilder`
2303
+
2304
+ Constructs prompts for AI generation.
2305
+
2306
+ #### Methods
2307
+
2308
+ ##### `addIdentity(name: string, description?: string, goal?: string): this`
2309
+
2310
+ Adds agent identity section.
2311
+
2312
+ ##### `addContext(variables: ContextVariable[]): this`
2313
+
2314
+ Adds context variables.
2315
+
2316
+ ##### `addGlossary(terms: Term[]): this`
2317
+
2318
+ Adds domain glossary terms.
2319
+
2320
+ ##### `addGuidelinesForMessageGeneration(guidelines: GuidelineMatch[]): this`
2321
+
2322
+ Adds guidelines section.
2323
+
2324
+ ##### `addActiveRoutes(routes): this`
2325
+
2326
+ Adds active routes to the prompt.
2327
+
2328
+ ##### `build(): string`
2329
+
2330
+ Builds the final prompt string.
2331
+
2332
+ ---
2333
+
2334
+ ### `PromptComposer`
2335
+
2336
+ Constructs prompts for AI generation.
2337
+
2338
+ **Note:** As of the latest version, many methods in `PromptComposer` are `async` to support function-based templates.
2339
+
2340
+ #### Methods
2341
+
2342
+ ##### `addIdentity(name: string, description?: string, goal?: string): this`
2343
+
2344
+ Adds agent identity section.
2345
+
2346
+ ##### `addContext(variables: ContextVariable[]): this`
2347
+
2348
+ Adds context variables.
2349
+
2350
+ ##### `addGlossary(terms: Term[]): this`
2351
+
2352
+ Adds domain glossary terms.
2353
+
2354
+ ##### `addGuidelinesForMessageGeneration(guidelines: GuidelineMatch[]): this`
2355
+
2356
+ Adds guidelines section.
2357
+
2358
+ ##### `addActiveRoutes(routes): this`
2359
+
2360
+ Adds active routes to the prompt.
2361
+
2362
+ ##### `build(): Promise<string>`
2363
+
2364
+ Builds the final prompt string.
2365
+
2366
+ ---
2367
+
2368
+ ## Utility Functions
2369
+
2370
+ ### `Tool<TContext, TArgs, TResult, TData>`
2371
+
2372
+ Defines a type-safe tool using the Tool interface.
2373
+
2374
+ ```typescript
2375
+ interface Tool<
2376
+ TContext = unknown,
2377
+ TArgs extends unknown[] = unknown[],
2378
+ TResult = unknown,
2379
+ TData = unknown
2380
+ > {
2381
+ id: string; // Unique tool identifier
2382
+ description?: string; // Description for AI discovery
2383
+ parameters?: unknown; // JSON Schema for tool parameters
2384
+ handler: ToolHandler<TContext, TArgs, TResult, TData>; // Tool execution handler
2385
+ }
2386
+ ```
2387
+
2388
+ **Example:**
2389
+
2390
+ ```typescript
2391
+ const getTool: Tool<MyContext, [id: string], Data> = {
2392
+ id: "get_data",
2393
+ description: "Fetches data by ID",
2394
+ parameters: {
2395
+ type: "object",
2396
+ properties: {
2397
+ id: { type: "string", description: "The data ID to fetch" },
2398
+ },
2399
+ required: ["id"],
2400
+ },
2401
+ handler: async (toolContext, args) => {
2402
+ return { data: await fetchData(args.id) };
2403
+ },
2404
+ };
2405
+ ```
2406
+
2407
+ ---
2408
+
2409
+ ### `formatKnowledgeBase(data, title?, maxDepth?)`
2410
+
2411
+ Formats a JSON structure into readable markdown format for AI prompts. Handles nested objects, arrays, and primitive values.
2412
+
2413
+ ```typescript
2414
+ formatKnowledgeBase(
2415
+ data: Record<string, unknown> | unknown,
2416
+ title?: string,
2417
+ maxDepth?: number
2418
+ ): string
2419
+ ```
2420
+
2421
+ **Parameters:**
2422
+
2423
+ - `data` - The JSON data to format
2424
+ - `title` - Optional title for the knowledge base section
2425
+ - `maxDepth` - Maximum nesting depth (default: 3)
2426
+
2427
+ **Returns:** Formatted markdown string
2428
+
2429
+ **Example:**
2430
+
2431
+ ```typescript
2432
+ import { formatKnowledgeBase } from "@falai/agent";
2433
+
2434
+ const knowledge = {
2435
+ company: {
2436
+ name: "Acme Corp",
2437
+ products: ["Widget A", "Widget B"],
2438
+ locations: {
2439
+ headquarters: "NYC",
2440
+ branches: ["LA", "Chicago"],
2441
+ },
2442
+ },
2443
+ };
2444
+
2445
+ const markdown = formatKnowledgeBase(knowledge, "Company Information");
2446
+ // Output:
2447
+ // ## Company Information
2448
+ //
2449
+ // - **name**: Acme Corp
2450
+ // - **products**:
2451
+ // - Widget A
2452
+ // - Widget B
2453
+ // - **locations**:
2454
+ // - **headquarters**: NYC
2455
+ // - **branches**:
2456
+ // - LA
2457
+ // - Chicago
2458
+ ```
2459
+
2460
+ ---
2461
+
2462
+ ### History Format
2463
+
2464
+ The agent accepts a simplified history format for conversation context. This format is easier to use than the internal Event structure.
2465
+
2466
+ #### Types
2467
+
2468
+ ```typescript
2469
+ type Role = "user" | "assistant" | "tool" | "system";
2470
+
2471
+ type HistoryItem =
2472
+ | {
2473
+ role: "user";
2474
+ content: string;
2475
+ name?: string; // Optional participant name
2476
+ }
2477
+ | {
2478
+ role: "assistant";
2479
+ content: string | null;
2480
+ tool_calls?: Array<{
2481
+ id: string;
2482
+ name: string;
2483
+ arguments: Record<string, unknown>;
2484
+ }>;
2485
+ }
2486
+ | {
2487
+ role: "tool";
2488
+ tool_call_id: string;
2489
+ name: string;
2490
+ content: any;
2491
+ }
2492
+ | {
2493
+ role: "system";
2494
+ content: string;
2495
+ };
2496
+
2497
+ type History = HistoryItem[];
2498
+ ```
2499
+
2500
+ **Example:**
2501
+
2502
+ ```typescript
2503
+ // Simple conversation history
2504
+ const history: History = [
2505
+ {
2506
+ role: "user",
2507
+ content: "Hello! Can you help me book a flight?",
2508
+ name: "Alice"
2509
+ },
2510
+ {
2511
+ role: "assistant",
2512
+ content: "I'd be happy to help you book a flight. Where would you like to go?"
2513
+ },
2514
+ {
2515
+ role: "user",
2516
+ content: "I want to go to Paris next Friday for 2 people.",
2517
+ name: "Alice"
2518
+ }
2519
+ ];
2520
+
2521
+ // Assistant with tool calls
2522
+ const historyWithTools: History = [
2523
+ {
2524
+ role: "assistant",
2525
+ content: "I'll search for flights to Paris.",
2526
+ tool_calls: [
2527
+ {
2528
+ id: "search_flights_1",
2529
+ name: "search_flights",
2530
+ arguments: {
2531
+ destination: "Paris",
2532
+ date: "2025-10-18",
2533
+ passengers: 2
2534
+ }
2535
+ }
2536
+ ]
2537
+ },
2538
+ {
2539
+ role: "tool",
2540
+ tool_call_id: "search_flights_1",
2541
+ name: "search_flights",
2542
+ content: { flights: [...] } // Tool execution result
2543
+ }
2544
+ ];
2545
+ ```
2546
+
2547
+ ---
2548
+
2549
+ ### `createToolEvent()`
2550
+
2551
+ Creates a tool execution event.
2552
+
2553
+ ```typescript
2554
+ createToolEvent(
2555
+ source: MessageRole,
2556
+ toolCalls: ToolCall[],
2557
+ timestamp?: string // Optional: provide custom timestamp (ISO 8601 format)
2558
+ ): Event
2559
+ ```
2560
+
2561
+ **Example:**
2562
+
2563
+ ```typescript
2564
+ // With auto-generated timestamp
2565
+ createToolEvent(MessageRole.AGENT, [
2566
+ { tool_id: "get_data", arguments: { id: "123" }, result: { data: {...} } }
2567
+ ]);
2568
+
2569
+ // With custom timestamp
2570
+ createToolEvent(
2571
+ MessageRole.AGENT,
2572
+ [{ tool_id: "get_data", arguments: { id: "123" }, result: { data: {...} } }],
2573
+ "2025-10-13T10:30:00Z"
2574
+ );
2575
+ ```
2576
+
2577
+ ---
2578
+
2579
+ ### `adaptEvent()`
2580
+
2581
+ Adapts an event to the internal format.
2582
+
2583
+ ```typescript
2584
+ adaptEvent(event: EmittedEvent): Event
2585
+ ```
2586
+
2587
+ ---
2588
+
2589
+ ## Type Definitions
2590
+
2591
+ ### `Term`
2592
+
2593
+ ```typescript
2594
+ interface Term<TContext = unknown> {
2595
+ name: Template<TContext>;
2596
+ description: Template<TContext>;
2597
+ synonyms?: Template<TContext>[];
2598
+ }
2599
+ ```
2600
+
2601
+ ---
2602
+
2603
+ ### `Guideline`
2604
+
2605
+ ```typescript
2606
+ interface Guideline<TContext = unknown, TData = unknown> {
2607
+ id?: string;
2608
+ condition?: ConditionTemplate<TContext, TData>; // ENHANCED: Flexible condition for guideline activation
2609
+ action: Template<TContext>;
2610
+ enabled?: boolean; // Default: true
2611
+ tags?: string[];
2612
+ tools?: ToolRef[];
2613
+ metadata?: Record<string, unknown>;
2614
+ }
2615
+ ```
2616
+
2617
+ ---
2618
+
2619
+ ### `RouteLifecycleHooks<TContext, TData>`
2620
+
2621
+ Route lifecycle hooks for managing route-specific data and behavior.
2622
+
2623
+ ```typescript
2624
+ interface RouteLifecycleHooks<TContext = unknown, TData = unknown> {
2625
+ /**
2626
+ * Called after collected data is updated for this route (from AI response or tool execution)
2627
+ * Useful for validation, enrichment, or persistence of route-specific collected data
2628
+ * Return modified collected data or the same data to keep it unchanged
2629
+ *
2630
+ * Unlike Agent-level onDataUpdate, this only triggers for data changes in this specific route.
2631
+ */
2632
+ onDataUpdate?: (
2633
+ data: Partial<TData>,
2634
+ previousCollected: Partial<TData>
2635
+ ) => Partial<TData> | Promise<Partial<TData>>;
2636
+
2637
+ /**
2638
+ * Called after context is updated via updateContext() when this route is active
2639
+ * Useful for route-specific context reactions, validation, or side effects
2640
+ *
2641
+ * Unlike Agent-level onContextUpdate, this only triggers when this specific route is active.
2642
+ */
2643
+ onContextUpdate?: (
2644
+ newContext: TContext,
2645
+ previousContext: TContext
2646
+ ) => void | Promise<void>;
2647
+ }
2648
+ ```
2649
+
2650
+ ---
2651
+
2652
+ ---
2653
+
2654
+ ### `Event`
2655
+
2656
+ ```typescript
2657
+ interface Event {
2658
+ kind: EventKind;
2659
+ source: MessageRole;
2660
+ data: MessageEventData | ToolEventData | StatusEventData;
2661
+ creation_utc: string;
2662
+ }
2663
+
2664
+ enum EventKind {
2665
+ MESSAGE = "message",
2666
+ TOOL = "tool",
2667
+ STATUS = "status",
2668
+ }
2669
+
2670
+ enum MessageRole {
2671
+ USER = "user",
2672
+ ASSISTANT = "assistant",
2673
+ AGENT = "agent",
2674
+ SYSTEM = "system",
2675
+ }
2676
+ ```
2677
+
2678
+ ---
2679
+
2680
+ ### `ToolContext<TContext>`
2681
+
2682
+ ```typescript
2683
+ interface ToolContext<TContext> {
2684
+ context: TContext;
2685
+ // Additional runtime context
2686
+ }
2687
+ ```
2688
+
2689
+ ---
2690
+
2691
+ ### `ToolResult<TReturn>`
2692
+
2693
+ ```typescript
2694
+ interface ToolResult<TReturn> {
2695
+ data: TReturn;
2696
+ error?: string;
2697
+ }
2698
+ ```
2699
+
2700
+ ---
2701
+
2702
+ ### `RoutingDecision`
2703
+
2704
+ Result of route and step selection process.
2705
+
2706
+ ```typescript
2707
+ interface RoutingDecision {
2708
+ context: string;
2709
+ routes: Record<string, number>; // Route scores
2710
+ responseDirectives?: string[];
2711
+ extractions?: unknown;
2712
+ contextUpdate?: Record<string, unknown>;
2713
+ }
2714
+ ```
2715
+
2716
+ ---
2717
+
2718
+ ### `ToolExecutionResult`
2719
+
2720
+ Result of tool execution.
2721
+
2722
+ ```typescript
2723
+ interface ToolExecutionResult {
2724
+ toolName: string;
2725
+ success: boolean;
2726
+ data?: unknown;
2727
+ contextUpdate?: Record<string, unknown>;
2728
+ dataUpdate?: Record<string, unknown>;
2729
+ error?: string;
2730
+ }
2731
+ ```
2732
+
2733
+ ---
2734
+
2735
+ ## Types
2736
+
2737
+ ### `SessionState<TData>`
2738
+
2739
+ Tracks the current position in the conversation flow and data collected during route progression.
2740
+
2741
+ ```typescript
2742
+ interface SessionState<TData = Record<string, unknown>> {
2743
+ /** Unique session identifier (useful for persistence) */
2744
+ id?: string;
2745
+
2746
+ /** Current route the conversation is in */
2747
+ currentRoute?: {
2748
+ id: string;
2749
+ title: string;
2750
+ enteredAt: Date;
2751
+ };
2752
+
2753
+ /** Current step within the route */
2754
+ currentStep?: {
2755
+ id: string;
2756
+ description?: string;
2757
+ enteredAt: Date;
2758
+ };
2759
+
2760
+ /**
2761
+ * Data collected during the current route
2762
+ * Convenience reference to dataByRoute[currentRoute.id]
2763
+ */
2764
+ data?: Partial<TData>;
2765
+
2766
+ /**
2767
+ * Data collected organized by route ID
2768
+ * Persists data when switching between routes
2769
+ * Allows resuming incomplete routes where they left off
2770
+ */
2771
+ dataByRoute?: Record<string, Partial<unknown>>;
2772
+
2773
+ /** History of routes visited in this session */
2774
+ routeHistory: Array<{
2775
+ routeId: string;
2776
+ enteredAt: Date;
2777
+ exitedAt?: Date;
2778
+ completed: boolean;
2779
+ }>;
2780
+
2781
+ /**
2782
+ * Pending route transition after completion
2783
+ * Set when a route completes with onComplete handler
2784
+ */
2785
+ pendingTransition?: {
2786
+ targetRouteId: string;
2787
+ condition?: string;
2788
+ reason: "route_complete" | "manual";
2789
+ };
2790
+
2791
+ /** Session metadata */
2792
+ metadata?: {
2793
+ createdAt?: Date;
2794
+ lastUpdatedAt?: Date;
2795
+ [key: string]: unknown;
2796
+ };
2797
+ }
2798
+ ```
2799
+
2800
+ **Key Features:**
2801
+
2802
+ - **`id`** - Optional session identifier that persists across database operations
2803
+ - **`data`** - Type-safe data collected via `schema` for the **current route**
2804
+ - **`dataByRoute`** - **Per-route data map that preserves collected data when switching routes**
2805
+ - **`currentRoute`** / **`currentStep`** - Track conversation position
2806
+ - **`routeHistory`** - Full audit trail of route transitions
2807
+ - **`pendingTransition`** - Handles route completion transitions
2808
+ - **`metadata`** - Custom data (timestamps, user info, etc.)
2809
+
2810
+ **Per-Route Data Preservation:**
2811
+
2812
+ When users switch routes (e.g., "Actually, I want to book a hotel instead"), the framework automatically:
2813
+
2814
+ - Saves current route's `data` data to `dataByRoute[routeId]`
2815
+ - Loads the new route's data from `dataByRoute[newRouteId]` (if resuming)
2816
+ - Keeps `data` as a convenient reference to the current route's data
2817
+
2818
+ This allows users to:
2819
+
2820
+ - Switch routes without losing progress
2821
+ - Resume incomplete routes where they left off
2822
+ - Access historical data from previous routes via `session.dataByRoute["route_id"]`
2823
+
2824
+ **Usage:**
2825
+
2826
+ ```typescript
2827
+ interface FlightData {
2828
+ destination: string;
2829
+ departureDate: string;
2830
+ }
2831
+
2832
+ // Create session with database ID
2833
+ const session = createSession<FlightData>("session_abc123");
2834
+
2835
+ // Use in conversation
2836
+ const response = await agent.respond({ history, session });
2837
+
2838
+ // Access collected data
2839
+ console.log(response.session?.data.destination); // Type-safe!
2840
+ ```
2841
+
2842
+ ---
2843
+
2844
+ ### Session Helper Functions
2845
+
2846
+ #### `createSession<TData>(sessionId?, metadata?): SessionState<TData>`
2847
+
2848
+ Creates a new session step object.
2849
+
2850
+ **Parameters:**
2851
+
2852
+ - `sessionId` (optional): Unique session identifier from database
2853
+ - `metadata` (optional): Additional metadata to attach
2854
+
2855
+ **Example:**
2856
+
2857
+ ```typescript
2858
+ // Simple usage
2859
+ const session = createSession<OnboardingData>();
2860
+
2861
+ // With database ID (when loading from persistence)
2862
+ const session = createSession<OnboardingData>("session_123");
2863
+
2864
+ // With metadata
2865
+ const session = createSession<OnboardingData>("session_123", {
2866
+ userId: "user_456",
2867
+ channel: "whatsapp",
2868
+ });
2869
+ ```
2870
+
2871
+ #### `enterRoute<TData>(session, routeId, routeTitle): SessionState<TData>`
2872
+
2873
+ Updates session when entering a new route. Automatically:
2874
+
2875
+ - Exits previous route (if exists)
2876
+ - Resets collected data
2877
+ - Adds route to history
2878
+ - Updates timestamps
2879
+
2880
+ **Example:**
2881
+
2882
+ ```typescript
2883
+ let session = createSession<FlightData>();
2884
+
2885
+ // Enter booking route
2886
+ session = enterRoute(session, "book_flight", "Book a Flight");
2887
+
2888
+ console.log(session.currentRoute?.title); // "Book a Flight"
2889
+ console.log(session.data); // {} (reset for new route)
2890
+ ```
2891
+
2892
+ #### `enterStep<TData>(session, stepId, description?): SessionState<TData>`
2893
+
2894
+ Updates session when entering a new step within a route.
2895
+
2896
+ **Example:**
2897
+
2898
+ ```typescript
2899
+ session = enterStep(session, "ask_destination", "Ask where to fly");
2900
+
2901
+ console.log(session.currentStep?.id); // "ask_destination"
2902
+ console.log(session.currentStep?.description); // "Ask where to fly"
2903
+ ```
2904
+
2905
+ #### `mergeCollected<TData>(session, data): SessionState<TData>`
2906
+
2907
+ Merges new collected data into session. Updates timestamps automatically.
2908
+
2909
+ **Example:**
2910
+
2911
+ ```typescript
2912
+ session = mergeCollected(session, {
2913
+ destination: "Paris",
2914
+ departureDate: "2025-06-15",
2915
+ });
2916
+
2917
+ console.log(session.data); // { destination: "Paris", departureDate: "2025-06-15" }
2918
+ ```
2919
+
2920
+ #### `sessionStepToData<TData>(session): object`
2921
+
2922
+ Converts SessionState to persistence-friendly format for database storage.
2923
+
2924
+ **Returns:**
2925
+
2926
+ ```typescript
2927
+ {
2928
+ currentRoute?: string; // Route ID
2929
+ currentStep?: string; // Step ID
2930
+ collectedData: { // All session data
2931
+ data: Partial<TData>;
2932
+ routeHistory: Array<...>;
2933
+ currentRouteTitle?: string;
2934
+ currentStepDescription?: string;
2935
+ metadata?: object;
2936
+ };
2937
+ }
2938
+ ```
2939
+
2940
+ **Example:**
2941
+
2942
+ ```typescript
2943
+ const session = createSession<FlightData>("session_123");
2944
+ // ... conversation happens ...
2945
+
2946
+ // Save to database
2947
+ const dbData = sessionStepToData(session);
2948
+ await db.sessions.update(session.id!, {
2949
+ currentRoute: dbData.currentRoute,
2950
+ currentStep: dbData.currentStep,
2951
+ collectedData: dbData.collectedData,
2952
+ });
2953
+ ```
2954
+
2955
+ #### `sessionDataToStep<TData>(sessionId, data): SessionState<TData>`
2956
+
2957
+ Converts database data back to SessionState for resuming conversations.
2958
+
2959
+ **Parameters:**
2960
+
2961
+ - `sessionId`: The database session ID
2962
+ - `data`: Database session data (currentRoute, currentStep, collectedData)
2963
+
2964
+ **Example:**
2965
+
2966
+ ```typescript
2967
+ // Load from database
2968
+ const dbSession = await db.sessions.findById("session_123");
2969
+
2970
+ // Restore session step
2971
+ const session = sessionDataToStep<FlightData>(dbSession.id, {
2972
+ currentRoute: dbSession.currentRoute,
2973
+ currentStep: dbSession.currentStep,
2974
+ collectedData: dbSession.collectedData,
2975
+ });
2976
+
2977
+ // Resume conversation
2978
+ const response = await agent.respond({ history, session });
2979
+ ```
2980
+
2981
+ **Complete Persistence Example:**
2982
+
2983
+ ```typescript
2984
+ // CREATE: New session
2985
+ let session = createSession<FlightData>(dbSession.id);
2986
+
2987
+ // CONVERSATION: Extract data
2988
+ const response1 = await agent.respond({ history: history1, session });
2989
+ session = response1.session!; // { data: { destination: "Paris" } }
2990
+
2991
+ // SAVE: To database
2992
+ const saveData = sessionStepToData(session);
2993
+ await db.sessions.update(session.id!, saveData);
2994
+
2995
+ // --- Later (new request) ---
2996
+
2997
+ // LOAD: From database
2998
+ const loaded = await db.sessions.findById("session_123");
2999
+ const restored = sessionDataToStep<FlightData>(loaded.id, loaded);
3000
+
3001
+ // CONTINUE: Conversation
3002
+ const response2 = await agent.respond({ history: history2, session: restored });
3003
+ ```
3004
+
3005
+ ---
3006
+
3007
+ ### `AgentStructuredResponse`
3008
+
3009
+ The structured response format returned by AI providers when JSON mode is enabled.
3010
+
3011
+ ```typescript
3012
+ interface AgentStructuredResponse {
3013
+ /** The actual message to send to the user */
3014
+ message: string;
3015
+ /** Route chosen by the agent (route title or null if no route) */
3016
+ route?: string | null;
3017
+ /** Current step within the route (step description or null) */
3018
+ step?: string | null;
3019
+ /** Tool calls the agent wants to execute */
3020
+ toolCalls?: Array<{
3021
+ toolName: string;
3022
+ arguments: Record<string, unknown>;
3023
+ }>;
3024
+ /** Additional reasoning or internal thoughts (optional) */
3025
+ reasoning?: string;
3026
+ }
3027
+ ```
3028
+
3029
+ This type represents the structured JSON output that AI providers return when using the enhanced response format. The `Agent.respond()` method automatically parses this and returns a more convenient format.
3030
+
3031
+ ---
3032
+
3033
+ ### ID Generation Utilities
3034
+
3035
+ Generate deterministic IDs for consistency across server restarts.
3036
+
3037
+ #### `generateRouteId(title: string): string`
3038
+
3039
+ Generates a deterministic route ID from a title.
3040
+
3041
+ ```typescript
3042
+ import { generateRouteId } from "@falai/agent";
3043
+
3044
+ const routeId = generateRouteId("User Onboarding");
3045
+ // Returns: "route_user_onboarding_{hash}"
3046
+ ```
3047
+
3048
+ #### `generateStepId(routeId: string, description?: string, index?: number): string`
3049
+
3050
+ Generates a deterministic step ID.
3051
+
3052
+ ```typescript
3053
+ import { generateStepId } from "@falai/agent";
3054
+
3055
+ const stepId = generateStepId("route_123", "Ask for name");
3056
+ // Returns: "step_ask_for_name_{hash}"
3057
+ ```
3058
+
3059
+ #### `generateToolId(name: string): string`
3060
+
3061
+ Generates a deterministic tool ID from a name.
3062
+
3063
+ ```typescript
3064
+ import { generateToolId } from "@falai/agent";
3065
+
3066
+ const toolId = generateToolId("get_user_data");
3067
+ // Returns: "tool_get_user_data_{hash}"
3068
+ ```
3069
+
3070
+ **Why Deterministic IDs?**
3071
+
3072
+ All IDs are generated deterministically using a hash function of their content (title, name, description). This ensures:
3073
+
3074
+ - **Consistency** - Same input always produces the same ID
3075
+ - **Server Restart Safe** - IDs remain stable across application restarts
3076
+ - **Persistence Friendly** - Safe to store in databases and reference later
3077
+ - **Custom Control** - You can always provide your own IDs when needed
3078
+
3079
+ ---
3080
+
3081
+ ## Constants
3082
+
3083
+ ### `END_ROUTE`
3084
+
3085
+ Symbol marking the end of a conversation route. Use this when building routes to mark where they should end.
3086
+
3087
+ ```typescript
3088
+ import { END_ROUTE } from "@falai/agent";
3089
+
3090
+ const thankYou = askEmail.nextStep({
3091
+ prompt: "Thank you for your information!",
3092
+ });
3093
+
3094
+ // Mark the end of the route
3095
+ thankYou.nextStep({ step: END_ROUTE });
3096
+ ```
3097
+
3098
+ ### `END_ROUTE_ID`
3099
+
3100
+ String constant representing END_ROUTE for runtime comparisons. When a route completes, `currentStep.id` is set to this value.
3101
+
3102
+ ```typescript
3103
+ import { END_ROUTE_ID } from "@falai/agent";
3104
+
3105
+ const response = await agent.respond({ history, session });
3106
+
3107
+ // Method 1: Using isRouteComplete (recommended)
3108
+ if (response.isRouteComplete) {
3109
+ console.log("Route completed!");
3110
+ }
3111
+
3112
+ // Method 2: Using END_ROUTE_ID constant
3113
+ if (response.session?.currentStep?.id === END_ROUTE_ID) {
3114
+ console.log("Route completed!");
3115
+ }
3116
+ ```
3117
+
3118
+ **Note:** Both methods are equivalent. Use `isRouteComplete` for simplicity, or `END_ROUTE_ID` for consistency with how you build routes.
3119
+
3120
+ ---
3121
+
3122
+ ## Enums
3123
+
3124
+ ### `CompositionMode`
3125
+
3126
+ ```typescript
3127
+ enum CompositionMode {
3128
+ FLUID = "fluid",
3129
+ CANNED_FLUID = "canned_fluid",
3130
+ CANNED_COMPOSITED = "composited_canned",
3131
+ CANNED_STRICT = "strict_canned",
3132
+ }
3133
+ ```
3134
+
3135
+ ---
3136
+
3137
+ ### `BuiltInSection`
3138
+
3139
+ Prompt builder section identifiers.
3140
+
3141
+ ```typescript
3142
+ enum BuiltInSection {
3143
+ IDENTITY = "identity",
3144
+ GLOSSARY = "glossary",
3145
+ CONTEXT = "context",
3146
+ GUIDELINES = "guidelines",
3147
+ TOOLS
3148
+ ACTIVE_ROUTES = "active_routes",
3149
+ }
3150
+ ```
3151
+
3152
+ ---
3153
+
3154
+ ## Advanced Topics
3155
+
3156
+ ### Custom AI Providers
3157
+
3158
+ Implement the `AiProvider` interface:
3159
+
3160
+ ```typescript
3161
+ interface AiProvider {
3162
+ generateMessage<TContext = unknown>(
3163
+ input: GenerateMessageInput<TContext>
3164
+ ): Promise<GenerateMessageOutput>;
3165
+ }
3166
+ ```
3167
+
3168
+ ---
3169
+
3170
+ ## Template Utilities
3171
+
3172
+ ### Dynamic Content with Templates
3173
+
3174
+ The framework supports dynamic content generation through a versatile `Template` system. A `Template` can be either a simple string with `{{variable}}` placeholders or a function that returns a string, allowing for more complex, context-aware logic.
3175
+
3176
+ Templates are evaluated at runtime with a `TemplateContext` object that provides access to the agent's state:
3177
+
3178
+ ```typescript
3179
+ interface TemplateContext<TContext = unknown, TData = unknown> {
3180
+ context?: TContext;
3181
+ session?: SessionState<TData>;
3182
+ history?: Event[];
3183
+ data?: Partial<TData>; // Convenience alias for session.data
3184
+ }
3185
+ ```
3186
+
3187
+ #### `Template<TContext, TData>` Type
3188
+
3189
+ This is the core type for all dynamic content:
3190
+
3191
+ ```typescript
3192
+ type Template<TContext = unknown, TData = unknown> =
3193
+ | string
3194
+ | ((params: TemplateContext<TContext, TData>) => string | Promise<string>);
3195
+ ```
3196
+
3197
+ **String Templates:**
3198
+
3199
+ Simple strings with `{{variable}}` placeholders are rendered using values from the `context` object.
3200
+
3201
+ ```typescript
3202
+ const agent = new Agent({
3203
+ identity: "I am {{name}}",
3204
+ context: { name: "HelperBot" },
3205
+ });
3206
+ ```
3207
+
3208
+ **Function Templates:**
3209
+
3210
+ For more complex logic, you can provide a function that receives the `TemplateContext` and returns a string (or a `Promise<string>` for async operations).
3211
+
3212
+ ```typescript
3213
+ const agent = new Agent({
3214
+ identity: ({ context }) => `I am here to help, ${context.user.name}`,
3215
+ context: { user: { name: "Alice" } },
3216
+ });
3217
+ ```
3218
+
3219
+ #### `render(template, params)`
3220
+
3221
+ An internal async utility that resolves a `Template` to a string. You won't typically call this directly, but it powers the dynamic content generation throughout the framework.
3222
+
3223
+ **Supported in (Dynamic/Personalized):**
3224
+
3225
+ - **Agent**: `identity`
3226
+ - **Terms**: `name`, `description`, `synonyms`
3227
+ - **Guidelines**: `condition`, `action`
3228
+ - **Routes**: `conditions`, `rules`, `prohibitions`
3229
+ - **Steps/Transitions**: `prompt`, `condition`
3230
+
3231
+ **Not supported in (Static/Predictable):**
3232
+
3233
+ - Agent `name`, `goal`, `description`
3234
+ - Route `title`, `description`
3235
+ - Step `description`
3236
+
3237
+ **Example:**
3238
+
3239
+ ```typescript
3240
+ const agent = new Agent({
3241
+ name: "Assistant", // Static
3242
+ identity: ({ context }) =>
3243
+ `I am here to help you, ${context.user.firstName}.`, // Dynamic
3244
+ context: {
3245
+ user: { firstName: "Alice", age: 30 },
3246
+ },
3247
+ });
3248
+
3249
+ agent.createGuideline({
3250
+ condition: ({ context }) => context.user.age > 18, // Dynamic condition
3251
+ action:
3252
+ "Be helpful to {{user.firstName}} and consider their age in responses", // Dynamic action
3253
+ });
3254
+ ```
3255
+
3256
+ ---
3257
+
3258
+ **Made with ❤️ for the community**