@falai/agent 1.2.8 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (499) hide show
  1. package/README.md +40 -886
  2. package/dist/adapters/MemoryAdapter.js +2 -2
  3. package/dist/adapters/MemoryAdapter.js.map +1 -1
  4. package/dist/adapters/MongoAdapter.js +2 -2
  5. package/dist/adapters/MongoAdapter.js.map +1 -1
  6. package/dist/adapters/OpenSearchAdapter.d.ts.map +1 -1
  7. package/dist/adapters/OpenSearchAdapter.js +9 -7
  8. package/dist/adapters/OpenSearchAdapter.js.map +1 -1
  9. package/dist/adapters/PostgreSQLAdapter.d.ts +14 -0
  10. package/dist/adapters/PostgreSQLAdapter.d.ts.map +1 -1
  11. package/dist/adapters/PostgreSQLAdapter.js +25 -9
  12. package/dist/adapters/PostgreSQLAdapter.js.map +1 -1
  13. package/dist/adapters/PrismaAdapter.js +5 -5
  14. package/dist/adapters/PrismaAdapter.js.map +1 -1
  15. package/dist/adapters/RedisAdapter.js +2 -2
  16. package/dist/adapters/RedisAdapter.js.map +1 -1
  17. package/dist/adapters/SQLiteAdapter.d.ts +17 -0
  18. package/dist/adapters/SQLiteAdapter.d.ts.map +1 -1
  19. package/dist/adapters/SQLiteAdapter.js +30 -11
  20. package/dist/adapters/SQLiteAdapter.js.map +1 -1
  21. package/dist/cjs/adapters/MemoryAdapter.js +2 -2
  22. package/dist/cjs/adapters/MemoryAdapter.js.map +1 -1
  23. package/dist/cjs/adapters/MongoAdapter.js +2 -2
  24. package/dist/cjs/adapters/MongoAdapter.js.map +1 -1
  25. package/dist/cjs/adapters/OpenSearchAdapter.d.ts.map +1 -1
  26. package/dist/cjs/adapters/OpenSearchAdapter.js +9 -7
  27. package/dist/cjs/adapters/OpenSearchAdapter.js.map +1 -1
  28. package/dist/cjs/adapters/PostgreSQLAdapter.d.ts +14 -0
  29. package/dist/cjs/adapters/PostgreSQLAdapter.d.ts.map +1 -1
  30. package/dist/cjs/adapters/PostgreSQLAdapter.js +25 -9
  31. package/dist/cjs/adapters/PostgreSQLAdapter.js.map +1 -1
  32. package/dist/cjs/adapters/PrismaAdapter.js +5 -5
  33. package/dist/cjs/adapters/PrismaAdapter.js.map +1 -1
  34. package/dist/cjs/adapters/RedisAdapter.js +2 -2
  35. package/dist/cjs/adapters/RedisAdapter.js.map +1 -1
  36. package/dist/cjs/adapters/SQLiteAdapter.d.ts +17 -0
  37. package/dist/cjs/adapters/SQLiteAdapter.d.ts.map +1 -1
  38. package/dist/cjs/adapters/SQLiteAdapter.js +30 -11
  39. package/dist/cjs/adapters/SQLiteAdapter.js.map +1 -1
  40. package/dist/cjs/constants/index.d.ts +0 -9
  41. package/dist/cjs/constants/index.d.ts.map +1 -1
  42. package/dist/cjs/constants/index.js +2 -11
  43. package/dist/cjs/constants/index.js.map +1 -1
  44. package/dist/cjs/core/Agent.d.ts +119 -153
  45. package/dist/cjs/core/Agent.d.ts.map +1 -1
  46. package/dist/cjs/core/Agent.js +471 -324
  47. package/dist/cjs/core/Agent.js.map +1 -1
  48. package/dist/cjs/core/AutoChainExecutor.d.ts +107 -0
  49. package/dist/cjs/core/AutoChainExecutor.d.ts.map +1 -0
  50. package/dist/cjs/core/AutoChainExecutor.js +297 -0
  51. package/dist/cjs/core/AutoChainExecutor.js.map +1 -0
  52. package/dist/cjs/core/BranchEvaluator.d.ts +54 -0
  53. package/dist/cjs/core/BranchEvaluator.d.ts.map +1 -0
  54. package/dist/cjs/core/BranchEvaluator.js +130 -0
  55. package/dist/cjs/core/BranchEvaluator.js.map +1 -0
  56. package/dist/cjs/core/DirectiveBus.d.ts +88 -0
  57. package/dist/cjs/core/DirectiveBus.d.ts.map +1 -0
  58. package/dist/cjs/core/DirectiveBus.js +196 -0
  59. package/dist/cjs/core/DirectiveBus.js.map +1 -0
  60. package/dist/cjs/core/DirectiveChainTracker.d.ts +49 -0
  61. package/dist/cjs/core/DirectiveChainTracker.d.ts.map +1 -0
  62. package/dist/cjs/core/DirectiveChainTracker.js +121 -0
  63. package/dist/cjs/core/DirectiveChainTracker.js.map +1 -0
  64. package/dist/cjs/core/Flow.d.ts +186 -0
  65. package/dist/cjs/core/Flow.d.ts.map +1 -0
  66. package/dist/cjs/core/Flow.js +550 -0
  67. package/dist/cjs/core/Flow.js.map +1 -0
  68. package/dist/cjs/core/FlowRouter.d.ts +182 -0
  69. package/dist/cjs/core/FlowRouter.d.ts.map +1 -0
  70. package/dist/cjs/core/{RoutingEngine.js → FlowRouter.js} +323 -306
  71. package/dist/cjs/core/FlowRouter.js.map +1 -0
  72. package/dist/cjs/core/PersistenceManager.d.ts +2 -2
  73. package/dist/cjs/core/PersistenceManager.d.ts.map +1 -1
  74. package/dist/cjs/core/PersistenceManager.js +7 -7
  75. package/dist/cjs/core/PersistenceManager.js.map +1 -1
  76. package/dist/cjs/core/PromptComposer.d.ts +21 -8
  77. package/dist/cjs/core/PromptComposer.d.ts.map +1 -1
  78. package/dist/cjs/core/PromptComposer.js +182 -105
  79. package/dist/cjs/core/PromptComposer.js.map +1 -1
  80. package/dist/cjs/core/PromptSectionCache.d.ts +1 -1
  81. package/dist/cjs/core/PromptSectionCache.js +1 -1
  82. package/dist/cjs/core/ResponseEngine.d.ts +18 -8
  83. package/dist/cjs/core/ResponseEngine.d.ts.map +1 -1
  84. package/dist/cjs/core/ResponseEngine.js +38 -36
  85. package/dist/cjs/core/ResponseEngine.js.map +1 -1
  86. package/dist/cjs/core/ResponseModal.d.ts +73 -56
  87. package/dist/cjs/core/ResponseModal.d.ts.map +1 -1
  88. package/dist/cjs/core/ResponseModal.js +1191 -1014
  89. package/dist/cjs/core/ResponseModal.js.map +1 -1
  90. package/dist/cjs/core/ResponsePipeline.d.ts +124 -26
  91. package/dist/cjs/core/ResponsePipeline.d.ts.map +1 -1
  92. package/dist/cjs/core/ResponsePipeline.js +509 -136
  93. package/dist/cjs/core/ResponsePipeline.js.map +1 -1
  94. package/dist/cjs/core/SignalEvaluator.d.ts +86 -0
  95. package/dist/cjs/core/SignalEvaluator.d.ts.map +1 -0
  96. package/dist/cjs/core/SignalEvaluator.js +333 -0
  97. package/dist/cjs/core/SignalEvaluator.js.map +1 -0
  98. package/dist/cjs/core/SignalProcessor.d.ts +152 -0
  99. package/dist/cjs/core/SignalProcessor.d.ts.map +1 -0
  100. package/dist/cjs/core/SignalProcessor.js +562 -0
  101. package/dist/cjs/core/SignalProcessor.js.map +1 -0
  102. package/dist/cjs/core/Step.d.ts +43 -32
  103. package/dist/cjs/core/Step.d.ts.map +1 -1
  104. package/dist/cjs/core/Step.js +221 -126
  105. package/dist/cjs/core/Step.js.map +1 -1
  106. package/dist/cjs/core/StreamingToolExecutor.d.ts +2 -2
  107. package/dist/cjs/core/StreamingToolExecutor.d.ts.map +1 -1
  108. package/dist/cjs/core/StreamingToolExecutor.js.map +1 -1
  109. package/dist/cjs/core/ToolManager.d.ts +44 -13
  110. package/dist/cjs/core/ToolManager.d.ts.map +1 -1
  111. package/dist/cjs/core/ToolManager.js +174 -91
  112. package/dist/cjs/core/ToolManager.js.map +1 -1
  113. package/dist/cjs/core/createAgent.d.ts +35 -0
  114. package/dist/cjs/core/createAgent.d.ts.map +1 -0
  115. package/dist/cjs/core/createAgent.js +39 -0
  116. package/dist/cjs/core/createAgent.js.map +1 -0
  117. package/dist/cjs/core/flow-namespace.d.ts +49 -0
  118. package/dist/cjs/core/flow-namespace.d.ts.map +1 -0
  119. package/dist/cjs/core/flow-namespace.js +171 -0
  120. package/dist/cjs/core/flow-namespace.js.map +1 -0
  121. package/dist/cjs/index.d.ts +11 -14
  122. package/dist/cjs/index.d.ts.map +1 -1
  123. package/dist/cjs/index.js +18 -22
  124. package/dist/cjs/index.js.map +1 -1
  125. package/dist/cjs/types/agent.d.ts +183 -54
  126. package/dist/cjs/types/agent.d.ts.map +1 -1
  127. package/dist/cjs/types/agent.js +0 -6
  128. package/dist/cjs/types/agent.js.map +1 -1
  129. package/dist/cjs/types/ai.d.ts +3 -3
  130. package/dist/cjs/types/ai.d.ts.map +1 -1
  131. package/dist/cjs/types/errors.d.ts +15 -0
  132. package/dist/cjs/types/errors.d.ts.map +1 -0
  133. package/dist/cjs/types/errors.js +22 -0
  134. package/dist/cjs/types/errors.js.map +1 -0
  135. package/dist/cjs/types/flow.d.ts +513 -0
  136. package/dist/cjs/types/flow.d.ts.map +1 -0
  137. package/dist/cjs/types/{route.js → flow.js} +2 -2
  138. package/dist/cjs/types/flow.js.map +1 -0
  139. package/dist/cjs/types/index.d.ts +7 -6
  140. package/dist/cjs/types/index.d.ts.map +1 -1
  141. package/dist/cjs/types/index.js +6 -2
  142. package/dist/cjs/types/index.js.map +1 -1
  143. package/dist/cjs/types/persistence.d.ts +11 -7
  144. package/dist/cjs/types/persistence.d.ts.map +1 -1
  145. package/dist/cjs/types/routing.d.ts +1 -1
  146. package/dist/cjs/types/routing.d.ts.map +1 -1
  147. package/dist/cjs/types/session.d.ts +24 -23
  148. package/dist/cjs/types/session.d.ts.map +1 -1
  149. package/dist/cjs/types/signals.d.ts +248 -0
  150. package/dist/cjs/types/signals.d.ts.map +1 -0
  151. package/dist/cjs/types/signals.js +11 -0
  152. package/dist/cjs/types/signals.js.map +1 -0
  153. package/dist/cjs/types/template.d.ts +2 -8
  154. package/dist/cjs/types/template.d.ts.map +1 -1
  155. package/dist/cjs/types/tool.d.ts +36 -29
  156. package/dist/cjs/types/tool.d.ts.map +1 -1
  157. package/dist/cjs/types/tool.js +1 -1
  158. package/dist/cjs/types/tool.js.map +1 -1
  159. package/dist/cjs/utils/condition.d.ts +7 -1
  160. package/dist/cjs/utils/condition.d.ts.map +1 -1
  161. package/dist/cjs/utils/condition.js.map +1 -1
  162. package/dist/cjs/utils/id.d.ts +13 -5
  163. package/dist/cjs/utils/id.d.ts.map +1 -1
  164. package/dist/cjs/utils/id.js +24 -10
  165. package/dist/cjs/utils/id.js.map +1 -1
  166. package/dist/cjs/utils/index.d.ts +2 -2
  167. package/dist/cjs/utils/index.d.ts.map +1 -1
  168. package/dist/cjs/utils/index.js +7 -3
  169. package/dist/cjs/utils/index.js.map +1 -1
  170. package/dist/cjs/utils/session.d.ts +44 -5
  171. package/dist/cjs/utils/session.d.ts.map +1 -1
  172. package/dist/cjs/utils/session.js +197 -38
  173. package/dist/cjs/utils/session.js.map +1 -1
  174. package/dist/constants/index.d.ts +0 -9
  175. package/dist/constants/index.d.ts.map +1 -1
  176. package/dist/constants/index.js +3 -9
  177. package/dist/constants/index.js.map +1 -1
  178. package/dist/core/Agent.d.ts +119 -153
  179. package/dist/core/Agent.d.ts.map +1 -1
  180. package/dist/core/Agent.js +472 -325
  181. package/dist/core/Agent.js.map +1 -1
  182. package/dist/core/AutoChainExecutor.d.ts +107 -0
  183. package/dist/core/AutoChainExecutor.d.ts.map +1 -0
  184. package/dist/core/AutoChainExecutor.js +293 -0
  185. package/dist/core/AutoChainExecutor.js.map +1 -0
  186. package/dist/core/BranchEvaluator.d.ts +54 -0
  187. package/dist/core/BranchEvaluator.d.ts.map +1 -0
  188. package/dist/core/BranchEvaluator.js +126 -0
  189. package/dist/core/BranchEvaluator.js.map +1 -0
  190. package/dist/core/DirectiveBus.d.ts +88 -0
  191. package/dist/core/DirectiveBus.d.ts.map +1 -0
  192. package/dist/core/DirectiveBus.js +192 -0
  193. package/dist/core/DirectiveBus.js.map +1 -0
  194. package/dist/core/DirectiveChainTracker.d.ts +49 -0
  195. package/dist/core/DirectiveChainTracker.d.ts.map +1 -0
  196. package/dist/core/DirectiveChainTracker.js +117 -0
  197. package/dist/core/DirectiveChainTracker.js.map +1 -0
  198. package/dist/core/Flow.d.ts +186 -0
  199. package/dist/core/Flow.d.ts.map +1 -0
  200. package/dist/core/Flow.js +546 -0
  201. package/dist/core/Flow.js.map +1 -0
  202. package/dist/core/FlowRouter.d.ts +182 -0
  203. package/dist/core/FlowRouter.d.ts.map +1 -0
  204. package/dist/core/{RoutingEngine.js → FlowRouter.js} +322 -305
  205. package/dist/core/FlowRouter.js.map +1 -0
  206. package/dist/core/PersistenceManager.d.ts +2 -2
  207. package/dist/core/PersistenceManager.d.ts.map +1 -1
  208. package/dist/core/PersistenceManager.js +7 -7
  209. package/dist/core/PersistenceManager.js.map +1 -1
  210. package/dist/core/PromptComposer.d.ts +21 -8
  211. package/dist/core/PromptComposer.d.ts.map +1 -1
  212. package/dist/core/PromptComposer.js +183 -106
  213. package/dist/core/PromptComposer.js.map +1 -1
  214. package/dist/core/PromptSectionCache.d.ts +1 -1
  215. package/dist/core/PromptSectionCache.js +1 -1
  216. package/dist/core/ResponseEngine.d.ts +18 -8
  217. package/dist/core/ResponseEngine.d.ts.map +1 -1
  218. package/dist/core/ResponseEngine.js +38 -36
  219. package/dist/core/ResponseEngine.js.map +1 -1
  220. package/dist/core/ResponseModal.d.ts +73 -56
  221. package/dist/core/ResponseModal.d.ts.map +1 -1
  222. package/dist/core/ResponseModal.js +1193 -1016
  223. package/dist/core/ResponseModal.js.map +1 -1
  224. package/dist/core/ResponsePipeline.d.ts +124 -26
  225. package/dist/core/ResponsePipeline.d.ts.map +1 -1
  226. package/dist/core/ResponsePipeline.js +509 -137
  227. package/dist/core/ResponsePipeline.js.map +1 -1
  228. package/dist/core/SignalEvaluator.d.ts +86 -0
  229. package/dist/core/SignalEvaluator.d.ts.map +1 -0
  230. package/dist/core/SignalEvaluator.js +326 -0
  231. package/dist/core/SignalEvaluator.js.map +1 -0
  232. package/dist/core/SignalProcessor.d.ts +152 -0
  233. package/dist/core/SignalProcessor.d.ts.map +1 -0
  234. package/dist/core/SignalProcessor.js +555 -0
  235. package/dist/core/SignalProcessor.js.map +1 -0
  236. package/dist/core/Step.d.ts +43 -32
  237. package/dist/core/Step.d.ts.map +1 -1
  238. package/dist/core/Step.js +220 -126
  239. package/dist/core/Step.js.map +1 -1
  240. package/dist/core/StreamingToolExecutor.d.ts +2 -2
  241. package/dist/core/StreamingToolExecutor.d.ts.map +1 -1
  242. package/dist/core/StreamingToolExecutor.js.map +1 -1
  243. package/dist/core/ToolManager.d.ts +44 -13
  244. package/dist/core/ToolManager.d.ts.map +1 -1
  245. package/dist/core/ToolManager.js +174 -91
  246. package/dist/core/ToolManager.js.map +1 -1
  247. package/dist/core/createAgent.d.ts +35 -0
  248. package/dist/core/createAgent.d.ts.map +1 -0
  249. package/dist/core/createAgent.js +36 -0
  250. package/dist/core/createAgent.js.map +1 -0
  251. package/dist/core/flow-namespace.d.ts +49 -0
  252. package/dist/core/flow-namespace.d.ts.map +1 -0
  253. package/dist/core/flow-namespace.js +168 -0
  254. package/dist/core/flow-namespace.js.map +1 -0
  255. package/dist/index.d.ts +11 -14
  256. package/dist/index.d.ts.map +1 -1
  257. package/dist/index.js +9 -12
  258. package/dist/index.js.map +1 -1
  259. package/dist/types/agent.d.ts +183 -54
  260. package/dist/types/agent.d.ts.map +1 -1
  261. package/dist/types/agent.js +0 -6
  262. package/dist/types/agent.js.map +1 -1
  263. package/dist/types/ai.d.ts +3 -3
  264. package/dist/types/ai.d.ts.map +1 -1
  265. package/dist/types/errors.d.ts +15 -0
  266. package/dist/types/errors.d.ts.map +1 -0
  267. package/dist/types/errors.js +18 -0
  268. package/dist/types/errors.js.map +1 -0
  269. package/dist/types/flow.d.ts +513 -0
  270. package/dist/types/flow.d.ts.map +1 -0
  271. package/dist/types/flow.js +5 -0
  272. package/dist/types/flow.js.map +1 -0
  273. package/dist/types/index.d.ts +7 -6
  274. package/dist/types/index.d.ts.map +1 -1
  275. package/dist/types/index.js +4 -1
  276. package/dist/types/index.js.map +1 -1
  277. package/dist/types/persistence.d.ts +11 -7
  278. package/dist/types/persistence.d.ts.map +1 -1
  279. package/dist/types/routing.d.ts +1 -1
  280. package/dist/types/routing.d.ts.map +1 -1
  281. package/dist/types/session.d.ts +24 -23
  282. package/dist/types/session.d.ts.map +1 -1
  283. package/dist/types/signals.d.ts +248 -0
  284. package/dist/types/signals.d.ts.map +1 -0
  285. package/dist/types/signals.js +10 -0
  286. package/dist/types/signals.js.map +1 -0
  287. package/dist/types/template.d.ts +2 -8
  288. package/dist/types/template.d.ts.map +1 -1
  289. package/dist/types/tool.d.ts +36 -29
  290. package/dist/types/tool.d.ts.map +1 -1
  291. package/dist/types/tool.js +1 -1
  292. package/dist/types/tool.js.map +1 -1
  293. package/dist/utils/condition.d.ts +7 -1
  294. package/dist/utils/condition.d.ts.map +1 -1
  295. package/dist/utils/condition.js.map +1 -1
  296. package/dist/utils/id.d.ts +13 -5
  297. package/dist/utils/id.d.ts.map +1 -1
  298. package/dist/utils/id.js +22 -9
  299. package/dist/utils/id.js.map +1 -1
  300. package/dist/utils/index.d.ts +2 -2
  301. package/dist/utils/index.d.ts.map +1 -1
  302. package/dist/utils/index.js +2 -2
  303. package/dist/utils/index.js.map +1 -1
  304. package/dist/utils/session.d.ts +44 -5
  305. package/dist/utils/session.d.ts.map +1 -1
  306. package/dist/utils/session.js +193 -37
  307. package/dist/utils/session.js.map +1 -1
  308. package/docs/README.md +15 -202
  309. package/docs/concepts/architecture.md +281 -0
  310. package/docs/concepts/directives.md +400 -0
  311. package/docs/concepts/pipeline.md +399 -0
  312. package/docs/guides/branching.md +263 -0
  313. package/docs/guides/compaction.md +163 -0
  314. package/docs/guides/conditions.md +167 -0
  315. package/docs/guides/error-handling.md +176 -0
  316. package/docs/guides/flow-control.md +409 -0
  317. package/docs/guides/instructions.md +210 -0
  318. package/docs/guides/persistence.md +182 -0
  319. package/docs/guides/streaming.md +137 -0
  320. package/docs/migration/README.md +15 -0
  321. package/docs/migration/route-to-flow.md +560 -0
  322. package/docs/migration/v1-to-v2.md +909 -0
  323. package/docs/reference/adapters.md +481 -0
  324. package/docs/reference/branches.md +241 -0
  325. package/docs/reference/create-agent.md +186 -0
  326. package/docs/reference/directive.md +243 -0
  327. package/docs/reference/errors.md +122 -0
  328. package/docs/reference/flow.md +238 -0
  329. package/docs/reference/instruction.md +177 -0
  330. package/docs/reference/pre-directive.md +131 -0
  331. package/docs/reference/providers.md +227 -0
  332. package/docs/reference/signals.md +356 -0
  333. package/docs/reference/step.md +339 -0
  334. package/docs/reference/tool.md +269 -0
  335. package/docs/start/01-install.md +81 -0
  336. package/docs/start/02-first-agent.md +196 -0
  337. package/docs/start/03-collect-data.md +222 -0
  338. package/docs/start/04-add-tools.md +276 -0
  339. package/docs/start/05-go-to-production.md +216 -0
  340. package/examples/01-quickstart.ts +20 -0
  341. package/examples/02-data-extraction.ts +90 -0
  342. package/examples/03-tools.ts +136 -0
  343. package/examples/04-instructions.ts +100 -0
  344. package/examples/05-branching.ts +140 -0
  345. package/examples/06-flow-control.ts +103 -0
  346. package/examples/07-streaming.ts +69 -0
  347. package/examples/08-persistence.ts +98 -0
  348. package/examples/09-signals.ts +144 -0
  349. package/examples/tsconfig.json +30 -0
  350. package/package.json +2 -1
  351. package/src/adapters/MemoryAdapter.ts +3 -3
  352. package/src/adapters/MongoAdapter.ts +3 -3
  353. package/src/adapters/OpenSearchAdapter.ts +10 -8
  354. package/src/adapters/PostgreSQLAdapter.ts +26 -10
  355. package/src/adapters/PrismaAdapter.ts +6 -6
  356. package/src/adapters/RedisAdapter.ts +3 -3
  357. package/src/adapters/SQLiteAdapter.ts +31 -12
  358. package/src/constants/index.ts +2 -10
  359. package/src/core/Agent.ts +585 -374
  360. package/src/core/AutoChainExecutor.ts +440 -0
  361. package/src/core/BranchEvaluator.ts +167 -0
  362. package/src/core/DirectiveBus.ts +248 -0
  363. package/src/core/DirectiveChainTracker.ts +144 -0
  364. package/src/core/Flow.ts +666 -0
  365. package/src/core/{RoutingEngine.ts → FlowRouter.ts} +385 -365
  366. package/src/core/PersistenceManager.ts +8 -8
  367. package/src/core/PromptComposer.ts +209 -140
  368. package/src/core/PromptSectionCache.ts +1 -1
  369. package/src/core/ResponseEngine.ts +61 -46
  370. package/src/core/ResponseModal.ts +1453 -1240
  371. package/src/core/ResponsePipeline.ts +655 -175
  372. package/src/core/SignalEvaluator.ts +420 -0
  373. package/src/core/SignalProcessor.ts +723 -0
  374. package/src/core/Step.ts +279 -176
  375. package/src/core/StreamingToolExecutor.ts +4 -4
  376. package/src/core/ToolManager.ts +200 -97
  377. package/src/core/createAgent.ts +40 -0
  378. package/src/core/flow-namespace.ts +219 -0
  379. package/src/index.ts +42 -36
  380. package/src/types/agent.ts +182 -53
  381. package/src/types/ai.ts +3 -3
  382. package/src/types/errors.ts +18 -0
  383. package/src/types/flow.ts +590 -0
  384. package/src/types/index.ts +43 -16
  385. package/src/types/persistence.ts +12 -8
  386. package/src/types/routing.ts +1 -1
  387. package/src/types/session.ts +26 -23
  388. package/src/types/signals.ts +321 -0
  389. package/src/types/template.ts +3 -11
  390. package/src/types/tool.ts +50 -42
  391. package/src/utils/condition.ts +13 -4
  392. package/src/utils/id.ts +27 -9
  393. package/src/utils/index.ts +6 -2
  394. package/src/utils/session.ts +238 -42
  395. package/dist/cjs/core/BatchExecutor.d.ts +0 -359
  396. package/dist/cjs/core/BatchExecutor.d.ts.map +0 -1
  397. package/dist/cjs/core/BatchExecutor.js +0 -861
  398. package/dist/cjs/core/BatchExecutor.js.map +0 -1
  399. package/dist/cjs/core/BatchPromptBuilder.d.ts +0 -89
  400. package/dist/cjs/core/BatchPromptBuilder.d.ts.map +0 -1
  401. package/dist/cjs/core/BatchPromptBuilder.js +0 -223
  402. package/dist/cjs/core/BatchPromptBuilder.js.map +0 -1
  403. package/dist/cjs/core/Route.d.ts +0 -180
  404. package/dist/cjs/core/Route.d.ts.map +0 -1
  405. package/dist/cjs/core/Route.js +0 -542
  406. package/dist/cjs/core/Route.js.map +0 -1
  407. package/dist/cjs/core/RoutingEngine.d.ts +0 -185
  408. package/dist/cjs/core/RoutingEngine.d.ts.map +0 -1
  409. package/dist/cjs/core/RoutingEngine.js.map +0 -1
  410. package/dist/cjs/types/route.d.ts +0 -336
  411. package/dist/cjs/types/route.d.ts.map +0 -1
  412. package/dist/cjs/types/route.js.map +0 -1
  413. package/dist/core/BatchExecutor.d.ts +0 -359
  414. package/dist/core/BatchExecutor.d.ts.map +0 -1
  415. package/dist/core/BatchExecutor.js +0 -856
  416. package/dist/core/BatchExecutor.js.map +0 -1
  417. package/dist/core/BatchPromptBuilder.d.ts +0 -89
  418. package/dist/core/BatchPromptBuilder.d.ts.map +0 -1
  419. package/dist/core/BatchPromptBuilder.js +0 -219
  420. package/dist/core/BatchPromptBuilder.js.map +0 -1
  421. package/dist/core/Route.d.ts +0 -180
  422. package/dist/core/Route.d.ts.map +0 -1
  423. package/dist/core/Route.js +0 -538
  424. package/dist/core/Route.js.map +0 -1
  425. package/dist/core/RoutingEngine.d.ts +0 -185
  426. package/dist/core/RoutingEngine.d.ts.map +0 -1
  427. package/dist/core/RoutingEngine.js.map +0 -1
  428. package/dist/types/route.d.ts +0 -336
  429. package/dist/types/route.d.ts.map +0 -1
  430. package/dist/types/route.js +0 -5
  431. package/dist/types/route.js.map +0 -1
  432. package/docs/CONTRIBUTING.md +0 -521
  433. package/docs/api/README.md +0 -3299
  434. package/docs/api/overview.md +0 -1410
  435. package/docs/architecture/data-extraction-flow.md +0 -360
  436. package/docs/architecture/multi-step-execution.md +0 -277
  437. package/docs/core/agent/README.md +0 -938
  438. package/docs/core/agent/context-management.md +0 -796
  439. package/docs/core/agent/rules-and-prohibitions.md +0 -113
  440. package/docs/core/agent/session-management.md +0 -693
  441. package/docs/core/ai-integration/prompt-composition.md +0 -355
  442. package/docs/core/ai-integration/providers.md +0 -515
  443. package/docs/core/ai-integration/response-processing.md +0 -433
  444. package/docs/core/conversation-flows/data-collection.md +0 -772
  445. package/docs/core/conversation-flows/route-dsl.md +0 -509
  446. package/docs/core/conversation-flows/routes.md +0 -249
  447. package/docs/core/conversation-flows/step-transitions.md +0 -731
  448. package/docs/core/conversation-flows/steps.md +0 -268
  449. package/docs/core/error-handling.md +0 -830
  450. package/docs/core/persistence/adapters.md +0 -255
  451. package/docs/core/persistence/session-storage.md +0 -656
  452. package/docs/core/routing/intelligent-routing.md +0 -470
  453. package/docs/core/tools/enhanced-tool.md +0 -186
  454. package/docs/core/tools/streaming-execution.md +0 -161
  455. package/docs/core/tools/tool-definition.md +0 -970
  456. package/docs/core/tools/tool-scoping.md +0 -819
  457. package/docs/guides/advanced-patterns/publishing.md +0 -186
  458. package/docs/guides/context-compaction.md +0 -96
  459. package/docs/guides/error-handling-patterns.md +0 -578
  460. package/docs/guides/getting-started/README.md +0 -795
  461. package/docs/guides/migration/README.md +0 -101
  462. package/docs/guides/migration/flexible-routing-conditions.md +0 -375
  463. package/docs/guides/migration/multi-step-execution.md +0 -393
  464. package/docs/guides/migration/response-modal-refactor.md +0 -518
  465. package/docs/guides/prompt-optimization.md +0 -164
  466. package/examples/advanced-patterns/context-compaction.ts +0 -223
  467. package/examples/advanced-patterns/knowledge-based-agent.ts +0 -735
  468. package/examples/advanced-patterns/persistent-onboarding.ts +0 -728
  469. package/examples/advanced-patterns/route-lifecycle-hooks.ts +0 -556
  470. package/examples/advanced-patterns/streaming-responses.ts +0 -656
  471. package/examples/ai-providers/anthropic-integration.ts +0 -388
  472. package/examples/ai-providers/openai-integration.ts +0 -228
  473. package/examples/condition-patterns/function-only-conditions.ts +0 -365
  474. package/examples/condition-patterns/mixed-array-conditions.ts +0 -477
  475. package/examples/condition-patterns/route-skipif-patterns.ts +0 -468
  476. package/examples/condition-patterns/step-skipif-patterns.ts +0 -0
  477. package/examples/condition-patterns/string-only-conditions.ts +0 -296
  478. package/examples/conversation-flows/completion-transitions.ts +0 -318
  479. package/examples/core-concepts/basic-agent.ts +0 -503
  480. package/examples/core-concepts/modern-streaming-api.ts +0 -309
  481. package/examples/core-concepts/schema-driven-extraction.ts +0 -332
  482. package/examples/core-concepts/session-management.ts +0 -494
  483. package/examples/integrations/database-integration.ts +0 -631
  484. package/examples/integrations/healthcare-integration.ts +0 -595
  485. package/examples/integrations/search-integration.ts +0 -530
  486. package/examples/integrations/server-session-management.ts +0 -307
  487. package/examples/persistence/custom-adapter.ts +0 -526
  488. package/examples/persistence/database-persistence.ts +0 -583
  489. package/examples/persistence/memory-sessions.ts +0 -495
  490. package/examples/persistence/prisma-schema.example.prisma +0 -74
  491. package/examples/persistence/redis-persistence.ts +0 -488
  492. package/examples/tools/basic-tools.ts +0 -765
  493. package/examples/tools/data-enrichment-tools.ts +0 -593
  494. package/examples/tools/enhanced-tool-metadata.ts +0 -268
  495. package/examples/tools/streaming-tool-execution.ts +0 -283
  496. package/src/core/BatchExecutor.ts +0 -1187
  497. package/src/core/BatchPromptBuilder.ts +0 -299
  498. package/src/core/Route.ts +0 -678
  499. package/src/types/route.ts +0 -392
@@ -0,0 +1,196 @@
1
+ ---
2
+ title: "Your first agent"
3
+ description: "Build a 16-line agent that responds to a user message, and meet the seven primitives that shape every @falai/agent program."
4
+ type: tutorial
5
+ order: 2
6
+ ---
7
+
8
+ # Your first agent
9
+
10
+ You are about to write an agent that fits on one screen. One schema, one flow, one step, one turn — and from it the full mental model unfolds. The framework's seven primitives all participate in this single call, even though only three appear as syntax. The page names all seven so the rest of the tutorial can reference them without introduction.
11
+
12
+ This page builds the smallest agent that does real work — sixteen lines of TypeScript, one `respond` call, one greeting back from the model. The point is not the greeting. The point is to put every primitive of the framework on the page at once, in the smallest possible shape, so the rest of the tutorial extends a scaffold you can already read in full.
13
+
14
+ By the end of this page you will have a runnable file, an expected output, and a working mental map of the [seven primitives](../concepts/architecture.md). The next page extends this same file into a data-collecting agent.
15
+
16
+ Keep [Install](./01-install.md) finished and your `GEMINI_API_KEY` ready in `.env` before you continue.
17
+
18
+ ## The whole agent
19
+
20
+ Drop this into `src/index.ts`:
21
+
22
+ ```typescript
23
+ import { createAgent, GeminiProvider } from "@falai/agent";
24
+
25
+ const agent = createAgent({
26
+ provider: new GeminiProvider({ apiKey: process.env.GEMINI_API_KEY! }),
27
+ schema: { type: "object", properties: { name: { type: "string" } } },
28
+ flows: [{
29
+ title: "Greet",
30
+ requiredFields: ["name"],
31
+ steps: [{ id: "ask_name", prompt: "What's your name?", collect: ["name"] }],
32
+ }],
33
+ });
34
+
35
+ const response = await agent.respond("Hi, I'm Alice");
36
+ console.log(response.message);
37
+ ```
38
+
39
+ That is the whole program. No persistence config, no tools, no branches, no signals. Three primitives appear by name (`Agent`, `Flow`, `Step`) and four more sit one decision away (`Tool`, `Instruction`, `Directive`, `PreDirective`). The next sections walk through every line.
40
+
41
+ ## Walk it line by line
42
+
43
+ ### Imports
44
+
45
+ ```typescript
46
+ import { createAgent, GeminiProvider } from "@falai/agent";
47
+ ```
48
+
49
+ `createAgent` is the level-1 factory — sugar over `new Agent(options)` — and the recommended construction path for application code. Its signature and full options surface live in the [`createAgent` reference](../reference/create-agent.md).
50
+
51
+ `GeminiProvider` is one of four built-in [providers](../reference/providers.md). Swap to `OpenAIProvider`, `AnthropicProvider`, or `OpenRouterProvider` by changing this single import — the agent itself stays vendor-agnostic.
52
+
53
+ ### `createAgent({ ... })`
54
+
55
+ ```typescript
56
+ const agent = createAgent({ /* ... */ });
57
+ ```
58
+
59
+ `createAgent` accepts one options object. Generic inference flows from `schema` through every `flows[].steps[].collect` reference, so the type of `session.data` and tool-handler arguments is derived once and propagates everywhere. Misuse — duplicate flow ids, an unknown key in `collect`, a malformed signal — surfaces as `FlowConfigurationError` synchronously, before any turn runs.
60
+
61
+ ### `provider`
62
+
63
+ ```typescript
64
+ provider: new GeminiProvider({ apiKey: process.env.GEMINI_API_KEY! }),
65
+ ```
66
+
67
+ The provider is the strategy plug between the agent and the model vendor. Every provider implements the same `AiProvider` interface, so the agent talks to Gemini today and to a different vendor tomorrow with one line changed. See [Providers](../reference/providers.md) for the full options surface — `model`, `backupModels`, `config`, `retryConfig`.
68
+
69
+ ### `schema`
70
+
71
+ ```typescript
72
+ schema: { type: "object", properties: { name: { type: "string" } } },
73
+ ```
74
+
75
+ The schema is the single source of truth for `TData` — the typed shape of everything the agent collects across the whole conversation. It lives at the agent level, not the flow level. Every `collect` site in every step references keys defined here, and TypeScript verifies the references at compile time.
76
+
77
+ This shape is why pre-extraction works: when a user message arrives, the engine extracts every collectable field it can in one pass, then skips any step whose `collect` set is already satisfied. The next tutorial page leans on this property hard. For the framing, see [the schema-first principle](../concepts/architecture.md#the-schema-first-principle).
78
+
79
+ ### `flows`
80
+
81
+ ```typescript
82
+ flows: [{
83
+ title: "Greet",
84
+ requiredFields: ["name"],
85
+ steps: [/* ... */],
86
+ }],
87
+ ```
88
+
89
+ A [`Flow`](../reference/flow.md) is one conversational goal — booking a hotel, escalating a complaint, greeting a stranger. The router selects exactly one flow per turn. This agent has only one flow, so the router has nothing to choose between; later tutorials add more.
90
+
91
+ `title` is the human-readable name (also used in the `Directive.goTo` shorthand). `requiredFields` declares which schema keys must be present in `session.data` before the engine fires the flow's completion path. The greeter's only required field is `name`.
92
+
93
+ ### Step `prompt` and `collect`
94
+
95
+ ```typescript
96
+ steps: [{ id: "ask_name", prompt: "What's your name?", collect: ["name"] }],
97
+ ```
98
+
99
+ A [`Step`](../reference/step.md) is a single node inside a flow. This step has the simplest LLM-step shape: an `id` for routing and logs, a `prompt` that becomes the engine's instruction to the model, and a `collect` set that names the schema fields this step is responsible for extracting from the user message.
100
+
101
+ When the user writes `"Hi, I'm Alice"`, the engine routes into `Greet`, lands on `ask_name`, runs pre-extraction against the schema, and lifts `name: "Alice"` into `session.data`. The step's `collect` set is now satisfied — and because `name` is the flow's only `requiredField`, the flow is complete on this very turn.
102
+
103
+ ### `requiredFields`
104
+
105
+ ```typescript
106
+ requiredFields: ["name"],
107
+ ```
108
+
109
+ `requiredFields` is the completion gate. The flow is **done** the moment every key in this array is present in `session.data`. Completion is a state transition, not a message — the framework never speaks on its own. Anything the user reads at completion comes from the model's response on the same turn or from a `reply` step on the next turn.
110
+
111
+ For this agent, completion happens on the first turn. For a longer flow, the gate would force more steps before the model wraps up.
112
+
113
+ ### `agent.respond(message)`
114
+
115
+ ```typescript
116
+ const response = await agent.respond("Hi, I'm Alice");
117
+ console.log(response.message);
118
+ ```
119
+
120
+ `respond(message)` runs one turn end to end: load (or create) the session, route to a flow, extract data, walk auto-step chains, call the LLM, deliver the assistant message, persist. It returns an `AgentResponse` with the fields you usually want on hand:
121
+
122
+ | Field | Type | What it is |
123
+ |-------|------|------------|
124
+ | `message` | `string` | The assistant's reply for this turn. |
125
+ | `session` | `SessionState<TData>` | The updated session — including `session.data` with the extracted fields. |
126
+ | `isFlowComplete` | `boolean` | `true` once `requiredFields` are all satisfied. |
127
+ | `appliedInstructions` | `AppliedInstruction[]` | Instructions that rendered into this turn's prompt (deterministic, not self-reported). |
128
+ | `triggeredSignals` | `SignalFiring[]` | Any signals that fired this turn. |
129
+
130
+ `response.message` is the only field this minimal program reads. The rest become useful as the agent grows.
131
+
132
+ ## The seven primitives
133
+
134
+ Three primitives appear by name in the code above: [`Agent`](../concepts/architecture.md#agent), [`Flow`](../concepts/architecture.md#flow), and [`Step`](../concepts/architecture.md#step). Four more shape every program of any size, and you will meet them in the pages ahead:
135
+
136
+ - [`Agent`](../concepts/architecture.md#agent) — the top-level handle. Owns the schema, provider, flows, tools, signals, and persistence.
137
+ - [`Flow`](../concepts/architecture.md#flow) — one conversational goal. Owns its steps, scoped tools, instructions, and completion semantics.
138
+ - [`Step`](../concepts/architecture.md#step) — one node inside a flow. Asks a question, collects fields, calls tools, runs hooks, or speaks a verbatim line.
139
+ - [`Tool`](../concepts/architecture.md#tool) — a typed function the AI can call. May redirect the conversation by emitting a directive. Added on page [04](./04-add-tools.md).
140
+ - [`Instruction`](../concepts/architecture.md#instruction) — a `must` / `never` / `should` behavioral statement at agent, flow, or step scope.
141
+ - [`Directive`](../concepts/architecture.md#directive) — a flat object any tool, hook, or branch returns to write state, change position, or speak verbatim.
142
+ - [`PreDirective`](../concepts/architecture.md#predirective) — a `Directive` plus per-turn shaping (`appendPrompt`, `injectTools`, `halt`) returned from `onEnter` and `prepare` hooks.
143
+
144
+ Read [Architecture](../concepts/architecture.md) end to end when you want the full mental model — what each primitive owns, how they reference each other, and why the set is exactly seven.
145
+
146
+ ## Run it
147
+
148
+ Make sure `.env` has `GEMINI_API_KEY` set, then run the file:
149
+
150
+ ```bash
151
+ bun run src/index.ts
152
+ ```
153
+
154
+ Or with Node 20+:
155
+
156
+ ```bash
157
+ node --env-file=.env --experimental-strip-types src/index.ts
158
+ ```
159
+
160
+ You should see a single line of greeting prose, something like:
161
+
162
+ ```
163
+ Hi Alice, nice to meet you! How can I help today?
164
+ ```
165
+
166
+ The exact words come from the model — they will not match across runs — but the shape is stable: one assistant message, addressed to Alice by name, written in the tone the model defaults to. If the call fails, double-check that `GEMINI_API_KEY` is exported and that your `.env` is being loaded (Bun loads it automatically; Node needs `--env-file`).
167
+
168
+ ## What just happened
169
+
170
+ In one turn, the engine:
171
+
172
+ 1. Created a fresh session keyed by an auto-generated id (the default `MemoryAdapter` keeps it in process).
173
+ 2. Ran the flow router. With one flow on the agent, `Greet` wins by default.
174
+ 3. Pre-extracted `name: "Alice"` from the user message in a single pass against the schema, before any step ran.
175
+ 4. Skipped `ask_name` because its `collect` set was already satisfied — the engine never re-asks for data it already has.
176
+ 5. Called the LLM once with the active prompt, the typed `session.data`, and the conversation history.
177
+ 6. Returned the assistant message with `isFlowComplete: true` because `requiredFields` were already met.
178
+
179
+ This sequence — pre-extract, then skip-then-execute, then check completion — is the [turn pipeline](../concepts/pipeline.md), and it runs on every `respond` call regardless of flow size.
180
+
181
+ ## When something goes wrong
182
+
183
+ A few common failure modes and where to look:
184
+
185
+ - **`Missing API key`** or a 401 from Gemini — `GEMINI_API_KEY` is unset or your `.env` did not load. Bun loads `.env` automatically; Node needs `--env-file=.env`.
186
+ - **`FlowConfigurationError: collect references unknown key 'foo'`** — the schema does not declare `foo` as a property. Add it to `schema.properties` or fix the `collect` array.
187
+ - **`FlowConfigurationError: duplicate flow id` / `duplicate step id`** — two flows or two steps share the same auto-derived id. Set explicit `id` values to disambiguate.
188
+ - **The LLM call hangs** — check the `model` (Gemini's free tier expects `"models/gemini-2.5-pro"` or `"models/gemini-2.5-flash"`) and your network. Provider errors surface as `ResponseGenerationError`.
189
+
190
+ The full set of typed errors and the `[<ErrorClass>] <what>: <why>. <how to fix>.` format contract live in the [Errors reference](../reference/errors.md).
191
+
192
+ ## Where this leaves you
193
+
194
+ You have a runnable agent, an expected-shape output, and the names of every primitive that will appear in the rest of the tutorial. The next page swaps the trivial `name` schema for a structured booking schema and three steps that each `collect` one field. The same single message — *"I want a hotel in Lisbon for two people next Friday"* — populates all three fields at once and lands the agent on the confirmation step on the first turn.
195
+
196
+ **Next:** [Collect data](./03-collect-data.md)
@@ -0,0 +1,222 @@
1
+ ---
2
+ title: "Collect data"
3
+ description: "Use the agent's schema to extract city, dates, and party size from one message — without asking three questions in a row."
4
+ type: tutorial
5
+ order: 3
6
+ ---
7
+
8
+ # Collect data
9
+
10
+ One schema, three steps, one completion gate. The engine extracts what it can in a single pass, skips steps whose data is already present, and finishes the flow the moment every required field lands. This page shows the pattern end to end — from a user who types everything in one sentence to a user who answers one field at a time.
11
+
12
+ In [Your first agent](./02-first-agent.md), the agent answered a single message. This page extends that scaffold into something more useful: a hotel-booking agent that lifts structured fields out of a user's message and skips any question it already has the answer to.
13
+
14
+ You will define a schema, write three steps that each `collect` one field, gate the confirmation step with `requires`, bypass already-answered steps with `skip`, and seal the flow with `requiredFields`. By the end of the page, a single sentence — *"I want a hotel in Lisbon for two people next Friday"* — will populate every field in one turn and land the agent on the confirmation step before the user types again.
15
+
16
+ Keep the file from the previous tutorial open. Everything here is one continuous edit.
17
+
18
+ ## Define the schema
19
+
20
+ The schema is the single source of truth for everything the agent collects across the whole conversation. It lives at the agent level, not the flow level, and every `collect` site below references keys defined here.
21
+
22
+ Add a `BookingData` type and pass a matching `schema` to `createAgent`:
23
+
24
+ ```typescript
25
+ import { createAgent, GeminiProvider } from "@falai/agent";
26
+
27
+ interface BookingData {
28
+ city: string;
29
+ checkIn: string;
30
+ guests: number;
31
+ }
32
+
33
+ const agent = createAgent<unknown, BookingData>({
34
+ name: "BookingBot",
35
+ provider: new GeminiProvider({ apiKey: process.env.GEMINI_API_KEY! }),
36
+ schema: {
37
+ type: "object",
38
+ properties: {
39
+ city: {
40
+ type: "string",
41
+ description: "Destination city the user wants to stay in.",
42
+ },
43
+ checkIn: {
44
+ type: "string",
45
+ description: "Check-in date as ISO yyyy-mm-dd.",
46
+ },
47
+ guests: {
48
+ type: "integer",
49
+ description: "Number of people staying. Defaults to 1 if not stated.",
50
+ },
51
+ },
52
+ },
53
+ flows: [/* added in the next section */],
54
+ });
55
+ ```
56
+
57
+ The `description` strings inside `properties` are not decoration. The provider sees them on every turn and uses them to extract fields from the user's message. Spend a sentence on each one — it pays back at extraction time. Especially for ambiguous fields (a date format, an ID prefix, a unit), the description is the only place you can tell the extractor what "valid" looks like.
58
+
59
+ Two type parameters flow through `createAgent`: `TContext` (ambient data, ignored here) and `TData` (the booking shape). They propagate to every step's `collect` array and every tool handler. Misspell a key in `collect: ["citi"]` and the type checker objects at the call site.
60
+
61
+ ## Collect one field per step
62
+
63
+ A `Step` declares which schema fields it is responsible for through its `collect` array. The engine reads that array on every turn — if any listed key is already populated in `session.data`, the step is skipped automatically. That is the core of pre-extraction: the engine will not ask a question whose answer it already has.
64
+
65
+ Add a `Booking` flow with three collection steps:
66
+
67
+ ```typescript
68
+ flows: [
69
+ {
70
+ title: "Booking",
71
+ description: "Book a hotel by collecting destination, date, and party size.",
72
+ when: "the user wants to book a hotel",
73
+ requiredFields: ["city", "checkIn", "guests"],
74
+ steps: [
75
+ {
76
+ id: "ask_city",
77
+ prompt: "Find out which city the user wants to stay in.",
78
+ collect: ["city"],
79
+ },
80
+ {
81
+ id: "ask_check_in",
82
+ prompt: "Find out which date the user wants to check in.",
83
+ collect: ["checkIn"],
84
+ requires: ["city"],
85
+ },
86
+ {
87
+ id: "ask_guests",
88
+ prompt: "Find out how many people are travelling.",
89
+ collect: ["guests"],
90
+ requires: ["city", "checkIn"],
91
+ skip: ({ data }) => typeof data.guests === "number",
92
+ },
93
+ {
94
+ id: "confirm",
95
+ prompt:
96
+ "Read back the city, check-in date, and guest count. Ask the user to confirm.",
97
+ requires: ["city", "checkIn", "guests"],
98
+ },
99
+ ],
100
+ },
101
+ ],
102
+ ```
103
+
104
+ Three things deserve a closer look.
105
+
106
+ `collect` is an instruction to the extractor, not a question gate. When the user message contains a city, the extractor populates `city` and the engine moves past `ask_city` whether or not that step ran a prompt. The step exists for the case where the field is still missing on entry — it asks the question that produces the value.
107
+
108
+ `requires` is the prerequisite gate. The engine refuses to enter a step until every key listed in `requires` is present in `session.data`. Without `requires: ["city"]` on `ask_check_in`, a user who messages "next Friday" first would stall the flow — the engine would extract `checkIn`, see no `city`, and have nothing to do.
109
+
110
+ `skip` is the bypass. It accepts a code predicate that runs on every turn; when it returns `true`, the step is skipped regardless of whether its `collect` set is satisfied. The example above demonstrates the pattern but is functionally redundant — the `collect: ["guests"]` already covers the same case. Use `skip` when the bypass condition is *not* about a `collect` field — for example, "skip the verification step if the user is already authenticated."
111
+
112
+ ## Gate completion with `requiredFields`
113
+
114
+ The flow's `requiredFields` is the contract for "this flow is done." When every field listed there is present in `session.data`, the engine fires the flow's completion path on the next turn boundary. Pre-extraction, sequential steps, and one-shot collection all converge on the same gate.
115
+
116
+ The `confirm` step in the snippet above does not collect anything — it only requires. Its job is to read the booking back to the user before the flow completes. This pattern is common: collection steps populate the schema, a final non-collecting step closes the loop.
117
+
118
+ ```typescript
119
+ {
120
+ id: "confirm",
121
+ prompt:
122
+ "Read back the city, check-in date, and guest count. Ask the user to confirm.",
123
+ requires: ["city", "checkIn", "guests"],
124
+ },
125
+ ```
126
+
127
+ The flow ends here implicitly. There is no terminus marker, no end-of-flow constant, no return value — the last step in `steps[]` is the implicit terminus. When `requiredFields` is satisfied, the flow completes; if a flow with no `requiredFields` reaches its last step, the same path runs.
128
+
129
+ A field that the flow can use but does not need belongs in `optionalFields` instead. It is descriptive only — never gates completion, but appears alongside `requiredFields` in re-entry resets if the flow is reentrant. For this tutorial, every field is required, so `optionalFields` stays empty.
130
+
131
+ ## The data fields at a glance
132
+
133
+ Three field-related properties show up in the snippets above. They look similar but answer different questions:
134
+
135
+ | Property | Lives on | Question it answers | Cost |
136
+ |----------|----------|---------------------|------|
137
+ | `schema.properties` | Agent | What can be extracted at all? | One extraction call per turn. |
138
+ | `step.collect` | Step | Which fields does this step want this turn? | Free — engine inspects `session.data`. |
139
+ | `step.requires` | Step | Which fields must already be present to enter this step? | Free — engine inspects `session.data`. |
140
+ | `step.skip` | Step | Should this step be bypassed regardless of `collect`? | Free — code predicate. |
141
+ | `flow.requiredFields` | Flow | When is the flow done? | Free — engine inspects `session.data`. |
142
+
143
+ The pattern is consistent: the schema describes the universe of possible data, every other property describes a slice over that universe. Pre-extraction is what stitches them together — without it, every step would have to ask its question regardless of what the user already said.
144
+
145
+ ## Watch pre-extraction work
146
+
147
+ Run the file with a single message that contains all three fields:
148
+
149
+ ```typescript
150
+ const session = { id: "demo-session" };
151
+
152
+ const response = await agent.respond(
153
+ "I want a hotel in Lisbon for two people next Friday.",
154
+ session,
155
+ );
156
+
157
+ console.log(response.message);
158
+ console.log(response.data);
159
+ console.log(response.currentStep?.id);
160
+ ```
161
+
162
+ The output is roughly:
163
+
164
+ ```
165
+ > Just to confirm: a hotel in Lisbon, checking in 2025-11-21, for 2 guests. Shall I book it?
166
+ { city: "Lisbon", checkIn: "2025-11-21", guests: 2 }
167
+ confirm
168
+ ```
169
+
170
+ Three things happened in one turn:
171
+
172
+ 1. **Pre-extraction ran first.** Before any step prompt or LLM step call, the extractor read the user message against the agent's schema and populated `city`, `checkIn`, and `guests` in `session.data`. The check-in date was normalized to the ISO format the schema described.
173
+ 2. **The first three steps skipped.** `ask_city`, `ask_check_in`, and `ask_guests` each have a `collect` array whose every key was already present after extraction. The engine skipped them in order without calling the LLM for any of them.
174
+ 3. **The engine landed on `confirm`.** Its `requires` were satisfied, its `collect` was empty, and its prompt asked for confirmation. That is the only LLM step that ran for the turn.
175
+
176
+ Try a message with one missing field:
177
+
178
+ ```typescript
179
+ await agent.respond("Book me a hotel in Lisbon next Friday.", session);
180
+ ```
181
+
182
+ The extractor populates `city` and `checkIn`. `ask_city` and `ask_check_in` both skip — their `collect` keys are present. `ask_guests` does *not* skip — `guests` is undefined — so the engine enters it and the assistant asks how many people are travelling.
183
+
184
+ Try the inverse: a message with only one field.
185
+
186
+ ```typescript
187
+ await agent.respond("I'd like to go to Lisbon.", session);
188
+ ```
189
+
190
+ The extractor populates `city` only. `ask_city` skips, `ask_check_in` enters next (its `requires: ["city"]` is satisfied), and the assistant asks for the check-in date. Three turns later, the same `confirm` step runs.
191
+
192
+ The same flow handles every shape of message — one field at a time, three at once, two-then-one — because `collect`, `requires`, and `skip` describe what the step needs rather than how many turns the conversation will take.
193
+
194
+ ### Routing skip
195
+
196
+ One detail worth knowing: when pre-extraction populates a field listed in the *current* step's `collect`, the engine treats that as confirmation that the user is answering this step rather than asking for something new. It skips the flow router entirely for that turn and stays in the active flow. The tradeoff is small — if the user both answers the step and signals new intent in the same message, the new intent is recovered on the next turn. In return, a user who is mid-form does not get bounced into a different flow because their answer happened to share a few words with another flow's `when`.
197
+
198
+ ## Why this works
199
+
200
+ `TData` is agent-level. The schema is declared once and every `collect` site references it; the extractor sees the full schema on every turn and lifts whatever it can in a single pass. Steps then act as filters over `session.data`: a step whose `collect` set is satisfied vanishes from the conversation, and a step whose `requires` set is missing refuses to run.
201
+
202
+ The split between AI work and code work is visible at every site:
203
+
204
+ - **Extraction** (AI): given a user message and the schema, populate as many fields as possible.
205
+ - **Skip / require / completion** (code): given the populated `session.data`, decide whether each step runs, whether the flow continues, and whether `requiredFields` is satisfied.
206
+
207
+ The framework spends one extraction call per turn on the AI side and pure data inspection on the code side. There is no separate "form mode" or "completion check" — the same step shape works whether the user fills the form one field at a time or pastes a full request in a single sentence.
208
+
209
+ ## Recap
210
+
211
+ You added four things to the agent from the previous tutorial:
212
+
213
+ - A typed `BookingData` schema, declared at the agent level.
214
+ - Three collection steps, each with its own `collect` array.
215
+ - A `requires` chain to gate the order in which steps may enter.
216
+ - A `requiredFields` list on the flow to define completion.
217
+
218
+ The pre-extraction property is what makes the rest worthwhile. A user who knows what they want types one sentence; a user who needs guidance types one field at a time; the same flow handles both because every step describes its own contract over `session.data` rather than its position in a conversation.
219
+
220
+ Two things are missing from the booking flow before it can do anything in the real world. There is no booking action — `confirm` ends with the user agreeing, and nothing happens. There is also no way to redirect when something goes wrong (the user is not eligible, the inventory is empty, the date is in the past). The next page adds tools to handle both.
221
+
222
+ **Next:** [Add tools](./04-add-tools.md)