@falai/agent 1.2.8 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (499) 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/types/agent.d.ts +183 -54
  126. package/dist/cjs/types/agent.d.ts.map +1 -1
  127. package/dist/cjs/types/agent.js +0 -6
  128. package/dist/cjs/types/agent.js.map +1 -1
  129. package/dist/cjs/types/ai.d.ts +3 -3
  130. package/dist/cjs/types/ai.d.ts.map +1 -1
  131. package/dist/cjs/types/errors.d.ts +15 -0
  132. package/dist/cjs/types/errors.d.ts.map +1 -0
  133. package/dist/cjs/types/errors.js +22 -0
  134. package/dist/cjs/types/errors.js.map +1 -0
  135. package/dist/cjs/types/flow.d.ts +513 -0
  136. package/dist/cjs/types/flow.d.ts.map +1 -0
  137. package/dist/cjs/types/{route.js → flow.js} +2 -2
  138. package/dist/cjs/types/flow.js.map +1 -0
  139. package/dist/cjs/types/index.d.ts +7 -6
  140. package/dist/cjs/types/index.d.ts.map +1 -1
  141. package/dist/cjs/types/index.js +6 -2
  142. package/dist/cjs/types/index.js.map +1 -1
  143. package/dist/cjs/types/persistence.d.ts +11 -7
  144. package/dist/cjs/types/persistence.d.ts.map +1 -1
  145. package/dist/cjs/types/routing.d.ts +1 -1
  146. package/dist/cjs/types/routing.d.ts.map +1 -1
  147. package/dist/cjs/types/session.d.ts +24 -23
  148. package/dist/cjs/types/session.d.ts.map +1 -1
  149. package/dist/cjs/types/signals.d.ts +248 -0
  150. package/dist/cjs/types/signals.d.ts.map +1 -0
  151. package/dist/cjs/types/signals.js +11 -0
  152. package/dist/cjs/types/signals.js.map +1 -0
  153. package/dist/cjs/types/template.d.ts +2 -8
  154. package/dist/cjs/types/template.d.ts.map +1 -1
  155. package/dist/cjs/types/tool.d.ts +36 -29
  156. package/dist/cjs/types/tool.d.ts.map +1 -1
  157. package/dist/cjs/types/tool.js +1 -1
  158. package/dist/cjs/types/tool.js.map +1 -1
  159. package/dist/cjs/utils/condition.d.ts +7 -1
  160. package/dist/cjs/utils/condition.d.ts.map +1 -1
  161. package/dist/cjs/utils/condition.js.map +1 -1
  162. package/dist/cjs/utils/id.d.ts +13 -5
  163. package/dist/cjs/utils/id.d.ts.map +1 -1
  164. package/dist/cjs/utils/id.js +24 -10
  165. package/dist/cjs/utils/id.js.map +1 -1
  166. package/dist/cjs/utils/index.d.ts +2 -2
  167. package/dist/cjs/utils/index.d.ts.map +1 -1
  168. package/dist/cjs/utils/index.js +7 -3
  169. package/dist/cjs/utils/index.js.map +1 -1
  170. package/dist/cjs/utils/session.d.ts +44 -5
  171. package/dist/cjs/utils/session.d.ts.map +1 -1
  172. package/dist/cjs/utils/session.js +197 -38
  173. package/dist/cjs/utils/session.js.map +1 -1
  174. package/dist/constants/index.d.ts +0 -9
  175. package/dist/constants/index.d.ts.map +1 -1
  176. package/dist/constants/index.js +3 -9
  177. package/dist/constants/index.js.map +1 -1
  178. package/dist/core/Agent.d.ts +119 -153
  179. package/dist/core/Agent.d.ts.map +1 -1
  180. package/dist/core/Agent.js +472 -325
  181. package/dist/core/Agent.js.map +1 -1
  182. package/dist/core/AutoChainExecutor.d.ts +107 -0
  183. package/dist/core/AutoChainExecutor.d.ts.map +1 -0
  184. package/dist/core/AutoChainExecutor.js +293 -0
  185. package/dist/core/AutoChainExecutor.js.map +1 -0
  186. package/dist/core/BranchEvaluator.d.ts +54 -0
  187. package/dist/core/BranchEvaluator.d.ts.map +1 -0
  188. package/dist/core/BranchEvaluator.js +126 -0
  189. package/dist/core/BranchEvaluator.js.map +1 -0
  190. package/dist/core/DirectiveBus.d.ts +88 -0
  191. package/dist/core/DirectiveBus.d.ts.map +1 -0
  192. package/dist/core/DirectiveBus.js +192 -0
  193. package/dist/core/DirectiveBus.js.map +1 -0
  194. package/dist/core/DirectiveChainTracker.d.ts +49 -0
  195. package/dist/core/DirectiveChainTracker.d.ts.map +1 -0
  196. package/dist/core/DirectiveChainTracker.js +117 -0
  197. package/dist/core/DirectiveChainTracker.js.map +1 -0
  198. package/dist/core/Flow.d.ts +186 -0
  199. package/dist/core/Flow.d.ts.map +1 -0
  200. package/dist/core/Flow.js +546 -0
  201. package/dist/core/Flow.js.map +1 -0
  202. package/dist/core/FlowRouter.d.ts +182 -0
  203. package/dist/core/FlowRouter.d.ts.map +1 -0
  204. package/dist/core/{RoutingEngine.js → FlowRouter.js} +322 -305
  205. package/dist/core/FlowRouter.js.map +1 -0
  206. package/dist/core/PersistenceManager.d.ts +2 -2
  207. package/dist/core/PersistenceManager.d.ts.map +1 -1
  208. package/dist/core/PersistenceManager.js +7 -7
  209. package/dist/core/PersistenceManager.js.map +1 -1
  210. package/dist/core/PromptComposer.d.ts +21 -8
  211. package/dist/core/PromptComposer.d.ts.map +1 -1
  212. package/dist/core/PromptComposer.js +183 -106
  213. package/dist/core/PromptComposer.js.map +1 -1
  214. package/dist/core/PromptSectionCache.d.ts +1 -1
  215. package/dist/core/PromptSectionCache.js +1 -1
  216. package/dist/core/ResponseEngine.d.ts +18 -8
  217. package/dist/core/ResponseEngine.d.ts.map +1 -1
  218. package/dist/core/ResponseEngine.js +38 -36
  219. package/dist/core/ResponseEngine.js.map +1 -1
  220. package/dist/core/ResponseModal.d.ts +73 -56
  221. package/dist/core/ResponseModal.d.ts.map +1 -1
  222. package/dist/core/ResponseModal.js +1193 -1016
  223. package/dist/core/ResponseModal.js.map +1 -1
  224. package/dist/core/ResponsePipeline.d.ts +124 -26
  225. package/dist/core/ResponsePipeline.d.ts.map +1 -1
  226. package/dist/core/ResponsePipeline.js +509 -137
  227. package/dist/core/ResponsePipeline.js.map +1 -1
  228. package/dist/core/SignalEvaluator.d.ts +86 -0
  229. package/dist/core/SignalEvaluator.d.ts.map +1 -0
  230. package/dist/core/SignalEvaluator.js +326 -0
  231. package/dist/core/SignalEvaluator.js.map +1 -0
  232. package/dist/core/SignalProcessor.d.ts +152 -0
  233. package/dist/core/SignalProcessor.d.ts.map +1 -0
  234. package/dist/core/SignalProcessor.js +555 -0
  235. package/dist/core/SignalProcessor.js.map +1 -0
  236. package/dist/core/Step.d.ts +43 -32
  237. package/dist/core/Step.d.ts.map +1 -1
  238. package/dist/core/Step.js +220 -126
  239. package/dist/core/Step.js.map +1 -1
  240. package/dist/core/StreamingToolExecutor.d.ts +2 -2
  241. package/dist/core/StreamingToolExecutor.d.ts.map +1 -1
  242. package/dist/core/StreamingToolExecutor.js.map +1 -1
  243. package/dist/core/ToolManager.d.ts +44 -13
  244. package/dist/core/ToolManager.d.ts.map +1 -1
  245. package/dist/core/ToolManager.js +174 -91
  246. package/dist/core/ToolManager.js.map +1 -1
  247. package/dist/core/createAgent.d.ts +35 -0
  248. package/dist/core/createAgent.d.ts.map +1 -0
  249. package/dist/core/createAgent.js +36 -0
  250. package/dist/core/createAgent.js.map +1 -0
  251. package/dist/core/flow-namespace.d.ts +49 -0
  252. package/dist/core/flow-namespace.d.ts.map +1 -0
  253. package/dist/core/flow-namespace.js +168 -0
  254. package/dist/core/flow-namespace.js.map +1 -0
  255. package/dist/index.d.ts +11 -14
  256. package/dist/index.d.ts.map +1 -1
  257. package/dist/index.js +9 -12
  258. package/dist/index.js.map +1 -1
  259. package/dist/types/agent.d.ts +183 -54
  260. package/dist/types/agent.d.ts.map +1 -1
  261. package/dist/types/agent.js +0 -6
  262. package/dist/types/agent.js.map +1 -1
  263. package/dist/types/ai.d.ts +3 -3
  264. package/dist/types/ai.d.ts.map +1 -1
  265. package/dist/types/errors.d.ts +15 -0
  266. package/dist/types/errors.d.ts.map +1 -0
  267. package/dist/types/errors.js +18 -0
  268. package/dist/types/errors.js.map +1 -0
  269. package/dist/types/flow.d.ts +513 -0
  270. package/dist/types/flow.d.ts.map +1 -0
  271. package/dist/types/flow.js +5 -0
  272. package/dist/types/flow.js.map +1 -0
  273. package/dist/types/index.d.ts +7 -6
  274. package/dist/types/index.d.ts.map +1 -1
  275. package/dist/types/index.js +4 -1
  276. package/dist/types/index.js.map +1 -1
  277. package/dist/types/persistence.d.ts +11 -7
  278. package/dist/types/persistence.d.ts.map +1 -1
  279. package/dist/types/routing.d.ts +1 -1
  280. package/dist/types/routing.d.ts.map +1 -1
  281. package/dist/types/session.d.ts +24 -23
  282. package/dist/types/session.d.ts.map +1 -1
  283. package/dist/types/signals.d.ts +248 -0
  284. package/dist/types/signals.d.ts.map +1 -0
  285. package/dist/types/signals.js +10 -0
  286. package/dist/types/signals.js.map +1 -0
  287. package/dist/types/template.d.ts +2 -8
  288. package/dist/types/template.d.ts.map +1 -1
  289. package/dist/types/tool.d.ts +36 -29
  290. package/dist/types/tool.d.ts.map +1 -1
  291. package/dist/types/tool.js +1 -1
  292. package/dist/types/tool.js.map +1 -1
  293. package/dist/utils/condition.d.ts +7 -1
  294. package/dist/utils/condition.d.ts.map +1 -1
  295. package/dist/utils/condition.js.map +1 -1
  296. package/dist/utils/id.d.ts +13 -5
  297. package/dist/utils/id.d.ts.map +1 -1
  298. package/dist/utils/id.js +22 -9
  299. package/dist/utils/id.js.map +1 -1
  300. package/dist/utils/index.d.ts +2 -2
  301. package/dist/utils/index.d.ts.map +1 -1
  302. package/dist/utils/index.js +2 -2
  303. package/dist/utils/index.js.map +1 -1
  304. package/dist/utils/session.d.ts +44 -5
  305. package/dist/utils/session.d.ts.map +1 -1
  306. package/dist/utils/session.js +193 -37
  307. package/dist/utils/session.js.map +1 -1
  308. package/docs/README.md +15 -202
  309. package/docs/concepts/architecture.md +281 -0
  310. package/docs/concepts/directives.md +400 -0
  311. package/docs/concepts/pipeline.md +399 -0
  312. package/docs/guides/branching.md +263 -0
  313. package/docs/guides/compaction.md +163 -0
  314. package/docs/guides/conditions.md +167 -0
  315. package/docs/guides/error-handling.md +176 -0
  316. package/docs/guides/flow-control.md +409 -0
  317. package/docs/guides/instructions.md +210 -0
  318. package/docs/guides/persistence.md +182 -0
  319. package/docs/guides/streaming.md +137 -0
  320. package/docs/migration/README.md +15 -0
  321. package/docs/migration/route-to-flow.md +560 -0
  322. package/docs/migration/v1-to-v2.md +909 -0
  323. package/docs/reference/adapters.md +481 -0
  324. package/docs/reference/branches.md +241 -0
  325. package/docs/reference/create-agent.md +186 -0
  326. package/docs/reference/directive.md +243 -0
  327. package/docs/reference/errors.md +122 -0
  328. package/docs/reference/flow.md +238 -0
  329. package/docs/reference/instruction.md +177 -0
  330. package/docs/reference/pre-directive.md +131 -0
  331. package/docs/reference/providers.md +227 -0
  332. package/docs/reference/signals.md +356 -0
  333. package/docs/reference/step.md +339 -0
  334. package/docs/reference/tool.md +269 -0
  335. package/docs/start/01-install.md +81 -0
  336. package/docs/start/02-first-agent.md +196 -0
  337. package/docs/start/03-collect-data.md +222 -0
  338. package/docs/start/04-add-tools.md +276 -0
  339. package/docs/start/05-go-to-production.md +216 -0
  340. package/examples/01-quickstart.ts +20 -0
  341. package/examples/02-data-extraction.ts +90 -0
  342. package/examples/03-tools.ts +136 -0
  343. package/examples/04-instructions.ts +100 -0
  344. package/examples/05-branching.ts +140 -0
  345. package/examples/06-flow-control.ts +103 -0
  346. package/examples/07-streaming.ts +69 -0
  347. package/examples/08-persistence.ts +98 -0
  348. package/examples/09-signals.ts +144 -0
  349. package/examples/tsconfig.json +30 -0
  350. package/package.json +2 -1
  351. package/src/adapters/MemoryAdapter.ts +3 -3
  352. package/src/adapters/MongoAdapter.ts +3 -3
  353. package/src/adapters/OpenSearchAdapter.ts +10 -8
  354. package/src/adapters/PostgreSQLAdapter.ts +26 -10
  355. package/src/adapters/PrismaAdapter.ts +6 -6
  356. package/src/adapters/RedisAdapter.ts +3 -3
  357. package/src/adapters/SQLiteAdapter.ts +31 -12
  358. package/src/constants/index.ts +2 -10
  359. package/src/core/Agent.ts +585 -374
  360. package/src/core/AutoChainExecutor.ts +440 -0
  361. package/src/core/BranchEvaluator.ts +167 -0
  362. package/src/core/DirectiveBus.ts +248 -0
  363. package/src/core/DirectiveChainTracker.ts +144 -0
  364. package/src/core/Flow.ts +666 -0
  365. package/src/core/{RoutingEngine.ts → FlowRouter.ts} +385 -365
  366. package/src/core/PersistenceManager.ts +8 -8
  367. package/src/core/PromptComposer.ts +209 -140
  368. package/src/core/PromptSectionCache.ts +1 -1
  369. package/src/core/ResponseEngine.ts +61 -46
  370. package/src/core/ResponseModal.ts +1453 -1240
  371. package/src/core/ResponsePipeline.ts +655 -175
  372. package/src/core/SignalEvaluator.ts +420 -0
  373. package/src/core/SignalProcessor.ts +723 -0
  374. package/src/core/Step.ts +279 -176
  375. package/src/core/StreamingToolExecutor.ts +4 -4
  376. package/src/core/ToolManager.ts +200 -97
  377. package/src/core/createAgent.ts +40 -0
  378. package/src/core/flow-namespace.ts +219 -0
  379. package/src/index.ts +42 -36
  380. package/src/types/agent.ts +182 -53
  381. package/src/types/ai.ts +3 -3
  382. package/src/types/errors.ts +18 -0
  383. package/src/types/flow.ts +590 -0
  384. package/src/types/index.ts +43 -16
  385. package/src/types/persistence.ts +12 -8
  386. package/src/types/routing.ts +1 -1
  387. package/src/types/session.ts +26 -23
  388. package/src/types/signals.ts +321 -0
  389. package/src/types/template.ts +3 -11
  390. package/src/types/tool.ts +50 -42
  391. package/src/utils/condition.ts +13 -4
  392. package/src/utils/id.ts +27 -9
  393. package/src/utils/index.ts +6 -2
  394. package/src/utils/session.ts +238 -42
  395. package/dist/cjs/core/BatchExecutor.d.ts +0 -359
  396. package/dist/cjs/core/BatchExecutor.d.ts.map +0 -1
  397. package/dist/cjs/core/BatchExecutor.js +0 -861
  398. package/dist/cjs/core/BatchExecutor.js.map +0 -1
  399. package/dist/cjs/core/BatchPromptBuilder.d.ts +0 -89
  400. package/dist/cjs/core/BatchPromptBuilder.d.ts.map +0 -1
  401. package/dist/cjs/core/BatchPromptBuilder.js +0 -223
  402. package/dist/cjs/core/BatchPromptBuilder.js.map +0 -1
  403. package/dist/cjs/core/Route.d.ts +0 -180
  404. package/dist/cjs/core/Route.d.ts.map +0 -1
  405. package/dist/cjs/core/Route.js +0 -542
  406. package/dist/cjs/core/Route.js.map +0 -1
  407. package/dist/cjs/core/RoutingEngine.d.ts +0 -185
  408. package/dist/cjs/core/RoutingEngine.d.ts.map +0 -1
  409. package/dist/cjs/core/RoutingEngine.js.map +0 -1
  410. package/dist/cjs/types/route.d.ts +0 -336
  411. package/dist/cjs/types/route.d.ts.map +0 -1
  412. package/dist/cjs/types/route.js.map +0 -1
  413. package/dist/core/BatchExecutor.d.ts +0 -359
  414. package/dist/core/BatchExecutor.d.ts.map +0 -1
  415. package/dist/core/BatchExecutor.js +0 -856
  416. package/dist/core/BatchExecutor.js.map +0 -1
  417. package/dist/core/BatchPromptBuilder.d.ts +0 -89
  418. package/dist/core/BatchPromptBuilder.d.ts.map +0 -1
  419. package/dist/core/BatchPromptBuilder.js +0 -219
  420. package/dist/core/BatchPromptBuilder.js.map +0 -1
  421. package/dist/core/Route.d.ts +0 -180
  422. package/dist/core/Route.d.ts.map +0 -1
  423. package/dist/core/Route.js +0 -538
  424. package/dist/core/Route.js.map +0 -1
  425. package/dist/core/RoutingEngine.d.ts +0 -185
  426. package/dist/core/RoutingEngine.d.ts.map +0 -1
  427. package/dist/core/RoutingEngine.js.map +0 -1
  428. package/dist/types/route.d.ts +0 -336
  429. package/dist/types/route.d.ts.map +0 -1
  430. package/dist/types/route.js +0 -5
  431. package/dist/types/route.js.map +0 -1
  432. package/docs/CONTRIBUTING.md +0 -521
  433. package/docs/api/README.md +0 -3299
  434. package/docs/api/overview.md +0 -1410
  435. package/docs/architecture/data-extraction-flow.md +0 -360
  436. package/docs/architecture/multi-step-execution.md +0 -277
  437. package/docs/core/agent/README.md +0 -938
  438. package/docs/core/agent/context-management.md +0 -796
  439. package/docs/core/agent/rules-and-prohibitions.md +0 -113
  440. package/docs/core/agent/session-management.md +0 -693
  441. package/docs/core/ai-integration/prompt-composition.md +0 -355
  442. package/docs/core/ai-integration/providers.md +0 -515
  443. package/docs/core/ai-integration/response-processing.md +0 -433
  444. package/docs/core/conversation-flows/data-collection.md +0 -772
  445. package/docs/core/conversation-flows/route-dsl.md +0 -509
  446. package/docs/core/conversation-flows/routes.md +0 -249
  447. package/docs/core/conversation-flows/step-transitions.md +0 -731
  448. package/docs/core/conversation-flows/steps.md +0 -268
  449. package/docs/core/error-handling.md +0 -830
  450. package/docs/core/persistence/adapters.md +0 -255
  451. package/docs/core/persistence/session-storage.md +0 -656
  452. package/docs/core/routing/intelligent-routing.md +0 -470
  453. package/docs/core/tools/enhanced-tool.md +0 -186
  454. package/docs/core/tools/streaming-execution.md +0 -161
  455. package/docs/core/tools/tool-definition.md +0 -970
  456. package/docs/core/tools/tool-scoping.md +0 -819
  457. package/docs/guides/advanced-patterns/publishing.md +0 -186
  458. package/docs/guides/context-compaction.md +0 -96
  459. package/docs/guides/error-handling-patterns.md +0 -578
  460. package/docs/guides/getting-started/README.md +0 -795
  461. package/docs/guides/migration/README.md +0 -101
  462. package/docs/guides/migration/flexible-routing-conditions.md +0 -375
  463. package/docs/guides/migration/multi-step-execution.md +0 -393
  464. package/docs/guides/migration/response-modal-refactor.md +0 -518
  465. package/docs/guides/prompt-optimization.md +0 -164
  466. package/examples/advanced-patterns/context-compaction.ts +0 -223
  467. package/examples/advanced-patterns/knowledge-based-agent.ts +0 -735
  468. package/examples/advanced-patterns/persistent-onboarding.ts +0 -728
  469. package/examples/advanced-patterns/route-lifecycle-hooks.ts +0 -556
  470. package/examples/advanced-patterns/streaming-responses.ts +0 -656
  471. package/examples/ai-providers/anthropic-integration.ts +0 -388
  472. package/examples/ai-providers/openai-integration.ts +0 -228
  473. package/examples/condition-patterns/function-only-conditions.ts +0 -365
  474. package/examples/condition-patterns/mixed-array-conditions.ts +0 -477
  475. package/examples/condition-patterns/route-skipif-patterns.ts +0 -468
  476. package/examples/condition-patterns/step-skipif-patterns.ts +0 -0
  477. package/examples/condition-patterns/string-only-conditions.ts +0 -296
  478. package/examples/conversation-flows/completion-transitions.ts +0 -318
  479. package/examples/core-concepts/basic-agent.ts +0 -503
  480. package/examples/core-concepts/modern-streaming-api.ts +0 -309
  481. package/examples/core-concepts/schema-driven-extraction.ts +0 -332
  482. package/examples/core-concepts/session-management.ts +0 -494
  483. package/examples/integrations/database-integration.ts +0 -631
  484. package/examples/integrations/healthcare-integration.ts +0 -595
  485. package/examples/integrations/search-integration.ts +0 -530
  486. package/examples/integrations/server-session-management.ts +0 -307
  487. package/examples/persistence/custom-adapter.ts +0 -526
  488. package/examples/persistence/database-persistence.ts +0 -583
  489. package/examples/persistence/memory-sessions.ts +0 -495
  490. package/examples/persistence/prisma-schema.example.prisma +0 -74
  491. package/examples/persistence/redis-persistence.ts +0 -488
  492. package/examples/tools/basic-tools.ts +0 -765
  493. package/examples/tools/data-enrichment-tools.ts +0 -593
  494. package/examples/tools/enhanced-tool-metadata.ts +0 -268
  495. package/examples/tools/streaming-tool-execution.ts +0 -283
  496. package/src/core/BatchExecutor.ts +0 -1187
  497. package/src/core/BatchPromptBuilder.ts +0 -299
  498. package/src/core/Route.ts +0 -678
  499. package/src/types/route.ts +0 -392
@@ -0,0 +1,163 @@
1
+ ---
2
+ title: "Compaction"
3
+ description: "Keep prompts within token limits across long sessions by layering tool-result budgeting, micro-compaction, and LLM summarization in cost order."
4
+ type: guide
5
+ order: 8
6
+ ---
7
+
8
+ # Compaction
9
+
10
+ > **Where this is introduced:** [Errors](./error-handling.md)
11
+
12
+ Long-running sessions accumulate history. Tool calls return verbose
13
+ JSON, turns pile up, and at some point the next provider call runs
14
+ out of token budget. Compaction is the framework's answer: a layered
15
+ strategy that trims and summarizes `session.history` before each turn
16
+ so the prompt fits without dropping anything load-bearing. Layers run
17
+ in cost order — character-level truncation first, an LLM summarization
18
+ call only when nothing cheaper closes the gap.
19
+
20
+ This guide is task-shaped: enable compaction, choose a budget, and
21
+ understand which layer fires when.
22
+
23
+ ## Enable compaction
24
+
25
+ Compaction is opt-in. Set `AgentOptions.compaction` and the agent
26
+ validates the config at construction time, then runs the engine on
27
+ every `respond` / `respondStream` call before the prompt is composed.
28
+
29
+ ```typescript
30
+ import { createAgent, GeminiProvider } from "@falai/agent";
31
+
32
+ const agent = createAgent({
33
+ name: "Concierge",
34
+ provider: new GeminiProvider({ apiKey: process.env.GEMINI_API_KEY! }),
35
+ schema: { /* ... */ },
36
+ flows: [/* ... */],
37
+
38
+ compaction: {
39
+ maxTokens: 32_000, // total token budget for the prompt
40
+ compactionThreshold: 0.8, // fire when history hits 80% of maxTokens (default)
41
+ preserveRecentCount: 4, // never touch the last 4 history items (default)
42
+ maxToolResultChars: 5_000, // global cap per tool message (default)
43
+ // enabled: true, // default true when `compaction` is provided
44
+ },
45
+ });
46
+ ```
47
+
48
+ The four knobs map onto the
49
+ [`AgentCompactionConfig`](../reference/create-agent.md) interface.
50
+ `maxTokens` is the only required field; the rest fall back to the
51
+ defaults shown above. The agent calls `validateOptions` synchronously
52
+ at construction, so misvalued thresholds (`compactionThreshold` outside
53
+ `[0.5, 0.95]`, `preserveRecentCount < 2`, `maxToolResultChars <= 0`)
54
+ throw immediately rather than silently no-oping at runtime.
55
+
56
+ A second knob lives on every `Tool`: `maxResultSizeChars`. That value
57
+ is enforced by the tool executor the moment a tool returns, before the
58
+ result enters history at all. It and the agent-level `maxToolResultChars`
59
+ work together — per-tool first, global later.
60
+
61
+ ## How a turn checks the budget
62
+
63
+ Before each turn, the session manager calls
64
+ `CompactionEngine.checkAndCompact(session.history, options)`. The
65
+ engine estimates the current token count using a character-based
66
+ heuristic (~4 characters per token), compares against
67
+ `maxTokens * compactionThreshold`, and applies the cheapest layer that
68
+ brings history below the threshold. If even the most expensive layer
69
+ cannot, an aggressive truncation fallback removes the oldest items
70
+ until the budget fits.
71
+
72
+ `preserveRecentCount` is honored by every layer. The trailing N items
73
+ of `session.history` are never modified, summarized, or removed —
74
+ recent turns are the one piece of context the engine refuses to spend.
75
+
76
+ ## Layer 1 — tool-result budgeting
77
+
78
+ `tool_result_budget` is the cheapest layer. It walks history, finds
79
+ items with `role: "tool"`, and truncates any whose stringified content
80
+ exceeds `maxToolResultChars`. Truncated items get a deterministic
81
+ notice appended:
82
+
83
+ ```text
84
+ [Truncated: 12834 chars total, showing first 5000]
85
+ ```
86
+
87
+ Character-level and synchronous — no LLM call, no network. It fires
88
+ whenever history crosses the threshold and at least one tool message
89
+ is oversized. For agents that orchestrate verbose APIs (search, SQL,
90
+ web fetches) this layer alone usually keeps the prompt in budget.
91
+
92
+ The per-tool counterpart is `Tool.maxResultSizeChars`. Set it on
93
+ high-volume tools to truncate at execution time, before the result
94
+ ever lands in history. Combine the two: a tight per-tool cap on a
95
+ known-chatty tool, plus a global ceiling at the agent level.
96
+
97
+ ## Layer 2 — micro-compaction
98
+
99
+ If `tool_result_budget` is not enough, `micro_compact` runs over the
100
+ already-budgeted history. It compresses verbose tool outputs inline
101
+ by collapsing whitespace runs to a single space and trimming the
102
+ edges. Tool results are the only target — user, assistant, and system
103
+ messages pass through unchanged.
104
+
105
+ Still LLM-free and deterministic. Most effective on tool results that
106
+ contain pretty-printed JSON or multiline text where formatting is
107
+ whitespace-heavy. The recent-N tail (`preserveRecentCount`) is
108
+ preserved verbatim during this pass; the cutoff is `history.length -
109
+ preserveRecentCount`, and only items before that cutoff are
110
+ compressed.
111
+
112
+ ## Layer 3 — LLM summarization
113
+
114
+ When neither character-level layer brings the prompt under threshold,
115
+ `auto_compact` dispatches a single `provider.generateMessage` call
116
+ asking the agent's own LLM to summarize the older portion. The result
117
+ becomes one synthetic system message:
118
+
119
+ ```text
120
+ [Conversation Summary]
121
+ <summary text from the provider>
122
+ ```
123
+
124
+ That synthetic item replaces every history item before the
125
+ `preserveRecentCount` tail. The recent tail is appended unchanged. If
126
+ the provider call fails — quota, network, any caught exception — the
127
+ engine falls back to `aggressiveTruncate`: walk older messages newest
128
+ to oldest, keep as many as fit under `maxTokens * compactionThreshold`,
129
+ drop the rest. The strategy field on the result still reads
130
+ `"auto_compact"` so callers can see that summarization was attempted.
131
+
132
+ This layer costs a real provider round-trip. It only fires when
133
+ character-level layers cannot close the gap — in practice, sessions
134
+ with hundreds of long turns or tools that return narrative prose
135
+ rather than structured data.
136
+
137
+ ## When each layer fires
138
+
139
+ The `compactionThreshold` ratio is the gate for all three layers. Below
140
+ threshold, `checkAndCompact` returns `strategy: "none"` and history
141
+ passes through untouched. At or above threshold, the engine attempts
142
+ each layer in order and stops as soon as the result drops below the
143
+ threshold:
144
+
145
+ | Estimated tokens | Strategy that fires |
146
+ |------------------|---------------------|
147
+ | `< maxTokens * compactionThreshold` | `none` |
148
+ | `≥ threshold`, oversized tool messages exist | `tool_result_budget` |
149
+ | `≥ threshold` after budgeting | `micro_compact` |
150
+ | `≥ threshold` after micro-compaction | `auto_compact` (LLM call) |
151
+ | LLM call failed | `auto_compact` (truncation fallback) |
152
+
153
+ The result's `messagesCompacted` count and optional `summary` field
154
+ are logged at `info` level so production logs show which layer fired
155
+ on which turn.
156
+
157
+ A practical defaults sketch: set `maxTokens` to ~80% of the model's
158
+ context window, leave `compactionThreshold` at the 0.8 default, and
159
+ put a tight per-tool `maxResultSizeChars` on any tool that talks to
160
+ a search API or a database. Pick the budget, set the caps, let the
161
+ layers absorb the noise.
162
+
163
+ **Next:** [Architecture](../concepts/architecture.md)
@@ -0,0 +1,167 @@
1
+ ---
2
+ title: "When and if"
3
+ description: "Pick between AI-evaluated `when` strings and code-evaluated `if` predicates, and combine them to save tokens."
4
+ type: guide
5
+ order: 1
6
+ ---
7
+
8
+ # When and if
9
+
10
+ Conditions decide whether a flow activates, a step runs, an instruction renders, or a branch fires. v2 splits them into two distinct fields with different evaluators:
11
+
12
+ - `when` — strings the LLM evaluates against intent and the conversation. Costs tokens.
13
+ - `if` — TypeScript predicates the engine evaluates locally. Free.
14
+
15
+ The split is the same everywhere: `Flow`, `Step`, `Instruction`, and `BranchEntry` all expose `when?` and `if?` with identical semantics. This guide shows how to pick between them, how arrays combine, and what happens when both are set. If you are migrating from v1, the [v1 → v2 migration guide](../migration/v1-to-v2.md) covers the renamed condition fields.
16
+
17
+ ## Pick the right field
18
+
19
+ Reach for `if` first. It's free, deterministic, and reads clearly in code review.
20
+
21
+ | Question to answer | Use |
22
+ | --------------------------------------------------------------- | -------- |
23
+ | Is this user authenticated? Is `data.tier === 'pro'`? | `if` |
24
+ | Is the feature flag on? Is the order older than 90 days? | `if` |
25
+ | Did the user ask about pricing? Are they expressing frustration? | `when` |
26
+ | Is the user describing a refund scenario in their own words? | `when` |
27
+
28
+ If the answer lives in `data`, `context`, or `session`, it's `if`. If the answer requires reading the user's intent from natural language, it's `when`.
29
+
30
+ ## `when` — AI strings
31
+
32
+ `when` accepts a string or an array of strings. Functions are rejected at construction time with `FlowConfigurationError`.
33
+
34
+ ```typescript
35
+ {
36
+ title: "Refund",
37
+ when: "the user is requesting a refund",
38
+ }
39
+ ```
40
+
41
+ Multiple strings combine with **AND** semantics — every clause must pass for the condition to match.
42
+
43
+ ```typescript
44
+ {
45
+ title: "Premium Refund",
46
+ when: [
47
+ "the user is requesting a refund",
48
+ "the user is asking about an enterprise plan",
49
+ ],
50
+ }
51
+ ```
52
+
53
+ The strings are sent to the LLM as part of the routing or activation prompt. Keep them short, intent-shaped, and free of code-style boolean expressions — `"the user wants to cancel"` lands; `"data.cancelRequested === true"` does not.
54
+
55
+ ## `if` — code predicates
56
+
57
+ `if` accepts a function or an array of functions. Each predicate receives a `TemplateContext`-shaped argument (`{ context, data, session, history, helpers }`) and returns `boolean | Promise<boolean>`.
58
+
59
+ ```typescript
60
+ {
61
+ title: "Enterprise",
62
+ if: ({ context }) => context.tier === "enterprise",
63
+ }
64
+ ```
65
+
66
+ Arrays combine with **AND** semantics — every predicate must return truthy.
67
+
68
+ ```typescript
69
+ {
70
+ if: [
71
+ ({ context }) => context.authenticated,
72
+ ({ data }) => (data.cartTotal ?? 0) > 100,
73
+ ],
74
+ }
75
+ ```
76
+
77
+ Predicates that throw or reject are caught, logged, and treated as `false` for that evaluation. They never corrupt the session — the worst case is the condition fails to match.
78
+
79
+ ### What's in the predicate context
80
+
81
+ Predicates receive a context object with the same shape used everywhere templates and conditions evaluate. The fields you'll reach for most:
82
+
83
+ | Field | Type | Notes |
84
+ | ---------- | ------------------------ | ---------------------------------------------------------------- |
85
+ | `data` | `Partial<TData>` | Collected schema fields. Null-check anything not in `requires`. |
86
+ | `context` | `TContext` | Agent-level ambient context (user, env, services). |
87
+ | `session` | `SessionState<TData>` | Current flow id, current step id, full history. |
88
+ | `history` | `Event[]` | Read-only conversation history. |
89
+
90
+ Predicates can be `async`. Awaiting a database lookup or feature-flag service is supported, but remember: every predicate runs every time its host primitive is evaluated. Keep them cheap, or memoize the work in a hook upstream.
91
+
92
+ ```typescript
93
+ {
94
+ if: async ({ context, data }) =>
95
+ await context.flags.isEnabled("v2_pricing", data.userId),
96
+ }
97
+ ```
98
+
99
+ ## When both are set
100
+
101
+ Setting both `when` and `if` on the same primitive runs `if` **first**, free. `when` is only sent to the LLM when every `if` predicate passes. The order is deliberate: predicates short-circuit the LLM call when the answer is already disqualified.
102
+
103
+ ```typescript
104
+ {
105
+ title: "US Pricing",
106
+ if: ({ context }) => context.country === "US" && context.flags.usPricing,
107
+ when: "the user is asking about pricing",
108
+ }
109
+ ```
110
+
111
+ In the snippet above, non-US users skip the AI evaluation entirely. The `when` string costs tokens only when the predicate already says "this user is in scope, ask the AI whether they're asking about pricing."
112
+
113
+ This pattern is the recommended shape any time a condition has both a cheap precondition and an intent classification. Lead with `if` to gate. Use `when` to interpret.
114
+
115
+ ## Where the split lives
116
+
117
+ The same `when` / `if` shape attaches to four primitives. Semantics are identical in each location:
118
+
119
+ | Primitive | Field path | What it gates |
120
+ | --------------- | ----------------------- | -------------------------------------------------- |
121
+ | Flow | `FlowOptions.when/if` | Whether the router selects this flow this turn |
122
+ | Step | `StepOptions.when/if` | Whether the step is reachable in the current flow |
123
+ | Instruction | `Instruction.when/if` | Whether the instruction renders into the prompt |
124
+ | BranchEntry | `BranchEntry.when/if` | Whether this branch entry matches inside `step.branches` |
125
+
126
+ ```typescript
127
+ // Flow scope — gate flow selection
128
+ { title: "Refund", when: "user wants a refund", if: ({ context }) => context.authenticated }
129
+
130
+ // Step scope — gate step reachability
131
+ { id: "verify_payment", when: "user is confirming the order", if: ({ data }) => !!data.cardToken }
132
+
133
+ // Instruction scope — render only when relevant
134
+ { kind: "should", when: "user mentions a discount code", prompt: "Validate the code before applying it." }
135
+
136
+ // Branch scope — pick a successor
137
+ branches: [
138
+ { if: ({ data }) => data.tier === "enterprise", when: "user wants pricing", then: "enterprise_pricing" },
139
+ { then: "default_pricing" },
140
+ ]
141
+ ```
142
+
143
+ ## `step.skip` is the OR companion
144
+
145
+ One adjacent field rounds out the picture. `step.skip` is **function-only** with **OR** semantics — when any predicate returns truthy, the step is bypassed. Use it for "skip when this field already exists" cases:
146
+
147
+ ```typescript
148
+ {
149
+ id: "ask_email",
150
+ collect: ["email"],
151
+ skip: ({ data }) => !!data.email,
152
+ }
153
+ ```
154
+
155
+ `skip` does not accept strings. There is no AI counterpart — skipping is a code decision by design.
156
+
157
+ ## Quick reference
158
+
159
+ A short checklist before shipping a condition:
160
+
161
+ - Does it read a field, flag, or context value? Use `if`.
162
+ - Does it interpret natural language? Use `when`.
163
+ - Multiple clauses that all must pass? Drop them in an array — both fields AND.
164
+ - Need to skip when a value is already collected? `step.skip` (OR semantics).
165
+ - Both fields set? `if` runs first, free; `when` only fires if `if` passes.
166
+
167
+ **Next:** [Branching](./branching.md)
@@ -0,0 +1,176 @@
1
+ ---
2
+ title: "Errors"
3
+ description: "Catch the typed error classes by class, narrow them with instanceof, and recover with the right pattern for each failure mode."
4
+ type: guide
5
+ order: 7
6
+ ---
7
+
8
+ # Errors
9
+
10
+ `@falai/agent` throws typed `Error` subclasses for every failure mode the framework owns. Catching `Error` is fine for telemetry, but recovering well needs class-level narrowing — a `DataValidationError` wants a re-prompt, a `ToolExecutionError` wants a soft message and maybe a redirect, a `FlowConfigurationError` wants to crash the build. This page is the recipe for each. The full surface lives in the [errors reference](../reference/errors.md).
11
+
12
+ ## The format contract
13
+
14
+ Every thrown message follows the same shape:
15
+
16
+ ```text
17
+ [<ErrorClass>] <what>: <why>. <how to fix>.
18
+ ```
19
+
20
+ The bracketed prefix mirrors the class name. The colon separates `<what>` from `<why>`. The trailing sentence is `<how to fix>`. The contract is uniform across the five classes the framework throws — `FlowConfigurationError`, `DataValidationError`, `ToolExecutionError`, `ResponseGenerationError`, and `NotImplementedError` — so log lines and `try/catch` blocks parse the same way regardless of which class fired.
21
+
22
+ The format applies to framework-thrown errors. If you write a custom tool or hook that throws, follow the same shape so downstream handlers stay uniform.
23
+
24
+ ## The five classes
25
+
26
+ | Class | Thrown when | Recover by |
27
+ |-------|-------------|------------|
28
+ | `FlowConfigurationError` | Misconfigured agent: duplicate ids, unknown `collect` keys, malformed `Directive`, branch targets that don't resolve, auto-step cycles, function on `when`. | Don't. Surface in CI. |
29
+ | `DataValidationError` | A user message produces a value that violates the declared `schema`. | Re-prompt the user for the offending fields. |
30
+ | `ToolExecutionError` | A tool handler throws, all retries fail, or `validateInput` cannot correct invalid args. | User-friendly message, optional retry, optional `agent.dispatch` to a recovery flow. |
31
+ | `ResponseGenerationError` | The provider call fails or the response cannot be parsed. | Backoff retry, fall back to a different provider, or surface a soft failure. |
32
+ | `NotImplementedError` | A reserved option is set to a value this version does not support (e.g. `routerMode: 'embedding'` in v2.0). | Use a supported value. Same posture as `FlowConfigurationError`. |
33
+
34
+ `FlowConfigurationError`, `ToolExecutionError`, and `NotImplementedError` are exported from `@falai/agent` and matchable with `instanceof`. `DataValidationError` and `ResponseGenerationError` are internal — match them by `error.name`.
35
+
36
+ ## Pattern 1: try/catch + instanceof narrowing
37
+
38
+ Wrap every `agent.respond` and `agent.respondStream` call site. Narrow by class, return the right user-facing string per branch, rethrow what cannot be recovered.
39
+
40
+ ```typescript
41
+ import {
42
+ FlowConfigurationError,
43
+ ToolExecutionError,
44
+ NotImplementedError,
45
+ } from "@falai/agent";
46
+
47
+ try {
48
+ const response = await agent.respond({ history, session });
49
+ return response.message;
50
+ } catch (err) {
51
+ if (err instanceof FlowConfigurationError) throw err; // bug — bubble up
52
+ if (err instanceof NotImplementedError) throw err; // config bug — bubble up
53
+ if (err instanceof ToolExecutionError) {
54
+ log.warn({ toolId: err.toolId, cause: err.cause }, err.message);
55
+ return "Sorry — that action failed. Try again in a moment.";
56
+ }
57
+ if (err instanceof Error && err.name === "DataValidationError") {
58
+ return "I need a couple of details cleared up — let's try that again.";
59
+ }
60
+ if (err instanceof Error && err.name === "ResponseGenerationError") {
61
+ return "I'm having trouble reaching the model. Please retry.";
62
+ }
63
+ throw err;
64
+ }
65
+ ```
66
+
67
+ The two unrecoverable classes — `FlowConfigurationError` and `NotImplementedError` — get rethrown so the process crashes loudly. The other three return a graceful message. Anything unexpected falls through to the outer rethrow.
68
+
69
+ ## Pattern 2: DataValidationError → re-prompt
70
+
71
+ A `DataValidationError` carries an `errors: ValidationError[]` array naming the offending fields. Use it to ask the user a targeted clarifying question instead of a generic one.
72
+
73
+ ```typescript
74
+ } catch (err) {
75
+ if (err instanceof Error && err.name === "DataValidationError") {
76
+ const fields = (err as { errors: { path: string; message: string }[] }).errors
77
+ .map((e) => `${e.path} (${e.message})`)
78
+ .join(", ");
79
+ return `I couldn't read these from your message: ${fields}. Mind clarifying?`;
80
+ }
81
+ // ...
82
+ }
83
+ ```
84
+
85
+ The framework does not retry by itself — the next user turn is the retry. Keep `session` alive between turns so the partial collection survives.
86
+
87
+ ## Pattern 3: ToolExecutionError → message, retry, or dispatch
88
+
89
+ Tool failures have three shapes. Pick by what the failing tool was doing.
90
+
91
+ **Soft failure — speak and continue.** A read-only tool that timed out: tell the user, let the conversation move on.
92
+
93
+ ```typescript
94
+ if (err instanceof ToolExecutionError) {
95
+ log.warn({ toolId: err.toolId }, err.message);
96
+ return "I couldn't fetch that just now. Want to try again?";
97
+ }
98
+ ```
99
+
100
+ **Optional retry.** Wrap the `respond` call in a small retry loop for transient errors.
101
+
102
+ ```typescript
103
+ for (let attempt = 0; attempt < 2; attempt++) {
104
+ try {
105
+ return (await agent.respond({ history, session })).message;
106
+ } catch (err) {
107
+ if (err instanceof ToolExecutionError && attempt === 0) {
108
+ await new Promise((r) => setTimeout(r, 250));
109
+ continue;
110
+ }
111
+ throw err;
112
+ }
113
+ }
114
+ ```
115
+
116
+ **Recovery flow.** Hard failures — a payment tool that hit a permanent denial — should redirect into a recovery flow rather than echo the error. Dispatch a directive against the session so the *next* turn enters the recovery flow.
117
+
118
+ ```typescript
119
+ if (err instanceof ToolExecutionError && err.toolId === "charge_card") {
120
+ await agent.dispatch(session, { goTo: "PaymentRecovery" });
121
+ return "I hit a snag with that payment. Let me walk you through it.";
122
+ }
123
+ ```
124
+
125
+ The dispatched [`Directive`](../reference/directive.md) lands in `session.pendingDirective` and is consumed at the start of the next turn.
126
+
127
+ ## Pattern 4: ResponseGenerationError → backoff or fallback provider
128
+
129
+ Provider errors are usually transient. Retry with backoff first; fall back to a second provider only if the primary keeps failing.
130
+
131
+ ```typescript
132
+ async function respondWithFallback(history: HistoryItem[], session: Session) {
133
+ for (let attempt = 0; attempt < 3; attempt++) {
134
+ try {
135
+ return await primaryAgent.respond({ history, session });
136
+ } catch (err) {
137
+ if (err instanceof Error && err.name === "ResponseGenerationError") {
138
+ await new Promise((r) => setTimeout(r, 200 * 2 ** attempt));
139
+ continue;
140
+ }
141
+ throw err;
142
+ }
143
+ }
144
+ return fallbackAgent.respond({ history, session });
145
+ }
146
+ ```
147
+
148
+ Both agents share the same `flows`, `tools`, and `schema` — only the `provider` differs. The session is provider-agnostic, so the fallback picks up exactly where the primary left off.
149
+
150
+ ## Pattern 5: FlowConfigurationError → don't catch in production
151
+
152
+ `FlowConfigurationError` is a *bug*, not a runtime condition. It fires when the agent definition is malformed: a step references a flow id that doesn't exist, two steps share a `collect` key, a branch target points nowhere, an auto-step chain loops. The right place to catch it is the test runner and CI — never the request path.
153
+
154
+ Smoke-test agent construction in CI so misconfiguration crashes the build rather than the first user request:
155
+
156
+ ```typescript
157
+ import { describe, expect, it } from "bun:test";
158
+ import { FlowConfigurationError } from "@falai/agent";
159
+ import { buildAgent } from "../src/agent";
160
+
161
+ describe("agent construction", () => {
162
+ it("builds without configuration errors", () => {
163
+ expect(() => buildAgent()).not.toThrow(FlowConfigurationError);
164
+ });
165
+ });
166
+ ```
167
+
168
+ In the request handler, let it bubble all the way up. A 500 plus a loud log is the correct outcome — the next deploy is the fix.
169
+
170
+ ```typescript
171
+ if (err instanceof FlowConfigurationError) throw err;
172
+ ```
173
+
174
+ `NotImplementedError` follows the same posture: it means a reserved option was set to a value this version doesn't support. Read the message, fix the config, ship the fix. Don't catch it.
175
+
176
+ **Next:** [Compaction](./compaction.md)