@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,276 @@
1
+ ---
2
+ title: "Add tools"
3
+ description: "Extend the booking agent with tools that book the room, gate eligibility, and redirect on failure."
4
+ type: tutorial
5
+ order: 4
6
+ ---
7
+
8
+ # Add tools
9
+
10
+ So far the agent talks. Now it acts. You will add a tool that books a hotel room and a tool that checks whether the user is allowed to book at all. Along the way you will see how `ctx.dispatch` and `ToolResult.directive` both land on the same directive bus, and why most tools only need an `id` and a `handler` to start.
11
+
12
+ So far the agent only collects fields. This page adds two tools:
13
+
14
+ - `book_hotel` — runs once the required fields are in, returns a
15
+ booking id, and (optionally) finishes the flow with a directive.
16
+ - `check_eligibility` — runs early and redirects to a denial flow
17
+ when the caller is not allowed. You'll see both forms of
18
+ redirection: imperative (`ctx.dispatch`) and declarative
19
+ (`ToolResult.directive`).
20
+
21
+ You'll also meet the optional metadata fields — `isReadOnly`,
22
+ `validateInput`, `checkPermissions` — that let tools opt into safer
23
+ defaults when you need them.
24
+
25
+ > Tool surface used here is the canonical [Tool reference](../reference/tool.md).
26
+ > `Tool.id` is the sole identifier — there's no separate `name`.
27
+
28
+ ## Recap: where we left off
29
+
30
+ `docs/start/03-collect-data.md` left us with a `Book Hotel` flow that
31
+ collects `destination`, `checkIn`, and `guests`, and a `confirm` step
32
+ that waits until all three are populated. We'll hand the `confirm`
33
+ step a tool that actually books the room, plus an eligibility check
34
+ to gate it.
35
+
36
+ ```typescript
37
+ interface BookingData {
38
+ destination: string;
39
+ checkIn: string;
40
+ guests: number;
41
+ bookingId?: string;
42
+ }
43
+ ```
44
+
45
+ ## 1. Add `book_hotel`
46
+
47
+ A tool is an object with an `id`, an optional `description` and
48
+ `parameters` schema, and a `handler` that returns the result the AI
49
+ will see. The handler receives a `ToolContext` (`ctx`) — the read
50
+ surface over `data`, `context`, and the session.
51
+
52
+ ```typescript
53
+ import type { Tool } from "@falai/agent";
54
+
55
+ const bookHotel: Tool<unknown, BookingData, { bookingId: string }> = {
56
+ id: "book_hotel",
57
+ description: "Reserve the hotel for the collected destination, dates, and guest count.",
58
+ parameters: {
59
+ type: "object",
60
+ properties: {
61
+ destination: { type: "string" },
62
+ checkIn: { type: "string" },
63
+ guests: { type: "number" },
64
+ },
65
+ required: ["destination", "checkIn", "guests"],
66
+ },
67
+ async handler(ctx, args) {
68
+ const bookingId = await reserve(args);
69
+ return {
70
+ data: { bookingId },
71
+ dataUpdate: { bookingId },
72
+ };
73
+ },
74
+ };
75
+ ```
76
+
77
+ The handler returns a `ToolResult`:
78
+
79
+ - `data` is what the AI sees as the tool result (used to compose the
80
+ next assistant message).
81
+ - `dataUpdate` is shallow-merged into `session.data`, so the booking
82
+ id sticks for the rest of the conversation.
83
+
84
+ Wire the tool to the `confirm` step:
85
+
86
+ ```typescript
87
+ {
88
+ id: "confirm",
89
+ prompt: "Confirm the trip and call book_hotel.",
90
+ requires: ["destination", "checkIn", "guests"],
91
+ tools: [bookHotel],
92
+ }
93
+ ```
94
+
95
+ The AI now has the tool available on `confirm`. Once the three
96
+ fields are set, it can call `book_hotel`, get the id back, and
97
+ confirm the booking in the reply.
98
+
99
+ ### Optional: finish the flow declaratively
100
+
101
+ If you want the tool itself to close the flow — instead of relying
102
+ on the next turn to notice `requiredFields` are satisfied — return a
103
+ `directive` alongside the data:
104
+
105
+ ```typescript
106
+ async handler(ctx, args) {
107
+ const bookingId = await reserve(args);
108
+ return {
109
+ data: { bookingId },
110
+ directive: {
111
+ complete: { reason: "reservation confirmed" },
112
+ dataUpdate: { bookingId },
113
+ },
114
+ };
115
+ }
116
+ ```
117
+
118
+ `ToolResult.directive` is the **declarative** form of redirection: a
119
+ directive returned with the result. Whatever you can say with
120
+ `ctx.dispatch` mid-handler, you can say with `directive` on return.
121
+ They merge identically. See [Directives](../concepts/directives.md)
122
+ for the full shape.
123
+
124
+ ## 2. Add `check_eligibility` — imperative form
125
+
126
+ Some destinations are off-limits for some users. We want a tool that
127
+ runs before the AI starts pitching options, decides whether the
128
+ caller can proceed, and — when not — bails out into a denial flow.
129
+
130
+ The imperative form uses `ctx.dispatch` to emit a directive
131
+ mid-handler:
132
+
133
+ ```typescript
134
+ const checkEligibilityImperative: Tool<{ userId: string }, BookingData, { ok: boolean }> = {
135
+ id: "check_eligibility",
136
+ description: "Verify the caller is allowed to book this destination.",
137
+ isReadOnly: () => true,
138
+ async handler(ctx) {
139
+ const ok = await isEligible(ctx.context.userId, ctx.data.destination);
140
+
141
+ if (!ok) {
142
+ // Stop reasoning down this path — jump to the denial flow.
143
+ ctx.dispatch({
144
+ goTo: "Denial",
145
+ reply: "Sorry — you're not eligible to book that destination.",
146
+ });
147
+ return { ok: false };
148
+ }
149
+
150
+ return { ok: true };
151
+ },
152
+ };
153
+ ```
154
+
155
+ What just happened:
156
+
157
+ - `ctx.dispatch(directive)` puts the directive on this turn's
158
+ directive bus. Algorithm 4 picks it up alongside any other
159
+ emissions.
160
+ - `goTo: "Denial"` redirects to a sibling flow named `"Denial"`.
161
+ - `reply` is the verbatim assistant utterance — the LLM call this
162
+ turn is skipped and the literal string is what the user sees.
163
+ - The handler still returns `{ ok: false }` so the trace is honest
164
+ about what the tool did.
165
+
166
+ For the redirect to work, the agent needs a `Denial` flow. It can
167
+ be as small as:
168
+
169
+ ```typescript
170
+ {
171
+ title: "Denial",
172
+ steps: [{ id: "explain",
173
+ prompt: "Explain why the booking is not possible and offer help." }],
174
+ },
175
+ ```
176
+
177
+ Wire the eligibility check on the `confirm` step (or earlier — your
178
+ call):
179
+
180
+ ```typescript
181
+ {
182
+ id: "confirm",
183
+ prompt: "Confirm the trip and call book_hotel.",
184
+ requires: ["destination", "checkIn", "guests"],
185
+ tools: [checkEligibilityImperative, bookHotel],
186
+ }
187
+ ```
188
+
189
+ ## 3. Same tool — declarative form
190
+
191
+ Many handlers don't need to dispatch mid-flight. They can compute
192
+ the answer, build the directive, and return it on the result.
193
+ `ToolResult.directive` is identical in effect to `ctx.dispatch` —
194
+ same merge, same precedence, same shape.
195
+
196
+ ```typescript
197
+ const checkEligibilityDeclarative: Tool<{ userId: string }, BookingData, { ok: boolean }> = {
198
+ id: "check_eligibility",
199
+ description: "Verify the caller is allowed to book this destination.",
200
+ isReadOnly: () => true,
201
+ async handler(ctx) {
202
+ const ok = await isEligible(ctx.context.userId, ctx.data.destination);
203
+
204
+ if (!ok) {
205
+ return {
206
+ data: { ok: false },
207
+ directive: {
208
+ goTo: "Denial",
209
+ reply: "Sorry — you're not eligible to book that destination.",
210
+ },
211
+ };
212
+ }
213
+
214
+ return { data: { ok: true } };
215
+ },
216
+ };
217
+ ```
218
+
219
+ When to reach for which:
220
+
221
+ - **Imperative** — you need to dispatch before the handler is done
222
+ (e.g. an early branch decides the rest of the work is moot but
223
+ the result payload still has to be computed for the trace).
224
+ - **Declarative** — single return point, directive next to the data
225
+ it goes with. Easier to read; preferred when there's no reason to
226
+ split.
227
+
228
+ Both forms can co-exist. Multiple `dispatch` calls plus a `directive`
229
+ on the return value all land on the same bus and merge identically
230
+ (see [Directives](../concepts/directives.md)).
231
+
232
+ ## 4. Optional metadata, briefly
233
+
234
+ Every metadata field on `Tool` is optional. Reach for them only when
235
+ you want the safer default they buy you.
236
+
237
+ ```typescript
238
+ isReadOnly: () => true; // safe to cache and parallelize
239
+ validateInput: (input) => ({ valid: typeof input.guests === "number" }); // repair or reject bad args
240
+ checkPermissions: (_, ctx) => ({ allowed: !!ctx.context.userId }); // gate access; handler skipped on deny
241
+ ```
242
+
243
+ Four more live on the same surface — `isConcurrencySafe`,
244
+ `isDestructive`, `interruptBehavior`, `maxResultSizeChars`. See the
245
+ [Tool reference](../reference/tool.md) for the full list and exact
246
+ contracts.
247
+
248
+ ## 5. Run it
249
+
250
+ A user message like
251
+
252
+ > "Book me a room in Lisbon for 2 adults, checking in March 14."
253
+
254
+ now flows through:
255
+
256
+ 1. **Pre-extraction.** The router pulls `destination: "Lisbon"`,
257
+ `checkIn: "March 14"`, `guests: 2` out of the message in one shot.
258
+ 2. **Step selection.** The `ask` step is satisfied — every `collect`
259
+ field is set — so the engine skips it and enters `confirm`.
260
+ 3. **Eligibility.** The AI calls `check_eligibility`. If allowed,
261
+ the tool returns `{ ok: true }` and we move on. If not, the
262
+ dispatched directive jumps to the `Denial` flow and the verbatim
263
+ `reply` becomes the assistant message — no LLM call this turn.
264
+ 4. **Booking.** The AI calls `book_hotel`, gets a `bookingId`, and
265
+ composes the confirmation reply.
266
+ 5. **Completion.** With every required field present (and a
267
+ `bookingId` in `data`), the flow finishes.
268
+
269
+ ## What's next
270
+
271
+ You have an agent that collects data, runs tools, gates access, and
272
+ redirects on failure. The remaining concern is shipping it: swapping
273
+ `MemoryAdapter` for `PrismaAdapter`, streaming responses, and
274
+ dropping the agent behind an HTTP endpoint.
275
+
276
+ **Next:** [Go to production](./05-go-to-production.md)
@@ -0,0 +1,216 @@
1
+ ---
2
+ title: "Go to production"
3
+ description: "Add durable persistence, streaming responses, and an HTTP endpoint to ship the booking agent."
4
+ type: tutorial
5
+ order: 5
6
+ ---
7
+
8
+ # Go to production
9
+
10
+ The framework stays the same shape from prototype to production; only the adapter and the call site change. This page adds `PrismaAdapter` for durable sessions, `respondStream` for real-time output, and a session-keyed POST endpoint that any chat client can call. Same seven primitives, same booking flow — now with persistence and streaming on top.
11
+
12
+ The booking agent from [04 — Add tools](./04-add-tools.md) runs end to end, but it forgets every conversation the moment the process exits, hands replies back as one final string, and lives in a script. Production has three more requirements: durability, real-time output, and a way for clients to talk to it. This page wires up all three.
13
+
14
+ You will:
15
+
16
+ 1. Swap the implicit `MemoryAdapter` for `PrismaAdapter` so sessions survive restarts.
17
+ 2. Switch the call site from `agent.respond` to `agent.respondStream` and consume chunks as they arrive.
18
+ 3. Wrap the agent in a session-keyed POST endpoint that any chat client can call.
19
+
20
+ By the end you have the same booking agent — same flow, same tools — running behind an HTTP API with persistent state.
21
+
22
+ ## 1. Persist sessions with Prisma
23
+
24
+ By default `createAgent` uses `MemoryAdapter`, an in-process map that vanishes with the process. Production needs storage that outlives a deploy. `PrismaAdapter` rides on top of any Prisma-supported database; you own the schema, the adapter does the reads and writes.
25
+
26
+ Add Prisma to the project:
27
+
28
+ ```bash
29
+ bun add @prisma/client
30
+ bun add -d prisma
31
+ bunx prisma init
32
+ ```
33
+
34
+ Open the generated `prisma/schema.prisma` and add the `AgentSession` and `AgentMessage` models. Two columns matter most: `pendingDirective` and `signals`. The agent serializes its [`Directive`](../reference/directive.md) and signal state into them at the end of every turn and reads them back at the start of the next.
35
+
36
+ ```prisma
37
+ // prisma/schema.prisma
38
+ generator client {
39
+ provider = "prisma-client-js"
40
+ }
41
+
42
+ datasource db {
43
+ provider = "postgresql"
44
+ url = env("DATABASE_URL")
45
+ }
46
+
47
+ model AgentSession {
48
+ id String @id
49
+ userId String?
50
+ agentName String?
51
+ status String @default("active")
52
+ currentFlow String?
53
+ currentStep String?
54
+ collectedData Json?
55
+ pendingDirective Json?
56
+ signals Json?
57
+ messageCount Int @default(0)
58
+ lastMessageAt DateTime?
59
+ completedAt DateTime?
60
+ createdAt DateTime @default(now())
61
+ updatedAt DateTime @updatedAt
62
+ }
63
+
64
+ model AgentMessage {
65
+ id String @id @default(cuid())
66
+ sessionId String
67
+ role String
68
+ content String
69
+ createdAt DateTime @default(now())
70
+
71
+ @@index([sessionId, createdAt])
72
+ }
73
+ ```
74
+
75
+ Push the schema and generate the client:
76
+
77
+ ```bash
78
+ bunx prisma db push
79
+ bunx prisma generate
80
+ ```
81
+
82
+ Now wire the adapter into the booking agent. The only change from the previous tutorial is the new `persistence` field — every flow, step, tool, and instruction stays exactly the same.
83
+
84
+ ```typescript
85
+ import { PrismaClient } from "@prisma/client";
86
+ import { createAgent, GeminiProvider, PrismaAdapter } from "@falai/agent";
87
+ import { bookingFlow, bookingTools, bookingInstructions, schema } from "./booking";
88
+
89
+ const prisma = new PrismaClient();
90
+
91
+ export const agent = createAgent({
92
+ name: "BookingBot",
93
+ provider: new GeminiProvider({ apiKey: process.env.GEMINI_API_KEY! }),
94
+ schema,
95
+ flows: [bookingFlow],
96
+ tools: bookingTools,
97
+ instructions: bookingInstructions,
98
+ persistence: {
99
+ adapter: new PrismaAdapter({ prisma }),
100
+ userId: "user_123",
101
+ },
102
+ });
103
+ ```
104
+
105
+ To resume a conversation by id, hydrate the session from the adapter and pass it through. `agent.session.getOrCreate(sessionId)` loads the stored `SessionState` (collected data, flow position, `pendingDirective`, signals state) — or creates a fresh one with that id if nothing exists yet.
106
+
107
+ ```typescript
108
+ const session = await agent.session.getOrCreate("user_123:thread_abc");
109
+
110
+ const response = await agent.respond({
111
+ history: [{ role: "user", content: "Hi again" }],
112
+ session,
113
+ });
114
+ ```
115
+
116
+ Unknown ids start fresh against that id; there is no "not found" error path.
117
+
118
+ For the full schema migration story (renaming `pending_transition` to `pendingDirective`, adding the `signals` column) see [persistence adapters reference](../reference/adapters.md#prismaadapter).
119
+
120
+ ## 2. Stream responses
121
+
122
+ `agent.respond` returns one final `AgentResponse` after the LLM and any tools have finished. That works for batch jobs, but a chat UI feels dead until the first character lands. `agent.respondStream` returns an `AsyncGenerator<AgentResponseStreamChunk>` — every chunk has the latest `delta` and `accumulated` text, plus a `done` flag.
123
+
124
+ ```typescript
125
+ const stream = agent.respondStream({
126
+ history: [{ role: "user", content: "Book me a hotel in Lisbon for two nights." }],
127
+ });
128
+
129
+ for await (const chunk of stream) {
130
+ if (chunk.delta) {
131
+ process.stdout.write(chunk.delta);
132
+ }
133
+ if (chunk.done) {
134
+ console.log("\n---");
135
+ console.log("Applied instructions:", chunk.appliedInstructions);
136
+ console.log("Triggered signals:", chunk.triggeredSignals);
137
+ console.log("Flow complete:", chunk.isFlowComplete);
138
+ }
139
+ }
140
+ ```
141
+
142
+ Two fields land only on the terminal chunk (`done: true`):
143
+
144
+ - `appliedInstructions` — the [instructions](../reference/instruction.md) whose conditions passed and were rendered into this turn's prompt. Deterministic; derived from rendering, not from LLM self-report.
145
+ - `triggeredSignals` — the signals (if any) that fired during this turn, in fire order.
146
+
147
+ Use them for telemetry, audit logs, or showing the user which guardrails ran. They mirror the same fields on the non-streaming `AgentResponse`, so swapping between APIs does not change observability.
148
+
149
+ To cancel mid-stream — say, the user hits Stop — pass an `AbortSignal`:
150
+
151
+ ```typescript
152
+ const controller = new AbortController();
153
+ setTimeout(() => controller.abort(), 5000);
154
+
155
+ const stream = agent.respondStream({
156
+ history,
157
+ signal: controller.signal,
158
+ });
159
+ ```
160
+
161
+ ## 3. A session-keyed HTTP endpoint
162
+
163
+ The agent is now durable and streaming. The last piece is exposing it. Any HTTP framework works — Express, Bun.serve, Fastify, Hono. The pattern is the same: accept a `sessionId` and `message`, look up history, stream chunks back to the client. This Bun example is one screenful.
164
+
165
+ ```typescript
166
+ import { agent } from "./agent";
167
+
168
+ Bun.serve({
169
+ port: 3000,
170
+ async fetch(req) {
171
+ if (req.method !== "POST" || new URL(req.url).pathname !== "/chat") {
172
+ return new Response("Not found", { status: 404 });
173
+ }
174
+
175
+ const { sessionId, message } = await req.json() as {
176
+ sessionId: string;
177
+ message: string;
178
+ };
179
+
180
+ const session = await agent.session.getOrCreate(sessionId);
181
+
182
+ const stream = agent.respondStream({
183
+ history: [{ role: "user", content: message }],
184
+ session,
185
+ });
186
+
187
+ return new Response(
188
+ new ReadableStream({
189
+ async start(controller) {
190
+ for await (const chunk of stream) {
191
+ controller.enqueue(
192
+ new TextEncoder().encode(
193
+ `data: ${JSON.stringify({
194
+ delta: chunk.delta,
195
+ done: chunk.done,
196
+ isFlowComplete: chunk.isFlowComplete,
197
+ })}\n\n`
198
+ )
199
+ );
200
+ }
201
+ controller.close();
202
+ },
203
+ }),
204
+ { headers: { "Content-Type": "text/event-stream" } }
205
+ );
206
+ },
207
+ });
208
+ ```
209
+
210
+ The shape that matters: `sessionId` is the contract between client and server. The same id on every request keeps the user pinned to the same conversation; the adapter loads the right `pendingDirective` and `signals`, the agent picks up exactly where the last turn ended. No per-request setup, no global state.
211
+
212
+ A real chat backend adds auth, rate limits, and persistent message storage — but the core glue is the four lines that build `agent`, the four lines that read `request.json()`, and the loop that pipes stream chunks into Server-Sent Events.
213
+
214
+ That is the full path: a 12-line `createAgent` call in [02 — Your first agent](./02-first-agent.md), data extraction in [03](./03-collect-data.md), tools in [04](./04-add-tools.md), and now durable, streaming, HTTP-served. The framework stays the same shape from prototype to production — only the adapter and the call site change.
215
+
216
+ **Next:** [How-to guides](../guides/conditions.md)
@@ -0,0 +1,20 @@
1
+ /** @intent Minimal agent: one flow, one step, one response.
2
+ * @teaches createAgent, GeminiProvider, Flow, Step, respond
3
+ * @readAfter docs/start/02-first-agent.md */
4
+ import { createAgent, GeminiProvider } from "../src";
5
+
6
+ if (!process.env.GEMINI_API_KEY) throw new Error("Set GEMINI_API_KEY");
7
+
8
+ const agent = createAgent({
9
+ name: "Greeter",
10
+ provider: new GeminiProvider({ apiKey: process.env.GEMINI_API_KEY, model: "models/gemini-2.5-flash" }),
11
+ schema: { type: "object", properties: { name: { type: "string" } } },
12
+ flows: [{
13
+ title: "Greet",
14
+ requiredFields: ["name"],
15
+ steps: [{ id: "ask_name", prompt: "What's your name?", collect: ["name"] }],
16
+ }],
17
+ });
18
+
19
+ const response = await agent.respond({ history: [{ role: "user", content: "Hi, I'm Alice" }] });
20
+ console.log(response.message);
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Data extraction — schema, collect, skip, requires, requiredFields; pre-extraction in action.
3
+ * Run with the message "I want X for Y people on Z" and watch all three fields populate from one turn.
4
+ * Read after: docs/start/03-collect-data.md
5
+ */
6
+
7
+ import { createAgent, GeminiProvider } from "@falai/agent";
8
+
9
+ // ─── Schema ──────────────────────────────────────────────────────────────────
10
+
11
+ interface BookingData {
12
+ roomType: "single" | "double" | "suite";
13
+ guests: number;
14
+ checkIn: string;
15
+ }
16
+
17
+ const schema = {
18
+ type: "object" as const,
19
+ properties: {
20
+ roomType: {
21
+ type: "string" as const,
22
+ enum: ["single", "double", "suite"],
23
+ description: "Type of room requested",
24
+ },
25
+ guests: {
26
+ type: "number" as const,
27
+ description: "Number of guests",
28
+ },
29
+ checkIn: {
30
+ type: "string" as const,
31
+ description: "Check-in date in YYYY-MM-DD format",
32
+ },
33
+ },
34
+ required: ["roomType", "guests", "checkIn"],
35
+ };
36
+
37
+ // ─── Agent ───────────────────────────────────────────────────────────────────
38
+
39
+ const agent = createAgent<Record<string, never>, BookingData>({
40
+ name: "Booking Agent",
41
+ provider: new GeminiProvider({
42
+ apiKey: process.env.GEMINI_API_KEY!,
43
+ model: "models/gemini-2.5-flash",
44
+ }),
45
+ schema,
46
+ flows: [
47
+ {
48
+ title: "Book a room",
49
+ when: "The user wants to book a hotel room",
50
+ requiredFields: ["roomType", "guests", "checkIn"],
51
+ steps: [
52
+ {
53
+ id: "ask_room",
54
+ prompt: "What type of room would you like? (single, double, or suite)",
55
+ collect: ["roomType"],
56
+ skip: [({ data }) => data.roomType !== undefined],
57
+ },
58
+ {
59
+ id: "ask_guests",
60
+ prompt: "How many guests will be staying?",
61
+ collect: ["guests"],
62
+ requires: ["roomType"],
63
+ skip: [({ data }) => data.guests !== undefined],
64
+ },
65
+ {
66
+ id: "ask_checkin",
67
+ prompt: "When would you like to check in?",
68
+ collect: ["checkIn"],
69
+ requires: ["roomType", "guests"],
70
+ skip: [({ data }) => data.checkIn !== undefined],
71
+ },
72
+ ],
73
+ },
74
+ ],
75
+ });
76
+
77
+ // ─── Run ─────────────────────────────────────────────────────────────────────
78
+
79
+ async function main() {
80
+ // Pre-extraction: all three fields are extracted from a single message.
81
+ const response = await agent.respond({
82
+ history: [{ role: "user", content: "I want a double for 2 people on 2025-03-15" }],
83
+ });
84
+
85
+ console.log(response.message);
86
+ console.log("Collected:", response.session?.data);
87
+ console.log("Complete:", response.isFlowComplete);
88
+ }
89
+
90
+ main();