@falai/agent 1.2.7 → 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 (508) 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 +1196 -1015
  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 +524 -134
  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/GeminiProvider.d.ts +3 -3
  126. package/dist/cjs/providers/GeminiProvider.d.ts.map +1 -1
  127. package/dist/cjs/providers/GeminiProvider.js +16 -14
  128. package/dist/cjs/providers/GeminiProvider.js.map +1 -1
  129. package/dist/cjs/types/agent.d.ts +183 -54
  130. package/dist/cjs/types/agent.d.ts.map +1 -1
  131. package/dist/cjs/types/agent.js +0 -6
  132. package/dist/cjs/types/agent.js.map +1 -1
  133. package/dist/cjs/types/ai.d.ts +3 -3
  134. package/dist/cjs/types/ai.d.ts.map +1 -1
  135. package/dist/cjs/types/errors.d.ts +15 -0
  136. package/dist/cjs/types/errors.d.ts.map +1 -0
  137. package/dist/cjs/types/errors.js +22 -0
  138. package/dist/cjs/types/errors.js.map +1 -0
  139. package/dist/cjs/types/flow.d.ts +513 -0
  140. package/dist/cjs/types/flow.d.ts.map +1 -0
  141. package/dist/cjs/types/{route.js → flow.js} +2 -2
  142. package/dist/cjs/types/flow.js.map +1 -0
  143. package/dist/cjs/types/index.d.ts +7 -6
  144. package/dist/cjs/types/index.d.ts.map +1 -1
  145. package/dist/cjs/types/index.js +6 -2
  146. package/dist/cjs/types/index.js.map +1 -1
  147. package/dist/cjs/types/persistence.d.ts +11 -7
  148. package/dist/cjs/types/persistence.d.ts.map +1 -1
  149. package/dist/cjs/types/routing.d.ts +1 -1
  150. package/dist/cjs/types/routing.d.ts.map +1 -1
  151. package/dist/cjs/types/session.d.ts +24 -23
  152. package/dist/cjs/types/session.d.ts.map +1 -1
  153. package/dist/cjs/types/signals.d.ts +248 -0
  154. package/dist/cjs/types/signals.d.ts.map +1 -0
  155. package/dist/cjs/types/signals.js +11 -0
  156. package/dist/cjs/types/signals.js.map +1 -0
  157. package/dist/cjs/types/template.d.ts +2 -8
  158. package/dist/cjs/types/template.d.ts.map +1 -1
  159. package/dist/cjs/types/tool.d.ts +36 -29
  160. package/dist/cjs/types/tool.d.ts.map +1 -1
  161. package/dist/cjs/types/tool.js +1 -1
  162. package/dist/cjs/types/tool.js.map +1 -1
  163. package/dist/cjs/utils/condition.d.ts +7 -1
  164. package/dist/cjs/utils/condition.d.ts.map +1 -1
  165. package/dist/cjs/utils/condition.js.map +1 -1
  166. package/dist/cjs/utils/id.d.ts +13 -5
  167. package/dist/cjs/utils/id.d.ts.map +1 -1
  168. package/dist/cjs/utils/id.js +24 -10
  169. package/dist/cjs/utils/id.js.map +1 -1
  170. package/dist/cjs/utils/index.d.ts +2 -2
  171. package/dist/cjs/utils/index.d.ts.map +1 -1
  172. package/dist/cjs/utils/index.js +7 -3
  173. package/dist/cjs/utils/index.js.map +1 -1
  174. package/dist/cjs/utils/session.d.ts +44 -5
  175. package/dist/cjs/utils/session.d.ts.map +1 -1
  176. package/dist/cjs/utils/session.js +197 -38
  177. package/dist/cjs/utils/session.js.map +1 -1
  178. package/dist/constants/index.d.ts +0 -9
  179. package/dist/constants/index.d.ts.map +1 -1
  180. package/dist/constants/index.js +3 -9
  181. package/dist/constants/index.js.map +1 -1
  182. package/dist/core/Agent.d.ts +119 -153
  183. package/dist/core/Agent.d.ts.map +1 -1
  184. package/dist/core/Agent.js +472 -325
  185. package/dist/core/Agent.js.map +1 -1
  186. package/dist/core/AutoChainExecutor.d.ts +107 -0
  187. package/dist/core/AutoChainExecutor.d.ts.map +1 -0
  188. package/dist/core/AutoChainExecutor.js +293 -0
  189. package/dist/core/AutoChainExecutor.js.map +1 -0
  190. package/dist/core/BranchEvaluator.d.ts +54 -0
  191. package/dist/core/BranchEvaluator.d.ts.map +1 -0
  192. package/dist/core/BranchEvaluator.js +126 -0
  193. package/dist/core/BranchEvaluator.js.map +1 -0
  194. package/dist/core/DirectiveBus.d.ts +88 -0
  195. package/dist/core/DirectiveBus.d.ts.map +1 -0
  196. package/dist/core/DirectiveBus.js +192 -0
  197. package/dist/core/DirectiveBus.js.map +1 -0
  198. package/dist/core/DirectiveChainTracker.d.ts +49 -0
  199. package/dist/core/DirectiveChainTracker.d.ts.map +1 -0
  200. package/dist/core/DirectiveChainTracker.js +117 -0
  201. package/dist/core/DirectiveChainTracker.js.map +1 -0
  202. package/dist/core/Flow.d.ts +186 -0
  203. package/dist/core/Flow.d.ts.map +1 -0
  204. package/dist/core/Flow.js +546 -0
  205. package/dist/core/Flow.js.map +1 -0
  206. package/dist/core/FlowRouter.d.ts +182 -0
  207. package/dist/core/FlowRouter.d.ts.map +1 -0
  208. package/dist/core/{RoutingEngine.js → FlowRouter.js} +322 -305
  209. package/dist/core/FlowRouter.js.map +1 -0
  210. package/dist/core/PersistenceManager.d.ts +2 -2
  211. package/dist/core/PersistenceManager.d.ts.map +1 -1
  212. package/dist/core/PersistenceManager.js +7 -7
  213. package/dist/core/PersistenceManager.js.map +1 -1
  214. package/dist/core/PromptComposer.d.ts +21 -8
  215. package/dist/core/PromptComposer.d.ts.map +1 -1
  216. package/dist/core/PromptComposer.js +183 -106
  217. package/dist/core/PromptComposer.js.map +1 -1
  218. package/dist/core/PromptSectionCache.d.ts +1 -1
  219. package/dist/core/PromptSectionCache.js +1 -1
  220. package/dist/core/ResponseEngine.d.ts +18 -8
  221. package/dist/core/ResponseEngine.d.ts.map +1 -1
  222. package/dist/core/ResponseEngine.js +38 -36
  223. package/dist/core/ResponseEngine.js.map +1 -1
  224. package/dist/core/ResponseModal.d.ts +73 -56
  225. package/dist/core/ResponseModal.d.ts.map +1 -1
  226. package/dist/core/ResponseModal.js +1198 -1017
  227. package/dist/core/ResponseModal.js.map +1 -1
  228. package/dist/core/ResponsePipeline.d.ts +124 -26
  229. package/dist/core/ResponsePipeline.d.ts.map +1 -1
  230. package/dist/core/ResponsePipeline.js +524 -135
  231. package/dist/core/ResponsePipeline.js.map +1 -1
  232. package/dist/core/SignalEvaluator.d.ts +86 -0
  233. package/dist/core/SignalEvaluator.d.ts.map +1 -0
  234. package/dist/core/SignalEvaluator.js +326 -0
  235. package/dist/core/SignalEvaluator.js.map +1 -0
  236. package/dist/core/SignalProcessor.d.ts +152 -0
  237. package/dist/core/SignalProcessor.d.ts.map +1 -0
  238. package/dist/core/SignalProcessor.js +555 -0
  239. package/dist/core/SignalProcessor.js.map +1 -0
  240. package/dist/core/Step.d.ts +43 -32
  241. package/dist/core/Step.d.ts.map +1 -1
  242. package/dist/core/Step.js +220 -126
  243. package/dist/core/Step.js.map +1 -1
  244. package/dist/core/StreamingToolExecutor.d.ts +2 -2
  245. package/dist/core/StreamingToolExecutor.d.ts.map +1 -1
  246. package/dist/core/StreamingToolExecutor.js.map +1 -1
  247. package/dist/core/ToolManager.d.ts +44 -13
  248. package/dist/core/ToolManager.d.ts.map +1 -1
  249. package/dist/core/ToolManager.js +174 -91
  250. package/dist/core/ToolManager.js.map +1 -1
  251. package/dist/core/createAgent.d.ts +35 -0
  252. package/dist/core/createAgent.d.ts.map +1 -0
  253. package/dist/core/createAgent.js +36 -0
  254. package/dist/core/createAgent.js.map +1 -0
  255. package/dist/core/flow-namespace.d.ts +49 -0
  256. package/dist/core/flow-namespace.d.ts.map +1 -0
  257. package/dist/core/flow-namespace.js +168 -0
  258. package/dist/core/flow-namespace.js.map +1 -0
  259. package/dist/index.d.ts +11 -14
  260. package/dist/index.d.ts.map +1 -1
  261. package/dist/index.js +9 -12
  262. package/dist/index.js.map +1 -1
  263. package/dist/providers/GeminiProvider.d.ts +3 -3
  264. package/dist/providers/GeminiProvider.d.ts.map +1 -1
  265. package/dist/providers/GeminiProvider.js +16 -14
  266. package/dist/providers/GeminiProvider.js.map +1 -1
  267. package/dist/types/agent.d.ts +183 -54
  268. package/dist/types/agent.d.ts.map +1 -1
  269. package/dist/types/agent.js +0 -6
  270. package/dist/types/agent.js.map +1 -1
  271. package/dist/types/ai.d.ts +3 -3
  272. package/dist/types/ai.d.ts.map +1 -1
  273. package/dist/types/errors.d.ts +15 -0
  274. package/dist/types/errors.d.ts.map +1 -0
  275. package/dist/types/errors.js +18 -0
  276. package/dist/types/errors.js.map +1 -0
  277. package/dist/types/flow.d.ts +513 -0
  278. package/dist/types/flow.d.ts.map +1 -0
  279. package/dist/types/flow.js +5 -0
  280. package/dist/types/flow.js.map +1 -0
  281. package/dist/types/index.d.ts +7 -6
  282. package/dist/types/index.d.ts.map +1 -1
  283. package/dist/types/index.js +4 -1
  284. package/dist/types/index.js.map +1 -1
  285. package/dist/types/persistence.d.ts +11 -7
  286. package/dist/types/persistence.d.ts.map +1 -1
  287. package/dist/types/routing.d.ts +1 -1
  288. package/dist/types/routing.d.ts.map +1 -1
  289. package/dist/types/session.d.ts +24 -23
  290. package/dist/types/session.d.ts.map +1 -1
  291. package/dist/types/signals.d.ts +248 -0
  292. package/dist/types/signals.d.ts.map +1 -0
  293. package/dist/types/signals.js +10 -0
  294. package/dist/types/signals.js.map +1 -0
  295. package/dist/types/template.d.ts +2 -8
  296. package/dist/types/template.d.ts.map +1 -1
  297. package/dist/types/tool.d.ts +36 -29
  298. package/dist/types/tool.d.ts.map +1 -1
  299. package/dist/types/tool.js +1 -1
  300. package/dist/types/tool.js.map +1 -1
  301. package/dist/utils/condition.d.ts +7 -1
  302. package/dist/utils/condition.d.ts.map +1 -1
  303. package/dist/utils/condition.js.map +1 -1
  304. package/dist/utils/id.d.ts +13 -5
  305. package/dist/utils/id.d.ts.map +1 -1
  306. package/dist/utils/id.js +22 -9
  307. package/dist/utils/id.js.map +1 -1
  308. package/dist/utils/index.d.ts +2 -2
  309. package/dist/utils/index.d.ts.map +1 -1
  310. package/dist/utils/index.js +2 -2
  311. package/dist/utils/index.js.map +1 -1
  312. package/dist/utils/session.d.ts +44 -5
  313. package/dist/utils/session.d.ts.map +1 -1
  314. package/dist/utils/session.js +193 -37
  315. package/dist/utils/session.js.map +1 -1
  316. package/docs/README.md +15 -202
  317. package/docs/concepts/architecture.md +281 -0
  318. package/docs/concepts/directives.md +400 -0
  319. package/docs/concepts/pipeline.md +399 -0
  320. package/docs/guides/branching.md +263 -0
  321. package/docs/guides/compaction.md +163 -0
  322. package/docs/guides/conditions.md +167 -0
  323. package/docs/guides/error-handling.md +176 -0
  324. package/docs/guides/flow-control.md +409 -0
  325. package/docs/guides/instructions.md +210 -0
  326. package/docs/guides/persistence.md +182 -0
  327. package/docs/guides/streaming.md +137 -0
  328. package/docs/migration/README.md +15 -0
  329. package/docs/migration/route-to-flow.md +560 -0
  330. package/docs/migration/v1-to-v2.md +909 -0
  331. package/docs/reference/adapters.md +481 -0
  332. package/docs/reference/branches.md +241 -0
  333. package/docs/reference/create-agent.md +186 -0
  334. package/docs/reference/directive.md +243 -0
  335. package/docs/reference/errors.md +122 -0
  336. package/docs/reference/flow.md +238 -0
  337. package/docs/reference/instruction.md +177 -0
  338. package/docs/reference/pre-directive.md +131 -0
  339. package/docs/reference/providers.md +227 -0
  340. package/docs/reference/signals.md +356 -0
  341. package/docs/reference/step.md +339 -0
  342. package/docs/reference/tool.md +269 -0
  343. package/docs/start/01-install.md +81 -0
  344. package/docs/start/02-first-agent.md +196 -0
  345. package/docs/start/03-collect-data.md +222 -0
  346. package/docs/start/04-add-tools.md +276 -0
  347. package/docs/start/05-go-to-production.md +216 -0
  348. package/examples/01-quickstart.ts +20 -0
  349. package/examples/02-data-extraction.ts +90 -0
  350. package/examples/03-tools.ts +136 -0
  351. package/examples/04-instructions.ts +100 -0
  352. package/examples/05-branching.ts +140 -0
  353. package/examples/06-flow-control.ts +103 -0
  354. package/examples/07-streaming.ts +69 -0
  355. package/examples/08-persistence.ts +98 -0
  356. package/examples/09-signals.ts +144 -0
  357. package/examples/tsconfig.json +30 -0
  358. package/package.json +2 -1
  359. package/src/adapters/MemoryAdapter.ts +3 -3
  360. package/src/adapters/MongoAdapter.ts +3 -3
  361. package/src/adapters/OpenSearchAdapter.ts +10 -8
  362. package/src/adapters/PostgreSQLAdapter.ts +26 -10
  363. package/src/adapters/PrismaAdapter.ts +6 -6
  364. package/src/adapters/RedisAdapter.ts +3 -3
  365. package/src/adapters/SQLiteAdapter.ts +31 -12
  366. package/src/constants/index.ts +2 -10
  367. package/src/core/Agent.ts +585 -374
  368. package/src/core/AutoChainExecutor.ts +440 -0
  369. package/src/core/BranchEvaluator.ts +167 -0
  370. package/src/core/DirectiveBus.ts +248 -0
  371. package/src/core/DirectiveChainTracker.ts +144 -0
  372. package/src/core/Flow.ts +666 -0
  373. package/src/core/{RoutingEngine.ts → FlowRouter.ts} +385 -365
  374. package/src/core/PersistenceManager.ts +8 -8
  375. package/src/core/PromptComposer.ts +209 -140
  376. package/src/core/PromptSectionCache.ts +1 -1
  377. package/src/core/ResponseEngine.ts +61 -46
  378. package/src/core/ResponseModal.ts +1458 -1241
  379. package/src/core/ResponsePipeline.ts +675 -173
  380. package/src/core/SignalEvaluator.ts +420 -0
  381. package/src/core/SignalProcessor.ts +723 -0
  382. package/src/core/Step.ts +279 -176
  383. package/src/core/StreamingToolExecutor.ts +4 -4
  384. package/src/core/ToolManager.ts +200 -97
  385. package/src/core/createAgent.ts +40 -0
  386. package/src/core/flow-namespace.ts +219 -0
  387. package/src/index.ts +42 -36
  388. package/src/providers/GeminiProvider.ts +17 -15
  389. package/src/types/agent.ts +182 -53
  390. package/src/types/ai.ts +3 -3
  391. package/src/types/errors.ts +18 -0
  392. package/src/types/flow.ts +590 -0
  393. package/src/types/index.ts +43 -16
  394. package/src/types/persistence.ts +12 -8
  395. package/src/types/routing.ts +1 -1
  396. package/src/types/session.ts +26 -23
  397. package/src/types/signals.ts +321 -0
  398. package/src/types/template.ts +3 -11
  399. package/src/types/tool.ts +50 -42
  400. package/src/utils/condition.ts +13 -4
  401. package/src/utils/id.ts +27 -9
  402. package/src/utils/index.ts +6 -2
  403. package/src/utils/session.ts +238 -42
  404. package/dist/cjs/core/BatchExecutor.d.ts +0 -359
  405. package/dist/cjs/core/BatchExecutor.d.ts.map +0 -1
  406. package/dist/cjs/core/BatchExecutor.js +0 -861
  407. package/dist/cjs/core/BatchExecutor.js.map +0 -1
  408. package/dist/cjs/core/BatchPromptBuilder.d.ts +0 -89
  409. package/dist/cjs/core/BatchPromptBuilder.d.ts.map +0 -1
  410. package/dist/cjs/core/BatchPromptBuilder.js +0 -223
  411. package/dist/cjs/core/BatchPromptBuilder.js.map +0 -1
  412. package/dist/cjs/core/Route.d.ts +0 -180
  413. package/dist/cjs/core/Route.d.ts.map +0 -1
  414. package/dist/cjs/core/Route.js +0 -542
  415. package/dist/cjs/core/Route.js.map +0 -1
  416. package/dist/cjs/core/RoutingEngine.d.ts +0 -185
  417. package/dist/cjs/core/RoutingEngine.d.ts.map +0 -1
  418. package/dist/cjs/core/RoutingEngine.js.map +0 -1
  419. package/dist/cjs/types/route.d.ts +0 -336
  420. package/dist/cjs/types/route.d.ts.map +0 -1
  421. package/dist/cjs/types/route.js.map +0 -1
  422. package/dist/core/BatchExecutor.d.ts +0 -359
  423. package/dist/core/BatchExecutor.d.ts.map +0 -1
  424. package/dist/core/BatchExecutor.js +0 -856
  425. package/dist/core/BatchExecutor.js.map +0 -1
  426. package/dist/core/BatchPromptBuilder.d.ts +0 -89
  427. package/dist/core/BatchPromptBuilder.d.ts.map +0 -1
  428. package/dist/core/BatchPromptBuilder.js +0 -219
  429. package/dist/core/BatchPromptBuilder.js.map +0 -1
  430. package/dist/core/Route.d.ts +0 -180
  431. package/dist/core/Route.d.ts.map +0 -1
  432. package/dist/core/Route.js +0 -538
  433. package/dist/core/Route.js.map +0 -1
  434. package/dist/core/RoutingEngine.d.ts +0 -185
  435. package/dist/core/RoutingEngine.d.ts.map +0 -1
  436. package/dist/core/RoutingEngine.js.map +0 -1
  437. package/dist/types/route.d.ts +0 -336
  438. package/dist/types/route.d.ts.map +0 -1
  439. package/dist/types/route.js +0 -5
  440. package/dist/types/route.js.map +0 -1
  441. package/docs/CONTRIBUTING.md +0 -521
  442. package/docs/api/README.md +0 -3299
  443. package/docs/api/overview.md +0 -1410
  444. package/docs/architecture/data-extraction-flow.md +0 -360
  445. package/docs/architecture/multi-step-execution.md +0 -277
  446. package/docs/core/agent/README.md +0 -938
  447. package/docs/core/agent/context-management.md +0 -796
  448. package/docs/core/agent/rules-and-prohibitions.md +0 -113
  449. package/docs/core/agent/session-management.md +0 -693
  450. package/docs/core/ai-integration/prompt-composition.md +0 -355
  451. package/docs/core/ai-integration/providers.md +0 -515
  452. package/docs/core/ai-integration/response-processing.md +0 -433
  453. package/docs/core/conversation-flows/data-collection.md +0 -772
  454. package/docs/core/conversation-flows/route-dsl.md +0 -509
  455. package/docs/core/conversation-flows/routes.md +0 -249
  456. package/docs/core/conversation-flows/step-transitions.md +0 -731
  457. package/docs/core/conversation-flows/steps.md +0 -268
  458. package/docs/core/error-handling.md +0 -830
  459. package/docs/core/persistence/adapters.md +0 -255
  460. package/docs/core/persistence/session-storage.md +0 -656
  461. package/docs/core/routing/intelligent-routing.md +0 -470
  462. package/docs/core/tools/enhanced-tool.md +0 -186
  463. package/docs/core/tools/streaming-execution.md +0 -161
  464. package/docs/core/tools/tool-definition.md +0 -970
  465. package/docs/core/tools/tool-scoping.md +0 -819
  466. package/docs/guides/advanced-patterns/publishing.md +0 -186
  467. package/docs/guides/context-compaction.md +0 -96
  468. package/docs/guides/error-handling-patterns.md +0 -578
  469. package/docs/guides/getting-started/README.md +0 -795
  470. package/docs/guides/migration/README.md +0 -101
  471. package/docs/guides/migration/flexible-routing-conditions.md +0 -375
  472. package/docs/guides/migration/multi-step-execution.md +0 -393
  473. package/docs/guides/migration/response-modal-refactor.md +0 -518
  474. package/docs/guides/prompt-optimization.md +0 -164
  475. package/examples/advanced-patterns/context-compaction.ts +0 -223
  476. package/examples/advanced-patterns/knowledge-based-agent.ts +0 -735
  477. package/examples/advanced-patterns/persistent-onboarding.ts +0 -728
  478. package/examples/advanced-patterns/route-lifecycle-hooks.ts +0 -556
  479. package/examples/advanced-patterns/streaming-responses.ts +0 -656
  480. package/examples/ai-providers/anthropic-integration.ts +0 -388
  481. package/examples/ai-providers/openai-integration.ts +0 -228
  482. package/examples/condition-patterns/function-only-conditions.ts +0 -365
  483. package/examples/condition-patterns/mixed-array-conditions.ts +0 -477
  484. package/examples/condition-patterns/route-skipif-patterns.ts +0 -468
  485. package/examples/condition-patterns/step-skipif-patterns.ts +0 -0
  486. package/examples/condition-patterns/string-only-conditions.ts +0 -296
  487. package/examples/conversation-flows/completion-transitions.ts +0 -318
  488. package/examples/core-concepts/basic-agent.ts +0 -503
  489. package/examples/core-concepts/modern-streaming-api.ts +0 -309
  490. package/examples/core-concepts/schema-driven-extraction.ts +0 -332
  491. package/examples/core-concepts/session-management.ts +0 -494
  492. package/examples/integrations/database-integration.ts +0 -631
  493. package/examples/integrations/healthcare-integration.ts +0 -595
  494. package/examples/integrations/search-integration.ts +0 -530
  495. package/examples/integrations/server-session-management.ts +0 -307
  496. package/examples/persistence/custom-adapter.ts +0 -526
  497. package/examples/persistence/database-persistence.ts +0 -583
  498. package/examples/persistence/memory-sessions.ts +0 -495
  499. package/examples/persistence/prisma-schema.example.prisma +0 -74
  500. package/examples/persistence/redis-persistence.ts +0 -488
  501. package/examples/tools/basic-tools.ts +0 -765
  502. package/examples/tools/data-enrichment-tools.ts +0 -593
  503. package/examples/tools/enhanced-tool-metadata.ts +0 -268
  504. package/examples/tools/streaming-tool-execution.ts +0 -283
  505. package/src/core/BatchExecutor.ts +0 -1187
  506. package/src/core/BatchPromptBuilder.ts +0 -299
  507. package/src/core/Route.ts +0 -678
  508. 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)