@falai/agent 1.2.8 → 2.0.1

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