@falai/agent 3.4.5 → 4.0.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (847) hide show
  1. package/README.md +41 -34
  2. package/dist/cjs/core/Agent.d.ts +22 -378
  3. package/dist/cjs/core/Agent.d.ts.map +1 -1
  4. package/dist/cjs/core/Agent.js +104 -1178
  5. package/dist/cjs/core/Agent.js.map +1 -1
  6. package/dist/cjs/core/CompactionEngine.d.ts.map +1 -1
  7. package/dist/cjs/core/CompactionEngine.js +5 -3
  8. package/dist/cjs/core/CompactionEngine.js.map +1 -1
  9. package/dist/cjs/core/FlowSpec.d.ts +136 -0
  10. package/dist/cjs/core/FlowSpec.d.ts.map +1 -0
  11. package/dist/cjs/core/FlowSpec.js +522 -0
  12. package/dist/cjs/core/FlowSpec.js.map +1 -0
  13. package/dist/cjs/core/Migrate.d.ts +38 -0
  14. package/dist/cjs/core/Migrate.d.ts.map +1 -0
  15. package/dist/cjs/core/Migrate.js +270 -0
  16. package/dist/cjs/core/Migrate.js.map +1 -0
  17. package/dist/cjs/core/Prompt.d.ts +54 -0
  18. package/dist/cjs/core/Prompt.d.ts.map +1 -0
  19. package/dist/cjs/core/Prompt.js +143 -0
  20. package/dist/cjs/core/Prompt.js.map +1 -0
  21. package/dist/cjs/core/Runner.d.ts +160 -0
  22. package/dist/cjs/core/Runner.d.ts.map +1 -0
  23. package/dist/cjs/core/Runner.js +1131 -0
  24. package/dist/cjs/core/Runner.js.map +1 -0
  25. package/dist/cjs/core/Speak.d.ts +37 -0
  26. package/dist/cjs/core/Speak.d.ts.map +1 -0
  27. package/dist/cjs/core/Speak.js +364 -0
  28. package/dist/cjs/core/Speak.js.map +1 -0
  29. package/dist/cjs/core/Understand.d.ts +28 -0
  30. package/dist/cjs/core/Understand.d.ts.map +1 -0
  31. package/dist/cjs/core/Understand.js +353 -0
  32. package/dist/cjs/core/Understand.js.map +1 -0
  33. package/dist/cjs/core/contracts.d.ts +122 -0
  34. package/dist/cjs/core/contracts.d.ts.map +1 -0
  35. package/dist/cjs/core/contracts.js +11 -0
  36. package/dist/cjs/core/contracts.js.map +1 -0
  37. package/dist/cjs/core/falai.d.ts +57 -0
  38. package/dist/cjs/core/falai.d.ts.map +1 -0
  39. package/dist/cjs/core/falai.js +43 -0
  40. package/dist/cjs/core/falai.js.map +1 -0
  41. package/dist/cjs/core/predicate.d.ts +9 -0
  42. package/dist/cjs/core/predicate.d.ts.map +1 -0
  43. package/dist/cjs/core/predicate.js +58 -0
  44. package/dist/cjs/core/predicate.js.map +1 -0
  45. package/dist/cjs/index.d.ts +26 -31
  46. package/dist/cjs/index.d.ts.map +1 -1
  47. package/dist/cjs/index.js +46 -68
  48. package/dist/cjs/index.js.map +1 -1
  49. package/dist/cjs/persistence/MemoryStore.d.ts +15 -0
  50. package/dist/cjs/persistence/MemoryStore.d.ts.map +1 -0
  51. package/dist/cjs/persistence/MemoryStore.js +39 -0
  52. package/dist/cjs/persistence/MemoryStore.js.map +1 -0
  53. package/dist/cjs/persistence/MongoStore.d.ts +42 -0
  54. package/dist/cjs/persistence/MongoStore.d.ts.map +1 -0
  55. package/dist/cjs/persistence/MongoStore.js +60 -0
  56. package/dist/cjs/persistence/MongoStore.js.map +1 -0
  57. package/dist/cjs/persistence/OpenSearchStore.d.ts +86 -0
  58. package/dist/cjs/persistence/OpenSearchStore.d.ts.map +1 -0
  59. package/dist/cjs/persistence/OpenSearchStore.js +120 -0
  60. package/dist/cjs/persistence/OpenSearchStore.js.map +1 -0
  61. package/dist/cjs/persistence/PostgresStore.d.ts +41 -0
  62. package/dist/cjs/persistence/PostgresStore.d.ts.map +1 -0
  63. package/dist/cjs/persistence/PostgresStore.js +58 -0
  64. package/dist/cjs/persistence/PostgresStore.js.map +1 -0
  65. package/dist/cjs/persistence/PrismaStore.d.ts +65 -0
  66. package/dist/cjs/persistence/PrismaStore.d.ts.map +1 -0
  67. package/dist/cjs/persistence/PrismaStore.js +95 -0
  68. package/dist/cjs/persistence/PrismaStore.js.map +1 -0
  69. package/dist/cjs/persistence/RedisStore.d.ts +34 -0
  70. package/dist/cjs/persistence/RedisStore.d.ts.map +1 -0
  71. package/dist/cjs/persistence/RedisStore.js +61 -0
  72. package/dist/cjs/persistence/RedisStore.js.map +1 -0
  73. package/dist/cjs/persistence/SQLiteStore.d.ts +45 -0
  74. package/dist/cjs/persistence/SQLiteStore.d.ts.map +1 -0
  75. package/dist/cjs/persistence/SQLiteStore.js +74 -0
  76. package/dist/cjs/persistence/SQLiteStore.js.map +1 -0
  77. package/dist/cjs/persistence/sessionRow.d.ts +14 -0
  78. package/dist/cjs/persistence/sessionRow.d.ts.map +1 -0
  79. package/dist/cjs/persistence/sessionRow.js +50 -0
  80. package/dist/cjs/persistence/sessionRow.js.map +1 -0
  81. package/dist/cjs/providers/DeepSeekProvider.d.ts.map +1 -1
  82. package/dist/cjs/providers/DeepSeekProvider.js +8 -3
  83. package/dist/cjs/providers/DeepSeekProvider.js.map +1 -1
  84. package/dist/cjs/providers/GeminiProvider.d.ts +4 -3
  85. package/dist/cjs/providers/GeminiProvider.d.ts.map +1 -1
  86. package/dist/cjs/providers/GeminiProvider.js +4 -3
  87. package/dist/cjs/providers/GeminiProvider.js.map +1 -1
  88. package/dist/cjs/providers/OpenAICompatibleProvider.d.ts +4 -0
  89. package/dist/cjs/providers/OpenAICompatibleProvider.d.ts.map +1 -1
  90. package/dist/cjs/providers/OpenAICompatibleProvider.js +2 -0
  91. package/dist/cjs/providers/OpenAICompatibleProvider.js.map +1 -1
  92. package/dist/cjs/providers/OpenRouterProvider.d.ts.map +1 -1
  93. package/dist/cjs/providers/OpenRouterProvider.js +2 -4
  94. package/dist/cjs/providers/OpenRouterProvider.js.map +1 -1
  95. package/dist/cjs/providers/ProviderAdapter.d.ts +1 -1
  96. package/dist/cjs/providers/ProviderAdapter.d.ts.map +1 -1
  97. package/dist/cjs/providers/ProviderAdapter.js +33 -10
  98. package/dist/cjs/providers/ProviderAdapter.js.map +1 -1
  99. package/dist/cjs/types/agent.d.ts +153 -383
  100. package/dist/cjs/types/agent.d.ts.map +1 -1
  101. package/dist/cjs/types/agent.js +1 -1
  102. package/dist/cjs/types/ai.d.ts +32 -1
  103. package/dist/cjs/types/ai.d.ts.map +1 -1
  104. package/dist/cjs/types/compaction.d.ts +3 -1
  105. package/dist/cjs/types/compaction.d.ts.map +1 -1
  106. package/dist/cjs/types/errors.d.ts +9 -12
  107. package/dist/cjs/types/errors.d.ts.map +1 -1
  108. package/dist/cjs/types/errors.js +14 -17
  109. package/dist/cjs/types/errors.js.map +1 -1
  110. package/dist/cjs/types/flow.d.ts +265 -513
  111. package/dist/cjs/types/flow.d.ts.map +1 -1
  112. package/dist/cjs/types/flow.js +7 -1
  113. package/dist/cjs/types/flow.js.map +1 -1
  114. package/dist/cjs/types/history.d.ts +7 -18
  115. package/dist/cjs/types/history.d.ts.map +1 -1
  116. package/dist/cjs/types/history.js.map +1 -1
  117. package/dist/cjs/types/index.d.ts +9 -15
  118. package/dist/cjs/types/index.d.ts.map +1 -1
  119. package/dist/cjs/types/index.js +4 -14
  120. package/dist/cjs/types/index.js.map +1 -1
  121. package/dist/cjs/types/session.d.ts +94 -64
  122. package/dist/cjs/types/session.d.ts.map +1 -1
  123. package/dist/cjs/types/session.js +5 -1
  124. package/dist/cjs/types/session.js.map +1 -1
  125. package/dist/cjs/types/tool.d.ts +37 -207
  126. package/dist/cjs/types/tool.d.ts.map +1 -1
  127. package/dist/cjs/types/tool.js +5 -14
  128. package/dist/cjs/types/tool.js.map +1 -1
  129. package/dist/cjs/utils/clock.d.ts +28 -0
  130. package/dist/cjs/utils/clock.d.ts.map +1 -0
  131. package/dist/cjs/utils/clock.js +64 -0
  132. package/dist/cjs/utils/clock.js.map +1 -0
  133. package/dist/cjs/utils/duration.d.ts +11 -0
  134. package/dist/cjs/utils/duration.d.ts.map +1 -0
  135. package/dist/cjs/utils/duration.js +31 -0
  136. package/dist/cjs/utils/duration.js.map +1 -0
  137. package/dist/cjs/utils/history.d.ts +4 -1
  138. package/dist/cjs/utils/history.d.ts.map +1 -1
  139. package/dist/cjs/utils/history.js +2 -2
  140. package/dist/cjs/utils/history.js.map +1 -1
  141. package/dist/cjs/utils/index.d.ts +4 -10
  142. package/dist/cjs/utils/index.d.ts.map +1 -1
  143. package/dist/cjs/utils/index.js +14 -61
  144. package/dist/cjs/utils/index.js.map +1 -1
  145. package/dist/cjs/utils/json.d.ts +2 -0
  146. package/dist/cjs/utils/json.d.ts.map +1 -1
  147. package/dist/cjs/utils/json.js +5 -0
  148. package/dist/cjs/utils/json.js.map +1 -1
  149. package/dist/cjs/utils/outcomes.d.ts +48 -0
  150. package/dist/cjs/utils/outcomes.d.ts.map +1 -0
  151. package/dist/cjs/utils/outcomes.js +51 -0
  152. package/dist/cjs/utils/outcomes.js.map +1 -0
  153. package/dist/cjs/utils/schema.d.ts +50 -0
  154. package/dist/cjs/utils/schema.d.ts.map +1 -0
  155. package/dist/cjs/utils/schema.js +138 -0
  156. package/dist/cjs/utils/schema.js.map +1 -0
  157. package/dist/cjs/utils/streamingMessage.d.ts +3 -2
  158. package/dist/cjs/utils/streamingMessage.d.ts.map +1 -1
  159. package/dist/cjs/utils/streamingMessage.js +38 -4
  160. package/dist/cjs/utils/streamingMessage.js.map +1 -1
  161. package/dist/cjs/utils/template.d.ts +13 -149
  162. package/dist/cjs/utils/template.d.ts.map +1 -1
  163. package/dist/cjs/utils/template.js +31 -363
  164. package/dist/cjs/utils/template.js.map +1 -1
  165. package/dist/cjs/utils/usage.d.ts +19 -0
  166. package/dist/cjs/utils/usage.d.ts.map +1 -0
  167. package/dist/cjs/utils/usage.js +35 -0
  168. package/dist/cjs/utils/usage.js.map +1 -0
  169. package/dist/core/Agent.d.ts +22 -378
  170. package/dist/core/Agent.d.ts.map +1 -1
  171. package/dist/core/Agent.js +107 -1181
  172. package/dist/core/Agent.js.map +1 -1
  173. package/dist/core/CompactionEngine.d.ts.map +1 -1
  174. package/dist/core/CompactionEngine.js +5 -3
  175. package/dist/core/CompactionEngine.js.map +1 -1
  176. package/dist/core/FlowSpec.d.ts +136 -0
  177. package/dist/core/FlowSpec.d.ts.map +1 -0
  178. package/dist/core/FlowSpec.js +516 -0
  179. package/dist/core/FlowSpec.js.map +1 -0
  180. package/dist/core/Migrate.d.ts +38 -0
  181. package/dist/core/Migrate.d.ts.map +1 -0
  182. package/dist/core/Migrate.js +264 -0
  183. package/dist/core/Migrate.js.map +1 -0
  184. package/dist/core/Prompt.d.ts +54 -0
  185. package/dist/core/Prompt.d.ts.map +1 -0
  186. package/dist/core/Prompt.js +133 -0
  187. package/dist/core/Prompt.js.map +1 -0
  188. package/dist/core/Runner.d.ts +160 -0
  189. package/dist/core/Runner.d.ts.map +1 -0
  190. package/dist/core/Runner.js +1127 -0
  191. package/dist/core/Runner.js.map +1 -0
  192. package/dist/core/Speak.d.ts +37 -0
  193. package/dist/core/Speak.d.ts.map +1 -0
  194. package/dist/core/Speak.js +360 -0
  195. package/dist/core/Speak.js.map +1 -0
  196. package/dist/core/Understand.d.ts +28 -0
  197. package/dist/core/Understand.d.ts.map +1 -0
  198. package/dist/core/Understand.js +349 -0
  199. package/dist/core/Understand.js.map +1 -0
  200. package/dist/core/contracts.d.ts +122 -0
  201. package/dist/core/contracts.d.ts.map +1 -0
  202. package/dist/core/contracts.js +10 -0
  203. package/dist/core/contracts.js.map +1 -0
  204. package/dist/core/falai.d.ts +57 -0
  205. package/dist/core/falai.d.ts.map +1 -0
  206. package/dist/core/falai.js +40 -0
  207. package/dist/core/falai.js.map +1 -0
  208. package/dist/core/predicate.d.ts +9 -0
  209. package/dist/core/predicate.d.ts.map +1 -0
  210. package/dist/core/predicate.js +54 -0
  211. package/dist/core/predicate.js.map +1 -0
  212. package/dist/index.d.ts +26 -31
  213. package/dist/index.d.ts.map +1 -1
  214. package/dist/index.js +19 -24
  215. package/dist/index.js.map +1 -1
  216. package/dist/persistence/MemoryStore.d.ts +15 -0
  217. package/dist/persistence/MemoryStore.d.ts.map +1 -0
  218. package/dist/persistence/MemoryStore.js +35 -0
  219. package/dist/persistence/MemoryStore.js.map +1 -0
  220. package/dist/persistence/MongoStore.d.ts +42 -0
  221. package/dist/persistence/MongoStore.d.ts.map +1 -0
  222. package/dist/persistence/MongoStore.js +56 -0
  223. package/dist/persistence/MongoStore.js.map +1 -0
  224. package/dist/persistence/OpenSearchStore.d.ts +86 -0
  225. package/dist/persistence/OpenSearchStore.d.ts.map +1 -0
  226. package/dist/persistence/OpenSearchStore.js +116 -0
  227. package/dist/persistence/OpenSearchStore.js.map +1 -0
  228. package/dist/persistence/PostgresStore.d.ts +41 -0
  229. package/dist/persistence/PostgresStore.d.ts.map +1 -0
  230. package/dist/persistence/PostgresStore.js +54 -0
  231. package/dist/persistence/PostgresStore.js.map +1 -0
  232. package/dist/persistence/PrismaStore.d.ts +65 -0
  233. package/dist/persistence/PrismaStore.d.ts.map +1 -0
  234. package/dist/persistence/PrismaStore.js +91 -0
  235. package/dist/persistence/PrismaStore.js.map +1 -0
  236. package/dist/persistence/RedisStore.d.ts +34 -0
  237. package/dist/persistence/RedisStore.d.ts.map +1 -0
  238. package/dist/persistence/RedisStore.js +57 -0
  239. package/dist/persistence/RedisStore.js.map +1 -0
  240. package/dist/persistence/SQLiteStore.d.ts +45 -0
  241. package/dist/persistence/SQLiteStore.d.ts.map +1 -0
  242. package/dist/persistence/SQLiteStore.js +70 -0
  243. package/dist/persistence/SQLiteStore.js.map +1 -0
  244. package/dist/persistence/sessionRow.d.ts +14 -0
  245. package/dist/persistence/sessionRow.d.ts.map +1 -0
  246. package/dist/persistence/sessionRow.js +45 -0
  247. package/dist/persistence/sessionRow.js.map +1 -0
  248. package/dist/providers/DeepSeekProvider.d.ts.map +1 -1
  249. package/dist/providers/DeepSeekProvider.js +8 -3
  250. package/dist/providers/DeepSeekProvider.js.map +1 -1
  251. package/dist/providers/GeminiProvider.d.ts +4 -3
  252. package/dist/providers/GeminiProvider.d.ts.map +1 -1
  253. package/dist/providers/GeminiProvider.js +4 -3
  254. package/dist/providers/GeminiProvider.js.map +1 -1
  255. package/dist/providers/OpenAICompatibleProvider.d.ts +4 -0
  256. package/dist/providers/OpenAICompatibleProvider.d.ts.map +1 -1
  257. package/dist/providers/OpenAICompatibleProvider.js +2 -0
  258. package/dist/providers/OpenAICompatibleProvider.js.map +1 -1
  259. package/dist/providers/OpenRouterProvider.d.ts.map +1 -1
  260. package/dist/providers/OpenRouterProvider.js +2 -4
  261. package/dist/providers/OpenRouterProvider.js.map +1 -1
  262. package/dist/providers/ProviderAdapter.d.ts +1 -1
  263. package/dist/providers/ProviderAdapter.d.ts.map +1 -1
  264. package/dist/providers/ProviderAdapter.js +34 -11
  265. package/dist/providers/ProviderAdapter.js.map +1 -1
  266. package/dist/types/agent.d.ts +153 -383
  267. package/dist/types/agent.d.ts.map +1 -1
  268. package/dist/types/agent.js +1 -1
  269. package/dist/types/ai.d.ts +32 -1
  270. package/dist/types/ai.d.ts.map +1 -1
  271. package/dist/types/compaction.d.ts +3 -1
  272. package/dist/types/compaction.d.ts.map +1 -1
  273. package/dist/types/errors.d.ts +9 -12
  274. package/dist/types/errors.d.ts.map +1 -1
  275. package/dist/types/errors.js +12 -15
  276. package/dist/types/errors.js.map +1 -1
  277. package/dist/types/flow.d.ts +265 -513
  278. package/dist/types/flow.d.ts.map +1 -1
  279. package/dist/types/flow.js +7 -1
  280. package/dist/types/flow.js.map +1 -1
  281. package/dist/types/history.d.ts +7 -18
  282. package/dist/types/history.d.ts.map +1 -1
  283. package/dist/types/history.js.map +1 -1
  284. package/dist/types/index.d.ts +9 -15
  285. package/dist/types/index.d.ts.map +1 -1
  286. package/dist/types/index.js +2 -7
  287. package/dist/types/index.js.map +1 -1
  288. package/dist/types/session.d.ts +94 -64
  289. package/dist/types/session.d.ts.map +1 -1
  290. package/dist/types/session.js +5 -1
  291. package/dist/types/session.js.map +1 -1
  292. package/dist/types/tool.d.ts +37 -207
  293. package/dist/types/tool.d.ts.map +1 -1
  294. package/dist/types/tool.js +6 -13
  295. package/dist/types/tool.js.map +1 -1
  296. package/dist/utils/clock.d.ts +28 -0
  297. package/dist/utils/clock.d.ts.map +1 -0
  298. package/dist/utils/clock.js +59 -0
  299. package/dist/utils/clock.js.map +1 -0
  300. package/dist/utils/duration.d.ts +11 -0
  301. package/dist/utils/duration.d.ts.map +1 -0
  302. package/dist/utils/duration.js +26 -0
  303. package/dist/utils/duration.js.map +1 -0
  304. package/dist/utils/history.d.ts +4 -1
  305. package/dist/utils/history.d.ts.map +1 -1
  306. package/dist/utils/history.js +2 -2
  307. package/dist/utils/history.js.map +1 -1
  308. package/dist/utils/index.d.ts +4 -10
  309. package/dist/utils/index.d.ts.map +1 -1
  310. package/dist/utils/index.js +4 -21
  311. package/dist/utils/index.js.map +1 -1
  312. package/dist/utils/json.d.ts +2 -0
  313. package/dist/utils/json.d.ts.map +1 -1
  314. package/dist/utils/json.js +4 -0
  315. package/dist/utils/json.js.map +1 -1
  316. package/dist/utils/outcomes.d.ts +48 -0
  317. package/dist/utils/outcomes.d.ts.map +1 -0
  318. package/dist/utils/outcomes.js +48 -0
  319. package/dist/utils/outcomes.js.map +1 -0
  320. package/dist/utils/schema.d.ts +50 -0
  321. package/dist/utils/schema.d.ts.map +1 -0
  322. package/dist/utils/schema.js +129 -0
  323. package/dist/utils/schema.js.map +1 -0
  324. package/dist/utils/streamingMessage.d.ts +3 -2
  325. package/dist/utils/streamingMessage.d.ts.map +1 -1
  326. package/dist/utils/streamingMessage.js +38 -4
  327. package/dist/utils/streamingMessage.js.map +1 -1
  328. package/dist/utils/template.d.ts +13 -149
  329. package/dist/utils/template.d.ts.map +1 -1
  330. package/dist/utils/template.js +28 -355
  331. package/dist/utils/template.js.map +1 -1
  332. package/dist/utils/usage.d.ts +19 -0
  333. package/dist/utils/usage.d.ts.map +1 -0
  334. package/dist/utils/usage.js +31 -0
  335. package/dist/utils/usage.js.map +1 -0
  336. package/docs/README.md +37 -19
  337. package/docs/concepts/architecture.md +117 -239
  338. package/docs/concepts/collection.md +170 -0
  339. package/docs/concepts/pipeline.md +132 -378
  340. package/docs/concepts/runs-and-waits.md +192 -0
  341. package/docs/guides/actions-and-events.md +276 -0
  342. package/docs/guides/branching.md +119 -208
  343. package/docs/guides/compaction.md +63 -158
  344. package/docs/guides/conditions.md +164 -128
  345. package/docs/guides/error-handling.md +168 -164
  346. package/docs/guides/flow-control.md +210 -349
  347. package/docs/guides/flows-from-json.md +224 -0
  348. package/docs/guides/instructions.md +125 -161
  349. package/docs/guides/persistence.md +182 -206
  350. package/docs/guides/streaming.md +50 -114
  351. package/docs/guides/testing.md +284 -0
  352. package/docs/guides/triggers.md +401 -0
  353. package/docs/migration/README.md +8 -15
  354. package/docs/migration/v1-to-v2.md +1 -1
  355. package/docs/migration/v2-3-to-v2-4.md +2 -2
  356. package/docs/migration/v2-6-to-v2-7.md +4 -4
  357. package/docs/migration/v3-to-v4.md +452 -0
  358. package/docs/reference/actions-events-conditions.md +396 -0
  359. package/docs/reference/agent.md +244 -0
  360. package/docs/reference/branches.md +75 -203
  361. package/docs/reference/errors.md +188 -144
  362. package/docs/reference/fields.md +125 -0
  363. package/docs/reference/flow-spec.md +248 -0
  364. package/docs/reference/flow.md +104 -192
  365. package/docs/reference/instruction.md +83 -137
  366. package/docs/reference/outcomes.md +273 -0
  367. package/docs/reference/providers.md +525 -302
  368. package/docs/reference/session.md +210 -0
  369. package/docs/reference/step.md +194 -312
  370. package/docs/reference/stores.md +496 -0
  371. package/docs/reference/tool.md +162 -231
  372. package/docs/reference/trigger.md +180 -0
  373. package/docs/rfc/v4-one-flow.md +477 -0
  374. package/docs/start/01-install.md +59 -44
  375. package/docs/start/02-first-agent.md +97 -147
  376. package/docs/start/03-collect-data.md +78 -183
  377. package/docs/start/04-add-tools.md +159 -227
  378. package/docs/start/05-go-to-production.md +167 -164
  379. package/examples/01-quickstart.ts +26 -16
  380. package/examples/02-fields.ts +75 -0
  381. package/examples/03-tools.ts +79 -119
  382. package/examples/04-instructions.ts +60 -87
  383. package/examples/05-branches.ts +78 -0
  384. package/examples/06-triggers-and-waits.ts +148 -0
  385. package/examples/07-streaming.ts +34 -60
  386. package/examples/08-store-and-migration.ts +97 -0
  387. package/examples/09-flows-from-json.ts +107 -0
  388. package/package.json +9 -6
  389. package/src/core/Agent.ts +116 -1512
  390. package/src/core/CompactionEngine.ts +7 -4
  391. package/src/core/FlowSpec.ts +712 -0
  392. package/src/core/Migrate.ts +256 -0
  393. package/src/core/Prompt.ts +156 -0
  394. package/src/core/Runner.ts +1181 -0
  395. package/src/core/Speak.ts +451 -0
  396. package/src/core/Understand.ts +422 -0
  397. package/src/core/contracts.ts +111 -0
  398. package/src/core/falai.ts +86 -0
  399. package/src/core/predicate.ts +56 -0
  400. package/src/index.ts +119 -147
  401. package/src/persistence/MemoryStore.ts +37 -0
  402. package/src/persistence/MongoStore.ts +89 -0
  403. package/src/persistence/OpenSearchStore.ts +153 -0
  404. package/src/persistence/PostgresStore.ts +89 -0
  405. package/src/persistence/PrismaStore.ts +127 -0
  406. package/src/persistence/RedisStore.ts +90 -0
  407. package/src/persistence/SQLiteStore.ts +103 -0
  408. package/src/persistence/sessionRow.ts +45 -0
  409. package/src/providers/DeepSeekProvider.ts +8 -3
  410. package/src/providers/GeminiProvider.ts +4 -3
  411. package/src/providers/OpenAICompatibleProvider.ts +6 -0
  412. package/src/providers/OpenRouterProvider.ts +2 -4
  413. package/src/providers/ProviderAdapter.ts +36 -8
  414. package/src/types/agent.ts +124 -397
  415. package/src/types/ai.ts +33 -1
  416. package/src/types/compaction.ts +3 -1
  417. package/src/types/errors.ts +13 -16
  418. package/src/types/flow.ts +249 -550
  419. package/src/types/history.ts +7 -20
  420. package/src/types/index.ts +87 -139
  421. package/src/types/session.ts +135 -70
  422. package/src/types/tool.ts +42 -267
  423. package/src/utils/clock.ts +70 -0
  424. package/src/utils/duration.ts +33 -0
  425. package/src/utils/history.ts +3 -2
  426. package/src/utils/index.ts +8 -66
  427. package/src/utils/json.ts +5 -0
  428. package/src/utils/outcomes.ts +56 -0
  429. package/src/utils/schema.ts +145 -0
  430. package/src/utils/streamingMessage.ts +34 -4
  431. package/src/utils/template.ts +32 -423
  432. package/src/utils/usage.ts +37 -0
  433. package/dist/adapters/MemoryAdapter.d.ts +0 -47
  434. package/dist/adapters/MemoryAdapter.d.ts.map +0 -1
  435. package/dist/adapters/MemoryAdapter.js +0 -204
  436. package/dist/adapters/MemoryAdapter.js.map +0 -1
  437. package/dist/adapters/MongoAdapter.d.ts +0 -97
  438. package/dist/adapters/MongoAdapter.d.ts.map +0 -1
  439. package/dist/adapters/MongoAdapter.js +0 -196
  440. package/dist/adapters/MongoAdapter.js.map +0 -1
  441. package/dist/adapters/OpenSearchAdapter.d.ts +0 -169
  442. package/dist/adapters/OpenSearchAdapter.d.ts.map +0 -1
  443. package/dist/adapters/OpenSearchAdapter.js +0 -471
  444. package/dist/adapters/OpenSearchAdapter.js.map +0 -1
  445. package/dist/adapters/PostgreSQLAdapter.d.ts +0 -85
  446. package/dist/adapters/PostgreSQLAdapter.d.ts.map +0 -1
  447. package/dist/adapters/PostgreSQLAdapter.js +0 -308
  448. package/dist/adapters/PostgreSQLAdapter.js.map +0 -1
  449. package/dist/adapters/PrismaAdapter.d.ts +0 -115
  450. package/dist/adapters/PrismaAdapter.d.ts.map +0 -1
  451. package/dist/adapters/PrismaAdapter.js +0 -406
  452. package/dist/adapters/PrismaAdapter.js.map +0 -1
  453. package/dist/adapters/RedisAdapter.d.ts +0 -72
  454. package/dist/adapters/RedisAdapter.d.ts.map +0 -1
  455. package/dist/adapters/RedisAdapter.js +0 -286
  456. package/dist/adapters/RedisAdapter.js.map +0 -1
  457. package/dist/adapters/SQLiteAdapter.d.ts +0 -86
  458. package/dist/adapters/SQLiteAdapter.d.ts.map +0 -1
  459. package/dist/adapters/SQLiteAdapter.js +0 -337
  460. package/dist/adapters/SQLiteAdapter.js.map +0 -1
  461. package/dist/adapters/index.d.ts +0 -17
  462. package/dist/adapters/index.d.ts.map +0 -1
  463. package/dist/adapters/index.js +0 -11
  464. package/dist/adapters/index.js.map +0 -1
  465. package/dist/adapters/sessionRow.d.ts +0 -22
  466. package/dist/adapters/sessionRow.d.ts.map +0 -1
  467. package/dist/adapters/sessionRow.js +0 -48
  468. package/dist/adapters/sessionRow.js.map +0 -1
  469. package/dist/cjs/adapters/MemoryAdapter.d.ts +0 -47
  470. package/dist/cjs/adapters/MemoryAdapter.d.ts.map +0 -1
  471. package/dist/cjs/adapters/MemoryAdapter.js +0 -208
  472. package/dist/cjs/adapters/MemoryAdapter.js.map +0 -1
  473. package/dist/cjs/adapters/MongoAdapter.d.ts +0 -97
  474. package/dist/cjs/adapters/MongoAdapter.d.ts.map +0 -1
  475. package/dist/cjs/adapters/MongoAdapter.js +0 -200
  476. package/dist/cjs/adapters/MongoAdapter.js.map +0 -1
  477. package/dist/cjs/adapters/OpenSearchAdapter.d.ts +0 -169
  478. package/dist/cjs/adapters/OpenSearchAdapter.d.ts.map +0 -1
  479. package/dist/cjs/adapters/OpenSearchAdapter.js +0 -475
  480. package/dist/cjs/adapters/OpenSearchAdapter.js.map +0 -1
  481. package/dist/cjs/adapters/PostgreSQLAdapter.d.ts +0 -85
  482. package/dist/cjs/adapters/PostgreSQLAdapter.d.ts.map +0 -1
  483. package/dist/cjs/adapters/PostgreSQLAdapter.js +0 -312
  484. package/dist/cjs/adapters/PostgreSQLAdapter.js.map +0 -1
  485. package/dist/cjs/adapters/PrismaAdapter.d.ts +0 -115
  486. package/dist/cjs/adapters/PrismaAdapter.d.ts.map +0 -1
  487. package/dist/cjs/adapters/PrismaAdapter.js +0 -410
  488. package/dist/cjs/adapters/PrismaAdapter.js.map +0 -1
  489. package/dist/cjs/adapters/RedisAdapter.d.ts +0 -72
  490. package/dist/cjs/adapters/RedisAdapter.d.ts.map +0 -1
  491. package/dist/cjs/adapters/RedisAdapter.js +0 -290
  492. package/dist/cjs/adapters/RedisAdapter.js.map +0 -1
  493. package/dist/cjs/adapters/SQLiteAdapter.d.ts +0 -86
  494. package/dist/cjs/adapters/SQLiteAdapter.d.ts.map +0 -1
  495. package/dist/cjs/adapters/SQLiteAdapter.js +0 -341
  496. package/dist/cjs/adapters/SQLiteAdapter.js.map +0 -1
  497. package/dist/cjs/adapters/index.d.ts +0 -17
  498. package/dist/cjs/adapters/index.d.ts.map +0 -1
  499. package/dist/cjs/adapters/index.js +0 -21
  500. package/dist/cjs/adapters/index.js.map +0 -1
  501. package/dist/cjs/adapters/sessionRow.d.ts +0 -22
  502. package/dist/cjs/adapters/sessionRow.d.ts.map +0 -1
  503. package/dist/cjs/adapters/sessionRow.js +0 -52
  504. package/dist/cjs/adapters/sessionRow.js.map +0 -1
  505. package/dist/cjs/constants/index.d.ts +0 -1
  506. package/dist/cjs/constants/index.d.ts.map +0 -1
  507. package/dist/cjs/constants/index.js +0 -4
  508. package/dist/cjs/constants/index.js.map +0 -1
  509. package/dist/cjs/core/AutoChainExecutor.d.ts +0 -97
  510. package/dist/cjs/core/AutoChainExecutor.d.ts.map +0 -1
  511. package/dist/cjs/core/AutoChainExecutor.js +0 -288
  512. package/dist/cjs/core/AutoChainExecutor.js.map +0 -1
  513. package/dist/cjs/core/BranchEvaluator.d.ts +0 -55
  514. package/dist/cjs/core/BranchEvaluator.d.ts.map +0 -1
  515. package/dist/cjs/core/BranchEvaluator.js +0 -125
  516. package/dist/cjs/core/BranchEvaluator.js.map +0 -1
  517. package/dist/cjs/core/DirectiveChainTracker.d.ts +0 -49
  518. package/dist/cjs/core/DirectiveChainTracker.d.ts.map +0 -1
  519. package/dist/cjs/core/DirectiveChainTracker.js +0 -121
  520. package/dist/cjs/core/DirectiveChainTracker.js.map +0 -1
  521. package/dist/cjs/core/Events.d.ts +0 -26
  522. package/dist/cjs/core/Events.d.ts.map +0 -1
  523. package/dist/cjs/core/Events.js +0 -144
  524. package/dist/cjs/core/Events.js.map +0 -1
  525. package/dist/cjs/core/Flow.d.ts +0 -183
  526. package/dist/cjs/core/Flow.d.ts.map +0 -1
  527. package/dist/cjs/core/Flow.js +0 -551
  528. package/dist/cjs/core/Flow.js.map +0 -1
  529. package/dist/cjs/core/FlowRouter.d.ts +0 -183
  530. package/dist/cjs/core/FlowRouter.d.ts.map +0 -1
  531. package/dist/cjs/core/FlowRouter.js +0 -1047
  532. package/dist/cjs/core/FlowRouter.js.map +0 -1
  533. package/dist/cjs/core/PersistenceManager.d.ts +0 -114
  534. package/dist/cjs/core/PersistenceManager.d.ts.map +0 -1
  535. package/dist/cjs/core/PersistenceManager.js +0 -336
  536. package/dist/cjs/core/PersistenceManager.js.map +0 -1
  537. package/dist/cjs/core/PromptComposer.d.ts +0 -47
  538. package/dist/cjs/core/PromptComposer.d.ts.map +0 -1
  539. package/dist/cjs/core/PromptComposer.js +0 -397
  540. package/dist/cjs/core/PromptComposer.js.map +0 -1
  541. package/dist/cjs/core/PromptSectionCache.d.ts +0 -48
  542. package/dist/cjs/core/PromptSectionCache.d.ts.map +0 -1
  543. package/dist/cjs/core/PromptSectionCache.js +0 -108
  544. package/dist/cjs/core/PromptSectionCache.js.map +0 -1
  545. package/dist/cjs/core/ResponseEngine.d.ts +0 -43
  546. package/dist/cjs/core/ResponseEngine.d.ts.map +0 -1
  547. package/dist/cjs/core/ResponseEngine.js +0 -235
  548. package/dist/cjs/core/ResponseEngine.js.map +0 -1
  549. package/dist/cjs/core/ResponseGenerationError.d.ts +0 -30
  550. package/dist/cjs/core/ResponseGenerationError.d.ts.map +0 -1
  551. package/dist/cjs/core/ResponseGenerationError.js +0 -35
  552. package/dist/cjs/core/ResponseGenerationError.js.map +0 -1
  553. package/dist/cjs/core/ResponseModal.d.ts +0 -305
  554. package/dist/cjs/core/ResponseModal.d.ts.map +0 -1
  555. package/dist/cjs/core/ResponseModal.js +0 -1414
  556. package/dist/cjs/core/ResponseModal.js.map +0 -1
  557. package/dist/cjs/core/ResponsePipeline.d.ts +0 -220
  558. package/dist/cjs/core/ResponsePipeline.d.ts.map +0 -1
  559. package/dist/cjs/core/ResponsePipeline.js +0 -1040
  560. package/dist/cjs/core/ResponsePipeline.js.map +0 -1
  561. package/dist/cjs/core/SessionFinalizer.d.ts +0 -34
  562. package/dist/cjs/core/SessionFinalizer.d.ts.map +0 -1
  563. package/dist/cjs/core/SessionFinalizer.js +0 -88
  564. package/dist/cjs/core/SessionFinalizer.js.map +0 -1
  565. package/dist/cjs/core/SessionManager.d.ts +0 -112
  566. package/dist/cjs/core/SessionManager.d.ts.map +0 -1
  567. package/dist/cjs/core/SessionManager.js +0 -308
  568. package/dist/cjs/core/SessionManager.js.map +0 -1
  569. package/dist/cjs/core/SignalCoordinator.d.ts +0 -103
  570. package/dist/cjs/core/SignalCoordinator.d.ts.map +0 -1
  571. package/dist/cjs/core/SignalCoordinator.js +0 -207
  572. package/dist/cjs/core/SignalCoordinator.js.map +0 -1
  573. package/dist/cjs/core/SignalEvaluator.d.ts +0 -86
  574. package/dist/cjs/core/SignalEvaluator.d.ts.map +0 -1
  575. package/dist/cjs/core/SignalEvaluator.js +0 -319
  576. package/dist/cjs/core/SignalEvaluator.js.map +0 -1
  577. package/dist/cjs/core/SignalProcessor.d.ts +0 -152
  578. package/dist/cjs/core/SignalProcessor.d.ts.map +0 -1
  579. package/dist/cjs/core/SignalProcessor.js +0 -505
  580. package/dist/cjs/core/SignalProcessor.js.map +0 -1
  581. package/dist/cjs/core/Step.d.ts +0 -184
  582. package/dist/cjs/core/Step.d.ts.map +0 -1
  583. package/dist/cjs/core/Step.js +0 -599
  584. package/dist/cjs/core/Step.js.map +0 -1
  585. package/dist/cjs/core/StepLifecycle.d.ts +0 -43
  586. package/dist/cjs/core/StepLifecycle.d.ts.map +0 -1
  587. package/dist/cjs/core/StepLifecycle.js +0 -180
  588. package/dist/cjs/core/StepLifecycle.js.map +0 -1
  589. package/dist/cjs/core/StreamingToolExecutor.d.ts +0 -142
  590. package/dist/cjs/core/StreamingToolExecutor.d.ts.map +0 -1
  591. package/dist/cjs/core/StreamingToolExecutor.js +0 -490
  592. package/dist/cjs/core/StreamingToolExecutor.js.map +0 -1
  593. package/dist/cjs/core/ToolLoopExecutor.d.ts +0 -133
  594. package/dist/cjs/core/ToolLoopExecutor.d.ts.map +0 -1
  595. package/dist/cjs/core/ToolLoopExecutor.js +0 -568
  596. package/dist/cjs/core/ToolLoopExecutor.js.map +0 -1
  597. package/dist/cjs/core/ToolManager.d.ts +0 -250
  598. package/dist/cjs/core/ToolManager.d.ts.map +0 -1
  599. package/dist/cjs/core/ToolManager.js +0 -1104
  600. package/dist/cjs/core/ToolManager.js.map +0 -1
  601. package/dist/cjs/core/createAgent.d.ts +0 -35
  602. package/dist/cjs/core/createAgent.d.ts.map +0 -1
  603. package/dist/cjs/core/createAgent.js +0 -39
  604. package/dist/cjs/core/createAgent.js.map +0 -1
  605. package/dist/cjs/core/flow-namespace.d.ts +0 -64
  606. package/dist/cjs/core/flow-namespace.d.ts.map +0 -1
  607. package/dist/cjs/core/flow-namespace.js +0 -182
  608. package/dist/cjs/core/flow-namespace.js.map +0 -1
  609. package/dist/cjs/core/toolGates.d.ts +0 -24
  610. package/dist/cjs/core/toolGates.d.ts.map +0 -1
  611. package/dist/cjs/core/toolGates.js +0 -52
  612. package/dist/cjs/core/toolGates.js.map +0 -1
  613. package/dist/cjs/types/persistence.d.ts +0 -254
  614. package/dist/cjs/types/persistence.d.ts.map +0 -1
  615. package/dist/cjs/types/persistence.js +0 -7
  616. package/dist/cjs/types/persistence.js.map +0 -1
  617. package/dist/cjs/types/prompt-cache.d.ts +0 -15
  618. package/dist/cjs/types/prompt-cache.d.ts.map +0 -1
  619. package/dist/cjs/types/prompt-cache.js +0 -6
  620. package/dist/cjs/types/prompt-cache.js.map +0 -1
  621. package/dist/cjs/types/signals.d.ts +0 -263
  622. package/dist/cjs/types/signals.d.ts.map +0 -1
  623. package/dist/cjs/types/signals.js +0 -11
  624. package/dist/cjs/types/signals.js.map +0 -1
  625. package/dist/cjs/types/template.d.ts +0 -84
  626. package/dist/cjs/types/template.d.ts.map +0 -1
  627. package/dist/cjs/types/template.js +0 -3
  628. package/dist/cjs/types/template.js.map +0 -1
  629. package/dist/cjs/utils/condition.d.ts +0 -63
  630. package/dist/cjs/utils/condition.d.ts.map +0 -1
  631. package/dist/cjs/utils/condition.js +0 -239
  632. package/dist/cjs/utils/condition.js.map +0 -1
  633. package/dist/cjs/utils/event.d.ts +0 -6
  634. package/dist/cjs/utils/event.d.ts.map +0 -1
  635. package/dist/cjs/utils/event.js +0 -20
  636. package/dist/cjs/utils/event.js.map +0 -1
  637. package/dist/cjs/utils/id.d.ts +0 -33
  638. package/dist/cjs/utils/id.d.ts.map +0 -1
  639. package/dist/cjs/utils/id.js +0 -84
  640. package/dist/cjs/utils/id.js.map +0 -1
  641. package/dist/cjs/utils/serialize.d.ts +0 -36
  642. package/dist/cjs/utils/serialize.d.ts.map +0 -1
  643. package/dist/cjs/utils/serialize.js +0 -77
  644. package/dist/cjs/utils/serialize.js.map +0 -1
  645. package/dist/cjs/utils/session.d.ts +0 -124
  646. package/dist/cjs/utils/session.d.ts.map +0 -1
  647. package/dist/cjs/utils/session.js +0 -396
  648. package/dist/cjs/utils/session.js.map +0 -1
  649. package/dist/constants/index.d.ts +0 -2
  650. package/dist/constants/index.d.ts.map +0 -1
  651. package/dist/constants/index.js +0 -4
  652. package/dist/constants/index.js.map +0 -1
  653. package/dist/core/AutoChainExecutor.d.ts +0 -97
  654. package/dist/core/AutoChainExecutor.d.ts.map +0 -1
  655. package/dist/core/AutoChainExecutor.js +0 -284
  656. package/dist/core/AutoChainExecutor.js.map +0 -1
  657. package/dist/core/BranchEvaluator.d.ts +0 -55
  658. package/dist/core/BranchEvaluator.d.ts.map +0 -1
  659. package/dist/core/BranchEvaluator.js +0 -121
  660. package/dist/core/BranchEvaluator.js.map +0 -1
  661. package/dist/core/DirectiveChainTracker.d.ts +0 -49
  662. package/dist/core/DirectiveChainTracker.d.ts.map +0 -1
  663. package/dist/core/DirectiveChainTracker.js +0 -117
  664. package/dist/core/DirectiveChainTracker.js.map +0 -1
  665. package/dist/core/Events.d.ts +0 -26
  666. package/dist/core/Events.d.ts.map +0 -1
  667. package/dist/core/Events.js +0 -137
  668. package/dist/core/Events.js.map +0 -1
  669. package/dist/core/Flow.d.ts +0 -183
  670. package/dist/core/Flow.d.ts.map +0 -1
  671. package/dist/core/Flow.js +0 -547
  672. package/dist/core/Flow.js.map +0 -1
  673. package/dist/core/FlowRouter.d.ts +0 -183
  674. package/dist/core/FlowRouter.d.ts.map +0 -1
  675. package/dist/core/FlowRouter.js +0 -1043
  676. package/dist/core/FlowRouter.js.map +0 -1
  677. package/dist/core/PersistenceManager.d.ts +0 -114
  678. package/dist/core/PersistenceManager.d.ts.map +0 -1
  679. package/dist/core/PersistenceManager.js +0 -332
  680. package/dist/core/PersistenceManager.js.map +0 -1
  681. package/dist/core/PromptComposer.d.ts +0 -47
  682. package/dist/core/PromptComposer.d.ts.map +0 -1
  683. package/dist/core/PromptComposer.js +0 -393
  684. package/dist/core/PromptComposer.js.map +0 -1
  685. package/dist/core/PromptSectionCache.d.ts +0 -48
  686. package/dist/core/PromptSectionCache.d.ts.map +0 -1
  687. package/dist/core/PromptSectionCache.js +0 -104
  688. package/dist/core/PromptSectionCache.js.map +0 -1
  689. package/dist/core/ResponseEngine.d.ts +0 -43
  690. package/dist/core/ResponseEngine.d.ts.map +0 -1
  691. package/dist/core/ResponseEngine.js +0 -231
  692. package/dist/core/ResponseEngine.js.map +0 -1
  693. package/dist/core/ResponseGenerationError.d.ts +0 -30
  694. package/dist/core/ResponseGenerationError.d.ts.map +0 -1
  695. package/dist/core/ResponseGenerationError.js +0 -31
  696. package/dist/core/ResponseGenerationError.js.map +0 -1
  697. package/dist/core/ResponseModal.d.ts +0 -305
  698. package/dist/core/ResponseModal.d.ts.map +0 -1
  699. package/dist/core/ResponseModal.js +0 -1410
  700. package/dist/core/ResponseModal.js.map +0 -1
  701. package/dist/core/ResponsePipeline.d.ts +0 -220
  702. package/dist/core/ResponsePipeline.d.ts.map +0 -1
  703. package/dist/core/ResponsePipeline.js +0 -1035
  704. package/dist/core/ResponsePipeline.js.map +0 -1
  705. package/dist/core/SessionFinalizer.d.ts +0 -34
  706. package/dist/core/SessionFinalizer.d.ts.map +0 -1
  707. package/dist/core/SessionFinalizer.js +0 -84
  708. package/dist/core/SessionFinalizer.js.map +0 -1
  709. package/dist/core/SessionManager.d.ts +0 -112
  710. package/dist/core/SessionManager.d.ts.map +0 -1
  711. package/dist/core/SessionManager.js +0 -301
  712. package/dist/core/SessionManager.js.map +0 -1
  713. package/dist/core/SignalCoordinator.d.ts +0 -103
  714. package/dist/core/SignalCoordinator.d.ts.map +0 -1
  715. package/dist/core/SignalCoordinator.js +0 -203
  716. package/dist/core/SignalCoordinator.js.map +0 -1
  717. package/dist/core/SignalEvaluator.d.ts +0 -86
  718. package/dist/core/SignalEvaluator.d.ts.map +0 -1
  719. package/dist/core/SignalEvaluator.js +0 -312
  720. package/dist/core/SignalEvaluator.js.map +0 -1
  721. package/dist/core/SignalProcessor.d.ts +0 -152
  722. package/dist/core/SignalProcessor.d.ts.map +0 -1
  723. package/dist/core/SignalProcessor.js +0 -498
  724. package/dist/core/SignalProcessor.js.map +0 -1
  725. package/dist/core/Step.d.ts +0 -184
  726. package/dist/core/Step.d.ts.map +0 -1
  727. package/dist/core/Step.js +0 -594
  728. package/dist/core/Step.js.map +0 -1
  729. package/dist/core/StepLifecycle.d.ts +0 -43
  730. package/dist/core/StepLifecycle.d.ts.map +0 -1
  731. package/dist/core/StepLifecycle.js +0 -176
  732. package/dist/core/StepLifecycle.js.map +0 -1
  733. package/dist/core/StreamingToolExecutor.d.ts +0 -142
  734. package/dist/core/StreamingToolExecutor.d.ts.map +0 -1
  735. package/dist/core/StreamingToolExecutor.js +0 -483
  736. package/dist/core/StreamingToolExecutor.js.map +0 -1
  737. package/dist/core/ToolLoopExecutor.d.ts +0 -133
  738. package/dist/core/ToolLoopExecutor.d.ts.map +0 -1
  739. package/dist/core/ToolLoopExecutor.js +0 -564
  740. package/dist/core/ToolLoopExecutor.js.map +0 -1
  741. package/dist/core/ToolManager.d.ts +0 -250
  742. package/dist/core/ToolManager.d.ts.map +0 -1
  743. package/dist/core/ToolManager.js +0 -1098
  744. package/dist/core/ToolManager.js.map +0 -1
  745. package/dist/core/createAgent.d.ts +0 -35
  746. package/dist/core/createAgent.d.ts.map +0 -1
  747. package/dist/core/createAgent.js +0 -36
  748. package/dist/core/createAgent.js.map +0 -1
  749. package/dist/core/flow-namespace.d.ts +0 -64
  750. package/dist/core/flow-namespace.d.ts.map +0 -1
  751. package/dist/core/flow-namespace.js +0 -179
  752. package/dist/core/flow-namespace.js.map +0 -1
  753. package/dist/core/toolGates.d.ts +0 -24
  754. package/dist/core/toolGates.d.ts.map +0 -1
  755. package/dist/core/toolGates.js +0 -49
  756. package/dist/core/toolGates.js.map +0 -1
  757. package/dist/types/persistence.d.ts +0 -254
  758. package/dist/types/persistence.d.ts.map +0 -1
  759. package/dist/types/persistence.js +0 -6
  760. package/dist/types/persistence.js.map +0 -1
  761. package/dist/types/prompt-cache.d.ts +0 -15
  762. package/dist/types/prompt-cache.d.ts.map +0 -1
  763. package/dist/types/prompt-cache.js +0 -5
  764. package/dist/types/prompt-cache.js.map +0 -1
  765. package/dist/types/signals.d.ts +0 -263
  766. package/dist/types/signals.d.ts.map +0 -1
  767. package/dist/types/signals.js +0 -10
  768. package/dist/types/signals.js.map +0 -1
  769. package/dist/types/template.d.ts +0 -84
  770. package/dist/types/template.d.ts.map +0 -1
  771. package/dist/types/template.js +0 -2
  772. package/dist/types/template.js.map +0 -1
  773. package/dist/utils/condition.d.ts +0 -63
  774. package/dist/utils/condition.d.ts.map +0 -1
  775. package/dist/utils/condition.js +0 -230
  776. package/dist/utils/condition.js.map +0 -1
  777. package/dist/utils/event.d.ts +0 -6
  778. package/dist/utils/event.d.ts.map +0 -1
  779. package/dist/utils/event.js +0 -17
  780. package/dist/utils/event.js.map +0 -1
  781. package/dist/utils/id.d.ts +0 -33
  782. package/dist/utils/id.d.ts.map +0 -1
  783. package/dist/utils/id.js +0 -77
  784. package/dist/utils/id.js.map +0 -1
  785. package/dist/utils/serialize.d.ts +0 -36
  786. package/dist/utils/serialize.d.ts.map +0 -1
  787. package/dist/utils/serialize.js +0 -72
  788. package/dist/utils/serialize.js.map +0 -1
  789. package/dist/utils/session.d.ts +0 -124
  790. package/dist/utils/session.d.ts.map +0 -1
  791. package/dist/utils/session.js +0 -379
  792. package/dist/utils/session.js.map +0 -1
  793. package/docs/concepts/directives.md +0 -369
  794. package/docs/reference/adapters.md +0 -543
  795. package/docs/reference/create-agent.md +0 -216
  796. package/docs/reference/directive.md +0 -242
  797. package/docs/reference/signals.md +0 -368
  798. package/examples/02-data-extraction.ts +0 -90
  799. package/examples/05-branching.ts +0 -140
  800. package/examples/06-flow-control.ts +0 -103
  801. package/examples/08-persistence.ts +0 -98
  802. package/examples/09-signals.ts +0 -144
  803. package/src/adapters/MemoryAdapter.ts +0 -281
  804. package/src/adapters/MongoAdapter.ts +0 -341
  805. package/src/adapters/OpenSearchAdapter.ts +0 -693
  806. package/src/adapters/PostgreSQLAdapter.ts +0 -487
  807. package/src/adapters/PrismaAdapter.ts +0 -617
  808. package/src/adapters/RedisAdapter.ts +0 -439
  809. package/src/adapters/SQLiteAdapter.ts +0 -496
  810. package/src/adapters/index.ts +0 -43
  811. package/src/adapters/sessionRow.ts +0 -57
  812. package/src/constants/index.ts +0 -2
  813. package/src/core/AutoChainExecutor.ts +0 -397
  814. package/src/core/BranchEvaluator.ts +0 -161
  815. package/src/core/DirectiveChainTracker.ts +0 -144
  816. package/src/core/Events.ts +0 -164
  817. package/src/core/Flow.ts +0 -665
  818. package/src/core/FlowRouter.ts +0 -1540
  819. package/src/core/PersistenceManager.ts +0 -446
  820. package/src/core/PromptComposer.ts +0 -448
  821. package/src/core/PromptSectionCache.ts +0 -125
  822. package/src/core/ResponseEngine.ts +0 -338
  823. package/src/core/ResponseGenerationError.ts +0 -53
  824. package/src/core/ResponseModal.ts +0 -1902
  825. package/src/core/ResponsePipeline.ts +0 -1404
  826. package/src/core/SessionFinalizer.ts +0 -108
  827. package/src/core/SessionManager.ts +0 -372
  828. package/src/core/SignalCoordinator.ts +0 -263
  829. package/src/core/SignalEvaluator.ts +0 -404
  830. package/src/core/SignalProcessor.ts +0 -663
  831. package/src/core/Step.ts +0 -782
  832. package/src/core/StepLifecycle.ts +0 -242
  833. package/src/core/StreamingToolExecutor.ts +0 -609
  834. package/src/core/ToolLoopExecutor.ts +0 -749
  835. package/src/core/ToolManager.ts +0 -1379
  836. package/src/core/createAgent.ts +0 -40
  837. package/src/core/flow-namespace.ts +0 -227
  838. package/src/core/toolGates.ts +0 -72
  839. package/src/types/persistence.ts +0 -303
  840. package/src/types/prompt-cache.ts +0 -17
  841. package/src/types/signals.ts +0 -338
  842. package/src/types/template.ts +0 -98
  843. package/src/utils/condition.ts +0 -296
  844. package/src/utils/event.ts +0 -16
  845. package/src/utils/id.ts +0 -91
  846. package/src/utils/serialize.ts +0 -86
  847. package/src/utils/session.ts +0 -501
@@ -1,274 +1,152 @@
1
1
  ---
2
- title: "Architecture"
3
- description: "The six primitives of @falai/agent and how they fit together to keep language on the AI's side and decisions on the code's side."
2
+ title: "Agent architecture"
3
+ description: "The seven words the rest of the docs use, and the line between what the model decides and what the code decides."
4
4
  type: concept
5
5
  order: 1
6
6
  ---
7
7
 
8
- # Architecture
9
-
10
- > the AI understands, the code is in control
11
-
12
- Six types do all the work. Five are about declaration — what the agent looks like in source. One is about control — what tools and hooks return at runtime to redirect a turn. This page maps the ownership and reference relationships between them, explains the schema-first principle that makes pre-extraction work, and draws the line between what the AI does and what the code does.
13
-
14
- LLMs are good at language and unreliable at control flow. They paraphrase well; they do not maintain invariants. They infer intent well; they do not enforce completion gates. The framework's job is to keep the AI on the side of language — understanding intent, extracting structured data, generating prose — while keeping the code on the side of decisions: which flow runs, when a flow completes, what a tool actually does, what state survives a turn.
15
-
16
- This page explains the shape of that seam. It names the six primitives, says what each one is for, and shows how they reference each other. It does not teach syntax. Once the mental model is in place, the [reference](../reference/create-agent.md) pages document the contracts and the [tutorial](../start/01-install.md) walks through the code line by line.
17
-
18
- ## Core vocabulary
19
-
20
- Eight terms cover everything below. Every other term in the docs defines itself at first use — there is no separate glossary.
21
-
22
- | Term | What it means here |
23
- |------|--------------------|
24
- | **Agent** | The top-level object. Owns the schema, provider, flows, tools, signals, and persistence. |
25
- | **Flow** | A single conversational goal — an ordered sequence of steps with shared completion semantics. |
26
- | **Step** | One node inside a flow. Asks a question, collects fields, calls tools, runs hooks, or speaks a verbatim line. |
27
- | **Tool** | A typed function the AI can call. May redirect the conversation by emitting a directive. |
28
- | **Instruction** | A behavioral statement (`must` / `never` / `should`) that shapes how the agent talks at a given scope. |
29
- | **Directive** | A flat object any tool, hook, or branch returns to write state, change position, or speak verbatim. |
30
- | **Schema** | The single source of truth for `TData` — what the agent collects across the whole conversation. |
31
- | **Context** | Ambient app data of type `TContext` — user, env, services. Independent of `TData`. |
32
-
33
- These are the words the rest of the docs use without footnotes. They are also the words the type system uses — every name in the table maps directly to an exported symbol or a generic parameter.
34
-
35
- ## The six primitives
36
-
37
- Six types do all the work. The first five are about declaration — what the agent looks like in source. The last one is about control — what tools and hooks return at runtime to act on a turn. None of them is novel on its own. The shape of the framework is in how few there are and how cleanly they compose.
38
-
39
- A small illustrative sketch first, just to show the silhouette:
40
-
41
- ```typescript
42
- const agent = createAgent({
43
- name: "BookingBot",
44
- schema: { /* TData shape */ },
45
- provider: new GeminiProvider({ apiKey }),
46
- instructions: [
47
- { kind: "must", prompt: "Confirm dates before booking." },
48
- ],
49
- tools: [
50
- { id: "book_hotel", handler: async (ctx) => { /* ... */ } },
51
- ],
52
- flows: [
53
- {
54
- title: "Booking",
55
- requiredFields: ["city", "checkIn"],
56
- steps: [
57
- { id: "ask", prompt: "Collect city and date.", collect: ["city", "checkIn"] },
58
- { id: "confirm", prompt: "Confirm and call book_hotel.", requires: ["city", "checkIn"] },
59
- ],
60
- },
61
- ],
62
- });
8
+ # Agent architecture
9
+
10
+ The AI understands. The code is in control.
11
+
12
+ @falai/agent runs a conversation as a set of small programs called flows. The model has two jobs: read what the customer wrote, and phrase what the assistant says. Every other decision is code: which flow runs, which step comes next, which field is still missing, how long to wait, what to send and when.
13
+
14
+ ## The words
15
+
16
+ These seven words are the whole design. The rest of the docs use them without explaining them again.
17
+
18
+ | Word | What it is | Where it lives |
19
+ |---|---|---|
20
+ | **Agent** | The configuration: fields, flows, provider, registries. One instance serves every session. | `f.agent(options)` returns an `Agent` |
21
+ | **Flow** | A trigger plus an ordered list of steps. | `Flow`, built with `f.flow()` |
22
+ | **Trigger** | When a run of the flow starts: `message`, `mention`, `silence`, `event`, or none (the host starts it). | `Trigger`, in `flow.on[]` |
23
+ | **Step** | One thing the run does: the model talks (`prompt` / `collect`), a fixed text goes out (`say`), the host does something (`do`), the run parks (`wait`), the code forks (`if`). | `Step`, in `flow.steps[]` |
24
+ | **Field** | One piece of data to collect, authored once on the agent with its own `ask`. | `FieldDef`, in `falai().fields()` |
25
+ | **Run** | One live execution of a flow inside a session. A session holds many runs; at most one is asking. That run holds the floor: the next message is read as its answer. | `Run`, in `session.runs[]` |
26
+ | **Turn** | One call to `agent.turn(input)`: something happened, here is what to send and when to wake up. | `TurnInput` in, `TurnResult` out |
27
+
28
+ Four registries live on the agent. Instructions are written inline, wherever they apply. Flows name registry entries as strings, and the names are checked when the agent is built.
29
+
30
+ | On the agent | What it holds | Named from |
31
+ |---|---|---|
32
+ | `actions` | Host code a `do` step runs. Returns `{ ok }`, `{ skipped }`, `{ failed }` or `{ defer }`. | `do: 'notify'` |
33
+ | `events` | Host events a trigger or a `wait` may name, each with an optional `direction`. | `on: [{ event: 'stage_entered' }]`, `wait: { event: 'meeting_booked' }` |
34
+ | `conditions` | Host predicates a JSON `if` may name, with an argument. | `if: { tagsAny: ['vip'] }` |
35
+ | `tools` | Typed functions the model may call while it speaks. They return `{ value?, data? }`, never movement. | `tools: ['checkAvailability']` on a step or a flow |
36
+ | `instructions` | Rules the prompt carries while they apply: `must`, `never`, `should`. | Not named: written inline where they apply, on the agent, a flow, a step, or the idle speaker |
37
+
38
+ The **host** is your program: the one that receives a message from the channel, loads the session, calls `turn()`, saves, sends and schedules. The framework does none of those.
39
+
40
+ ## How they fit
41
+
42
+ ```text
43
+ Agent (immutable, one instance for every session)
44
+ ├── fields nome, empresa, confirmado, … authored once, typed
45
+ ├── flows[] Flow = on[] (triggers) + steps[]
46
+ │ step: talk | say | do | wait | if
47
+ │ movement: then / else → step id | 'end' | { step, clear } | { flow, input }
48
+ ├── actions do: 'notify' ┐
49
+ ├── events event: 'meeting_booked' │ host registries,
50
+ ├── conditions if: { inStage: 'x' } │ referenced by name
51
+ ├── tools the model may call these ┘
52
+ ├── instructions must / never / should
53
+ ├── idle speaks when no run holds the floor ('silent' mutes it)
54
+ └── provider talks to the model
55
+
56
+ Session (one per conversation; the host saves it)
57
+ ├── data the collected fields, in any order
58
+ ├── runs[] live runs: running | asking | waiting | suspended
59
+ ├── claims which flows already ran here, so repeat: 'once' and cooldowns hold
60
+ └── inputs the last 50 input ids, for replays
61
+
62
+ turn(input) ── message | wake | event | start ──▶ TurnResult
63
+ session, changed, messages[], schedule[], llmCalls, …
63
64
  ```
64
65
 
65
- Five of the six primitives appear by name in that block. The remaining one — `Directive` — surfaces only when control flow is on the line, returned from a tool or hook to redirect the conversation.
66
-
67
- ### Agent
68
-
69
- An `Agent<TContext, TData>` is the top-level handle. It binds the four ingredients of a conversational system: a **schema** (what to collect), a **provider** (which LLM to call), a set of **flows** (what goals to pursue), and an optional **persistence** adapter (where to keep sessions). Anything ambient — auth, feature flags, services — rides on `TContext`. Anything collected — names, dates, choices — lives in `TData`. Both type parameters are inferred once at the agent boundary and propagate through every flow, step, tool, and hook beneath it.
70
-
71
- The agent owns the registry. It assigns a deterministic id to every flow, step, and tool; it enforces a single `schema` at every `collect` site; it holds the chosen provider and the session lifecycle. It exposes `respond(params)` and `respondStream(params)` for handling user input, plus `dispatch(target, session)` for redirecting from outside a turn. One agent serves many concurrent conversations — a session id keys into the persistence adapter, and `respond` is otherwise stateless from the caller's perspective.
72
-
73
- ### Flow
66
+ ## The two model calls
74
67
 
75
- A `Flow<TContext, TData>` is one conversational goal — booking a hotel, escalating a complaint, onboarding a teammate. Each flow declares a `title`, a list of `steps`, optional `requiredFields` that gate completion, and conditions for activation: `when` for AI-evaluated strings, `if` for code predicates. The flow router selects exactly one flow per turn, so a flow is also the unit of attention — at any moment, the agent is either inside one flow or sitting idle between flows.
68
+ The model gets at most two calls per turn, and each has one job.
76
69
 
77
- A flow owns its steps in declaration order, its scoped instructions and tools, and its completion semantics. The top-level `onComplete: string` is sugar for chaining into another flow on completion; for dynamic logic, `hooks.onComplete` returns a `Directive`. The optional `reentrant` flag opts the flow into "do another?" loops — on re-entry, the engine clears every field declared in `requiredFields` and `optionalFields` so the flow starts fresh. A flow does not own session data — `TData` lives at the agent — but it does declare which fields it needs to be considered done.
70
+ - **The understand call** reads the customer's message. It scores the candidate flows from 0 to 100, says which things the customer brought up, answers the `when` questions of the asking step, and extracts any field values the message carries. It never moves a run.
71
+ - **The speak call** phrases the assistant's reply for one talk step (or for the idle speaker) and extracts the fields that step is still collecting. It may call tools in rounds. It never moves a run either.
78
72
 
79
- ### Step
73
+ Everything else is code, in `src/core/Runner.ts`: which flows are eligible, which run holds the floor, which fields are pending, which step comes next, how long a wait is, what key a message gets, when a claim (a record that this flow already ran) blocks a start, what the result says. Code behaves the same on a replay; the model does not. So nothing the model says is applied before code checks it: unknown fields are dropped, values are coerced to the field's type, `enum` membership is enforced.
80
74
 
81
- A `Step<TContext, TData>` is a single node inside a flow. Each step describes one moment in the conversation: ask a question, collect a few schema fields, call a tool, branch to another step, or speak a verbatim line. Steps are the smallest unit the engine can suspend on between user turns — when a step finishes, the engine checks for a directive, then for branches, then falls through to the linear successor. Steps are also the unit at which scoped tools and instructions attach, so a step can shadow an agent-level setting locally without modifying the agent.
75
+ Two things follow. A flow with no talk steps costs zero model calls. And every result carries `llmCalls`, so a test asserts the budget instead of trusting it. [The turn pipeline](./pipeline.md) walks the eight phases and what each one spends.
82
76
 
83
- A step comes in three mutually exclusive shapes. An **LLM step** has a `prompt` and the engine calls the model. An **auto step** sets `auto: true` — pure computation, no LLM call, only `onEnter`, `prepare`, and `branches` execute. A **reply step** sets `reply` — the engine renders the template and emits it verbatim, skipping the model entirely. Beyond shape, a step owns its `collect` set (which schema fields it extracts), its `requires` list (prerequisites that must be present before entry), its scoped tools and instructions, its `branches` for explicit forks, and the four lifecycle positions: `onEnter`, `prepare`, `finalize`, `onExit`. The combination of three shapes and four lifecycle positions is what lets a step be either a conversational moment or a pure pipeline node, with no third category in between.
77
+ ## One agent, every session
84
78
 
85
- ### Tool
79
+ An `Agent` is immutable configuration. Build it once and keep it for the life of the process. It holds no session, no context and no history of its own; those arrive on every `turn()`.
86
80
 
87
- A `Tool<TContext, TData, TResult>` is a function the AI can call during a turn. Every tool is a single interface — `id` is the sole identifier, every metadata field is optional, and the handler receives a `ToolContext` (a typed view of `data`, `context`, `history`, plus `dispatch` for mid-handler redirection). A tool can return a plain value, a `ToolResult` with state writes, or a `ToolResult` with an embedded `directive` that redirects the conversation when the result is delivered.
81
+ ```ts
82
+ import type { Agent } from "@falai/agent";
83
+ declare const agent: Agent;
88
84
 
89
- A tool owns its parameters schema (what arguments the LLM may pass), its handler (what actually runs), and the optional safety metadata that lets the executor reason about it: `isReadOnly`, `isConcurrencySafe`, `isDestructive`, `validateInput`, `checkPermissions`, `maxResultSizeChars`. Tools are scoped — defined on the agent (always available), on a flow (available only while that flow is active), or on a step (available only while that step is current). Resolution stacks scope-on-scope so a step can shadow an agent-level tool by id without removing it from the registry.
90
-
91
- ### Instruction
92
-
93
- An `Instruction<TContext, TData>` is a single behavioral statement that shapes how the agent talks. Every instruction carries a `kind` discriminator — `must` for absolute do, `never` for absolute don't, `should` for conditional nudge — alongside a `prompt` (the rendered text) and optional activation conditions (`when` for AI strings, `if` for code predicates). One shape covers every behavioral nudge in the system; the only thing that differs from one instruction to the next is its severity and its scope.
94
-
95
- An instruction owns its rendered position in the prompt. The composer renders each active instruction as a single bullet under the system prompt's `## Instructions` section, prefixed with its kind and a scope caption: `[Always]` for agent-level, `[In: <FlowTitle>]` for flow-level, `[Step: <stepId>]` for step-level. The set actually rendered on a turn is reported back as `appliedInstructions` on the response — observability is deterministic, derived from rendering, not self-reported by the model.
96
-
97
- ### Directive
98
-
99
- A `Directive<TContext, TData>` is a flat object literal — not a class, not a builder, not a discriminated union — that any tool, hook, or branch returns to act on the turn. Every field is optional. A directive carries up to four orthogonal payloads: at most **one position field** (`goTo`, `goToStep`, `complete`, `abort`, or `reset`), zero or one **verbatim reply**, optional **state writes** (`dataUpdate` / `contextUpdate`), and optional **pre-LLM augmentation** (`appendPrompt`, `injectTools`, `halt`) plus optional `reason` strings inside object forms for traceability. The flatness is intentional — earlier drafts modeled directives as a discriminated union, but a flat object composes more naturally when a single decision point needs to write state, change position, and speak verbatim in one return value.
100
-
101
- The directive is the single language the framework speaks for control flow. A tool that decides "this user is ineligible" returns `{ goTo: "denial", reply: "Sorry — you don't qualify." }`. A finalize hook that finishes a booking returns `{ complete: true, dataUpdate: { bookingId } }`. A prepare hook that detects a VIP returns `{ appendPrompt: ["This caller is VIP — confirm preferences first."] }`. All of these merge through one algorithm — position fields by precedence, state writes shallow-merged, `reply` last-wins — implemented as `flow.merge(a, b)` and applied uniformly across the turn pipeline.
102
-
103
- The three pre-LLM fields (`appendPrompt`, `injectTools`, `halt`) have a one-turn lifetime: they only take effect in pre-LLM hooks (`onEnter`, `prepare`). When emitted from post-LLM hooks or persisted to `session.pendingDirective`, they are ignored with a WARN log. This keeps one type for all emitters while the engine enforces the phase boundary at runtime.
104
-
105
- ## Supporting concepts
106
-
107
- The six primitives carry the weight. Four supporting pieces make them ergonomic.
108
-
109
- ### `flow` namespace
110
-
111
- `flow` is a small runtime helper namespace exported from the package root. There are no constructor builders here — directives are object literals everywhere they appear in source. The namespace exists for runtime work: validating a directive that arrived from outside the framework (an RPC payload, a queue message), merging two directives by hand when composing custom orchestration, or narrowing an `unknown` value to `Directive` in a type guard.
112
-
113
- ```typescript
114
- import { flow } from "@falai/agent";
115
-
116
- flow.isDirective(x); // type guard
117
- flow.merge(a, b); // Algorithm 4 merge of two directives
118
- flow.validate(d); // throws FlowConfigurationError on invalid shape
85
+ const r = await agent.turn({ sessionId: "demo", message: "oi" });
86
+ console.log(r.llmCalls); // 1: one flow, nothing to judge, one speak call
119
87
  ```
120
88
 
121
- `flow.merge` is the same algorithm the engine runs internally on the per-turn directive bus, exposed for callers that need to compose results before dispatching them. `flow.validate` enforces three invariants — at most one position field, no empty `goTo: {}`, no `reply` alongside `abort` — and throws a typed error otherwise. The pipeline calls it eagerly on every emitted directive, so downstream code can rely on shape.
89
+ Here is the agent that call ran against:
122
90
 
123
- ### `createAgent`
91
+ ```ts
92
+ import { falai } from "@falai/agent";
93
+ import type { AiProvider } from "@falai/agent";
124
94
 
125
- `createAgent(options)` is the level-1 entry point for constructing an agent. It is sugar over `new Agent(options)` and accepts the same `AgentOptions` shape, but reads more naturally for the common case: one options object, generic inference flowing from `schema` through every `flows[].steps[].collect` reference. The type of `session.data` and tool-handler arguments is derived once at the call site and propagates everywhere.
95
+ declare const provider: AiProvider;
126
96
 
127
- ```typescript
128
- const agent = createAgent({
129
- name: "BookingBot",
130
- provider: new GeminiProvider({ apiKey: process.env.GEMINI_API_KEY! }),
131
- schema: { /* ... */ },
132
- flows: [/* ... */],
97
+ const f = falai().fields({
98
+ nome: { type: "string", ask: "Pergunte o nome da pessoa, sem tom de formulário." },
133
99
  });
134
- ```
135
-
136
- The factory is the recommended construction path for application code. The class form (`new Agent(options)`) remains for power users who need to subclass — for example, to override `respond` for custom telemetry, or to add bespoke methods on top of the agent surface. Both share validation: misuse surfaces as `FlowConfigurationError` synchronously at construction, before any turn runs.
137
-
138
- ### `Agent.dispatch`
139
-
140
- `agent.dispatch(target, session)` is the imperative entry point for redirecting a session from outside a turn — typically from a webhook, a cron job, or a UI button that jumps the user into a different flow. It accepts either a string shorthand (`"Feedback"` desugars to `{ goTo: "Feedback" }`) or a full `Directive`. Internally, it writes `session.pendingDirective`; the directive is consumed at the start of the next `respond` call before any other resolution runs. With a persistence adapter configured (and `autoSave` on — the default), dispatch persists immediately, so the queued directive survives process boundaries; without an adapter it is memory-only, and with `autoSave: false` persisting before the next turn is the caller's job. Because the save compare-and-swaps on the session version, a dispatch from a stale copy throws `SessionConflictError` instead of clobbering another writer.
141
-
142
- ```typescript
143
- const updated = await agent.dispatch(
144
- { goTo: "Billing", reply: "Transferring you now." },
145
- session,
146
- );
147
- ```
148
-
149
- Inside a turn, the same effect is reached by returning or dispatching a directive from a tool or hook — the per-turn bus handles the merge. Outside a turn, `Agent.dispatch` is the sanctioned entry point for setting the next position. There is one way to express each thing, and this is the one for "the user just clicked the cancel button in the UI; their next message should land in the Cancellation flow."
150
100
 
151
- The two routes — in-turn (return a directive) and out-of-turn (`Agent.dispatch`) — converge on the same place: `session.pendingDirective`. The pipeline consumes that field at the very top of the next turn before signals or routing run, applies it via `applyDirective`, and clears it. Persistence sees the same shape regardless of where the directive came from, which means the persisted state is independent of how the redirection was issued.
152
-
153
- ### Branches
154
-
155
- A step's `branches` field declares an explicit, source-local fork: from this step, here are the next-step options and how each one is chosen. Branches sit between code and AI — `if` predicates evaluate for free, `when` strings call the LLM only when the predicate already passed. The first matching entry wins, and its `then` resolves to a step id (within the current flow), a flow id (sugar for `goTo`), or a full directive (for cross-flow steps and state-writing forks).
156
-
157
- Branches are the answer to "how do I fork without an LLM call when the choice is purely a function of `data`?" — combined with `auto: true`, an entire decision can run with zero tokens. They coexist with the implicit-fork pattern (multiple successor steps, each carrying its own `step.when`); when both are present on the same step, branches take precedence. Branch resolution sits between the post-LLM phase of the directive bus and the linear successor selection — it is one specific position in the [turn pipeline](./pipeline.md), not a parallel system.
158
-
159
- Branches are also the place where the AI/code split is most visible at the call site. A single `branches` array can mix entries: one entry that uses `if` only (free), one that uses `when` only (one LLM call), one that uses both (`if` short-circuits the `when` evaluation). The author chooses per branch, and the cost of that choice is local to one entry rather than buried in a flag elsewhere.
160
-
161
- ## How the primitives reference each other
162
-
163
- The diagram below maps the ownership and reference relationships between the six primitives and the two state surfaces. Solid arrows are ownership. Dashed lines are scoping or extension. The two state nodes (`Schema` and `Context`) are not primitives — they are the typed surfaces the primitives operate on, drawn at the bottom because everything else references them.
164
-
165
- ```mermaid
166
- graph TB
167
- Schema[(Schema<br/>TData)]
168
- Context[(Context<br/>TContext)]
169
-
170
- Agent --> Schema
171
- Agent --> Context
172
- Agent -->|owns| Flow
173
- Agent -->|owns| Tool
174
- Agent -->|owns| Instruction
175
-
176
- Flow -->|owns| Step
177
- Flow -->|requiredFields| Schema
178
- Flow -.scoped.- Tool
179
- Flow -.scoped.- Instruction
180
-
181
- Step -->|collect / requires| Schema
182
- Step -.scoped.- Tool
183
- Step -.scoped.- Instruction
184
- Step -->|branches| Step
185
- Step -->|onEnter / prepare| Directive
186
- Step -->|finalize| Directive
187
-
188
- Tool -->|ctx.dispatch| Directive
189
- Tool -->|ToolResult.directive| Directive
190
-
191
- Directive -.merged via.-> FlowNS[flow.merge]
101
+ const agent = f.agent({
102
+ name: "Ana",
103
+ provider,
104
+ flows: [
105
+ f.flow({
106
+ id: "boas-vindas",
107
+ name: "Boas-vindas",
108
+ on: [{ message: [] }],
109
+ steps: [{ id: "nome", collect: ["nome"] }],
110
+ }),
111
+ ],
112
+ });
192
113
 
193
- classDef primitive fill:#1e293b,stroke:#0ea5e9,color:#fff;
194
- classDef state fill:#0f172a,stroke:#64748b,color:#cbd5e1;
195
- class Agent,Flow,Step,Tool,Instruction,Directive primitive;
196
- class Schema,Context state;
114
+ export { agent };
197
115
  ```
198
116
 
199
- Read it top-down. The agent owns flows, tools, and instructions, and binds them to a single schema and a single context type. A flow owns steps and may scope its own instructions and tools. A step references the schema through `collect` and `requires`, may carry its own scoped instructions and tools, and may fork via `branches` into another step. Hooks and tools emit directives — pre-LLM hooks use the pre-LLM fields (`appendPrompt`, `injectTools`, `halt`), post-LLM hooks use position/state/reply fields. The `flow` namespace validates and merges them.
200
-
201
- The two state types — `Schema` for `TData`, `Context` for `TContext` — sit at the bottom because everything else points at them. They are not primitives in the same sense as the six types; they are the typed surfaces those primitives operate on, and they are owned by the agent.
202
-
203
- Two things are deliberately absent from this diagram. There is no separate "router" primitive — flow selection is an internal pipeline phase, not a user-facing type. There is no separate "session" primitive in the declaration model — sessions are runtime state, indexed by `sessionId`, persisted by adapters, but not something application code constructs as a building block. Both of those concerns live in the [turn pipeline](./pipeline.md), where they are explained as steps in the per-turn sequence rather than parts of the static structure.
204
-
205
- ## The schema-first principle
206
-
207
- `TData` is **agent-level**, not flow-level. One schema describes everything that can be collected across every flow. Flows declare which fields they need (`requiredFields`); steps declare which fields they extract (`collect`) and which they require (`requires`). This is what makes pre-extraction work: when the user message arrives, the engine extracts every collectable field it can in a single pass into `session.data`, then skips any step whose `collect` set is already satisfied.
208
-
209
- The agent owns the schema, so the same field can be collected by step A in flow X and used as a prerequisite by step B in flow Y. The contracts at every site are the same shape — `(keyof TData)[]` — and TypeScript verifies them at compile time. Move a field name once at the schema and the failures surface immediately at every call site that references it.
117
+ The constructor checks the configuration before any turn runs: duplicate flow ids; every field, action, event, condition, tool and step id a flow names; the `with` of each `do` step against the action's parameters; the idle speaker's tool names. A bad name throws `FlowConfigurationError` when the agent is built, not on the turn that first reaches it.
210
118
 
211
- A practical consequence: a single user message like "I want a hotel in Lisbon for two people next Friday" populates `city`, `guests`, and `checkIn` in one extraction pass. The booking flow's first three steps all skip — their `collect` sets are already satisfied — and the engine arrives at the confirmation step on the very first turn. The flow's `requiredFields` gate completion the same way regardless of whether fields were collected one per turn or three at once. The schema does not care which step did the work; it only cares that the data is there.
119
+ Per turn, the host passes what only it knows:
212
120
 
213
- ## What the AI does, what the code does
121
+ | Input | What it is |
122
+ |---|---|
123
+ | `sessionId`, `session?` | The session the host loaded, or nothing on a first turn. A wake never creates a session. |
124
+ | `context` | Your own data for this turn: the customer, the tenant, whatever your flows read. Typed by `falai<C>()`. Templates read it as `{{context.x}}`; predicates, actions and tools as `ctx.context`. |
125
+ | `history` | The conversation so far. Pass it on every input kind, wakes included; both calls read it. |
126
+ | `silenced?` | Why the assistant cannot speak right now. `do` steps still run, nothing is phrased, zero calls — unless you pass `{ reason, understand: true }`, which still spends the understand call. |
127
+ | `anchors?`, `claims?` | Host keys and claims from the customer's other sessions, for flows that run once per customer instead of once per session (see [Anchors](./runs-and-waits.md#anchors)). |
214
128
 
215
- Two halves divide the work, and the seven primitives are positioned on whichever half makes the decision cheap and correct.
129
+ Then one of four input kinds: `{ message, id?, at? }`, `{ wake }`, `{ event, payload?, key }` or `{ start: { flow, input?, key } }`. [Agent](../reference/agent.md) lists every field.
216
130
 
217
- The AI is responsible for **language**: routing scores (which flow does this message want?), pre-extraction (what fields can be lifted out of this message?), step prompts (what should the assistant say to advance this step?), and the `when` half of conditions (does this AI-readable description match the situation?). The model is good at these jobs, and the framework spends tokens on them deliberately.
131
+ ## Never sends, never sleeps, never saves
218
132
 
219
- The code is responsible for **decisions**: completion (are all required fields present?), branches (does the `if` predicate pass?), tool execution (run the function, get a result), directive merging (which position field wins?), persistence (write the session, atomically). The runtime is good at these jobs, and the framework keeps them on the deterministic side of the seam.
220
-
221
- A primitive sits on the side that owns its decision. A `Flow.when` is AI because intent classification is the AI's job. A `Step.if` is code because boolean checks against `data` are the code's job. A `Directive` is code because the merge algorithm is deterministic. An `Instruction` is rendered text the code controls; the model only chooses how to follow it. Pulling on either thread leads back to the same answer: language belongs to the AI, decisions belong to the code, and the framework is the seam.
222
-
223
- The `when` / `if` split is the smallest visible expression of this principle. The same activation slot — on a flow, on a step, on an instruction, on a branch entry — accepts both: a string for the AI to evaluate, a function for the code to evaluate. When both are set, code runs first and short-circuits the AI call when the predicate already disqualifies the option. There is no unified condition type that abstracts the difference, because the difference is the point. One side spends tokens; the other does not. Authors choose explicitly, every time.
224
-
225
- ## What stays out
226
-
227
- A few things are notably absent from the framework, and the absences are part of the architecture.
228
-
229
- There is no built-in router DSL. The flow router is a single internal phase that scores flows by their `when`/`if` activation, applies a margin against the currently active flow to avoid thrashing, and lands on exactly one flow per turn. It is not exposed for subclassing or composition because there is nothing usefully variable about it at the application layer.
230
-
231
- There is no per-flow schema. Every flow consumes the agent's `TData`. A flow that needs an extra structured field declares it on the agent schema and lists it in `requiredFields`. The "this flow has its own private state" pattern always becomes "this flow uses a subset of the shared schema."
232
-
233
- There is no implicit messaging. The framework never emits a message of its own. Completion is a pure state transition — the active flow ends, the session goes idle, and any prose at that boundary comes from a developer-defined `reply` step or from the next flow's first step. Nothing speaks unless a step or a directive says it.
234
-
235
- There is no glossary. Eight terms are defined in the callout at the top of this page, and every other term in the docs defines itself at first use on the page that introduces it. The framework's surface is small enough that a glossary would duplicate prose without adding clarity.
236
-
237
- ## Why six primitives
238
-
239
- The set of six is the result of a few specific cuts. Each one collapsed a category of duplication into a single shape, and each one is worth naming for its own sake — not for migration purposes (the [migration guide](../migration/v1-to-v2.md) covers that), but because the surface visible today is the result of those choices.
240
-
241
- **One word per concept.** The verb form `route()` is still the act of selecting a flow, and "routing" is still the gerund — but the noun for "a single conversational goal" is **Flow**. The system that selects one is the **FlowRouter**. There is no overlap between the noun and the verb, which keeps the surface readable when the two appear in the same sentence.
242
-
243
- **One Instruction with a kind discriminator.** A behavioral statement is an `Instruction` with `kind: 'must' | 'never' | 'should'`. The three values cover absolute do, absolute don't, and conditional nudge — every behavioral statement an author wants to make falls into one of those categories, and the severity is visible at the call site. The renderer treats all three identically: same prompt position, same scope caption, same `appliedInstructions` reporting. Severity is what the model sees, not what the framework branches on.
244
-
245
- **One Tool with optional metadata.** A `Tool` is a single interface. The simple case is `{ id, handler }`. The production case adds `validateInput`, `checkPermissions`, `isReadOnly`, `isConcurrencySafe`, `isDestructive`, and `maxResultSizeChars` — every one optional. There is no upgrade boundary mid-codebase: a tool that starts as a plain function adds metadata fields when it needs them, without changing type or import. The executor reads each field defensively (undefined falls back to safe defaults), so the same tool runs identically with two metadata fields or zero.
246
-
247
- The remaining four primitives — Agent, Step, Flow, Directive — were always single-shape concepts. The six-primitive count is what survives those three consolidations plus the three that stood on their own.
248
-
249
- ## Construction shape
250
-
251
- The level-1 entry point is `createAgent({ ... })` — one options object, generic inference flowing from `schema` through every `flows[].steps[].collect` reference. The class form `new Agent({ ... })` accepts the same options for power users who need to subclass.
252
-
253
- ```typescript
254
- import { createAgent, GeminiProvider } from "@falai/agent";
255
-
256
- const agent = createAgent({
257
- name: "BookingBot",
258
- provider: new GeminiProvider({ apiKey }),
259
- schema: { /* TData shape */ },
260
- flows: [/* FlowOptions[] */],
261
- tools: [/* Tool[] */],
262
- instructions: [/* Instruction[] */],
263
- });
264
- ```
133
+ `turn()` does no I/O except the provider, your `do` handlers and the tools the model calls. It does not send a message, set a timer, read a clock you did not give it, or touch a store. It returns a plan:
265
134
 
266
- The construction shape encodes the ownership tree: an agent owns flows, tools, and instructions; the schema is set once; the provider is bound. Generic inference does the rest. The first time a `collect: ["foo"]` references a key not in the schema, the type checker objects at the call site. The first time two flows declare the same id, the constructor throws `FlowConfigurationError` synchronously. The first time a tool returns a malformed directive, `flow.validate` throws at apply time. Every error has a typed class, a single format (`[<ErrorClass>] <what>: <why>. <how to fix>.`), and a place in the construction or runtime sequence where it consistently surfaces.
135
+ | Result | What the host does with it |
136
+ |---|---|
137
+ | `changed: false` | Nothing. Save nothing, send nothing. |
138
+ | `session` | Save it with the version you loaded: `store.save(session, loadedVersion)`. A stale version throws `SessionConflictError`; discard everything and replay the same input. |
139
+ | `messages[]` | Send each one, honouring `afterMs`, keyed by `key` so a retry never sends twice. |
140
+ | `schedule[]` | Enqueue each wake with `jobId = key`. When it fires, call `turn({ wake: key })`. |
141
+ | `outcomes`, `started`, `ended`, `skipped` | Your execution log. |
267
142
 
268
- ## What's next
143
+ The order matters: save first, then send and schedule. A message that leaves before the save is sent twice when the save loses a race; a message that leaves after it is not. The one exception is `do` handlers and tool handlers: they run inside the turn, before the save, so they run at least once and must be idempotent on `ctx.key`. [Runs and waits](./runs-and-waits.md#five-rules-that-always-hold) lists the five rules it rests on.
269
144
 
270
- The next page walks through what happens when `agent.respond(params)` is called: the per-turn pipeline, resolution precedence (`pendingDirective` first, then signals + routing in parallel, then auto-step chains, then branches, then linear succession), the directive bus, and how `flow.merge` collapses simultaneous emissions into a single applied directive. After that, the [Directives](./directives.md) page goes deeper into the directive shape itself — why it is flat, how `SignalDirective` extends it for signals, and what each field does.
145
+ Time comes from `clock` on the agent (default: the system time), so a test passes `fakeClock()` and moves it by hand. Core code never reads `Date.now()`.
271
146
 
272
- If the goal right now is to write code, the [tutorial](../start/01-install.md) starts from a one-line install and arrives at a working agent in five short pages. If the goal is to look up an exact contract, every primitive on this page has a [reference](../reference/create-agent.md) page with the full TypeScript declaration, a fields table, two short examples, and the typed errors it can throw.
147
+ ## Where next
273
148
 
274
- **Next:** [Turn pipeline](./pipeline.md)
149
+ - [The turn pipeline](./pipeline.md): the eight phases and what each one costs.
150
+ - [Runs and waits](./runs-and-waits.md): the floor, waits, wakes, keys, claims.
151
+ - [Field collection](./collection.md): pending fields, `ask`, `extract`, `maxAsks`.
152
+ - [Your first agent](../start/02-first-agent.md): the same words, one file at a time.
@@ -0,0 +1,170 @@
1
+ ---
2
+ title: "Field collection"
3
+ description: "Declare each field once, then let the two model calls fill it and the code decide what is still missing."
4
+ type: concept
5
+ order: 4
6
+ ---
7
+
8
+ # Field collection
9
+
10
+ A field is one piece of data the conversation collects: a name, a company, a budget, a yes or no. You declare each field once, on the agent, with how to ask for it. Steps say which fields they collect. The model asks and extracts. Code decides what is still missing.
11
+
12
+ ## Declared once
13
+
14
+ ```ts
15
+ import { falai } from "@falai/agent";
16
+
17
+ const f = falai().fields({
18
+ nome: { type: "string", ask: "Pergunte o nome, sem tom de formulário." },
19
+ });
20
+ // `f` is the toolkit. `nome` is now a field any flow can collect.
21
+ ```
22
+
23
+ Declare the rest the same way:
24
+
25
+ ```ts
26
+ import { falai } from "@falai/agent";
27
+ import type { DataOf } from "@falai/agent";
28
+
29
+ const f = falai().fields({
30
+ nome: { type: "string", ask: "Pergunte o nome de um jeito leve, sem tom de formulário." },
31
+ tamanho: { type: "string", enum: ["1-10", "11-50", "51-200", "200+"], ask: "Pergunte quantas pessoas trabalham lá; ofereça as faixas." },
32
+ orcamento: { type: "number", ask: "Pergunte a faixa de investimento, dizendo que é só para orientar." },
33
+ confirmado: { type: "boolean", ask: "Resuma o que anotou e pergunte se está tudo certo." },
34
+ });
35
+
36
+ type Data = DataOf<typeof f>;
37
+ // { readonly nome: string; readonly tamanho: "1-10" | "11-50" | "51-200" | "200+"; readonly orcamento: number; readonly confirmado: boolean }
38
+ ```
39
+
40
+ | Property | What it does |
41
+ |---|---|
42
+ | `type` | `'string'`, `'number'`, `'integer'` or `'boolean'`. Values are coerced to it on the way in. |
43
+ | `enum` | The allowed values. A value outside the list is dropped. It becomes a literal union in `Data`. |
44
+ | `description` | What the field means, for the model. |
45
+ | `ask` | How the model should ask for it. A step may override it. |
46
+ | `extract` | Where a value may come from: `'anywhere'` or `'asked'`. The default depends on `type`, below. |
47
+
48
+ `f.fields()` binds the data type, so `collect`, `ask`, `clearOnStart`, `{ step, clear }`, `if: { equals }` and an action's `ctx.set()` are all checked against these field names at compile time. The collected values live in `session.data` as a `Partial<Data>`.
49
+
50
+ ## Known and pending
51
+
52
+ A field is **known** when its value is not `undefined`, `null` or `''`. Anything else is unknown. There is no "asked but refused" state, only a count.
53
+
54
+ A talk step's **pending** fields are computed by code every time the step is reached or has spoken:
55
+
56
+ ```text
57
+ pending = step.collect − known fields − fields asked maxAsks times (in collect order)
58
+ ```
59
+
60
+ Three things follow.
61
+
62
+ - Fields land in any order. When the first message says "sou a Ana da Zeta, somos 30", three fields become known at once, one of them belonging to a later step.
63
+ - A step with nothing pending is skipped with no model call: outcome `code: 'already-known'`. A run that was asking and finds its fields known on the next message logs `ok` and moves on.
64
+ - A step stays `asking` until its pending set is empty or a branch fires. There is no deadlock: `maxAsks` empties the set eventually.
65
+
66
+ ## Where values come from
67
+
68
+ Four writers reach `session.data`. Two are the model, two are your code.
69
+
70
+ | Writer | Which fields | When |
71
+ |---|---|---|
72
+ | The understand call | Unknown fields with `extract: 'anywhere'` listed by any talk step of the floor's flow or of a candidate `message` flow | On a message, before runs move |
73
+ | The speak call | The speaking step's pending fields, whatever their `extract`, in the envelope `{ message, ...fields }` | When the step speaks |
74
+ | A tool's `data` | Whatever the tool returns | During a speak round, written as given |
75
+ | An action's `ctx.set(patch)` | Whatever the action writes | During a `do` step, written as given |
76
+
77
+ Values from the model are validated before they are written. Each dropped value leaves an outcome line instead of a write:
78
+
79
+ | Check | Outcome detail |
80
+ |---|---|
81
+ | The name is not one of the agent's fields | `code: 'unknown-field'` |
82
+ | The value does not fit the type | `code: 'bad-value'` |
83
+ | The value is not in `enum` | `code: 'not-in-enum'` |
84
+
85
+ Coercion is forgiving (`coerceField` in `src/utils/schema.ts`):
86
+
87
+ - `"30"` becomes the number 30; a comma is a decimal separator, so `"1,5"` is 1.5.
88
+ - An `integer` is truncated.
89
+ - A boolean reads `true`, `sim`, `yes`, `1` as true and `false`, `não`, `nao`, `no`, `0` as false.
90
+ - A number or boolean offered for a string is stringified.
91
+
92
+ ## `extract`: anywhere or asked
93
+
94
+ `extract` says where a value may come from.
95
+
96
+ - `'anywhere'`: from any customer message, by the understand call, before the run moves. The default for `string`, `number` and `integer`.
97
+ - `'asked'`: only from the reply to the step that lists the field, by the speak envelope. The default for `boolean`, so a stray "sim" in an unrelated message never confirms anything.
98
+
99
+ The default is `extractMode` in `src/utils/schema.ts`: `def.extract ?? (def.type === 'boolean' ? 'asked' : 'anywhere')`. Set it when the default is wrong for you: a document number you want only when asked, or a boolean the customer often volunteers.
100
+
101
+ This split also decides which call spends tokens on what. On a message, the understand call lists every unknown `'anywhere'` field of the flows in play; the speak call lists only the current step's pending fields. A turn where everything the step needs is `'asked'` and no other flow is eligible skips the understand call entirely: one call for the whole turn (`tests/scenarios/s01-triagem.test.ts`, the correction test).
102
+
103
+ ## `maxAsks`
104
+
105
+ `maxAsks` on a talk step is how many times a field may be asked before the step gives up on it. The default is 3 (`DEFAULT_MAX_ASKS` in `src/utils/schema.ts`).
106
+
107
+ `run.asked[field]` goes up by one each time the step speaks and the field is still unknown after that reply's own extraction. A field that reaches the ceiling drops out of the pending set. When the set is empty the step reports it and moves to `then`:
108
+
109
+ ```text
110
+ { kind: 'collect', status: 'skipped', code: 'max-asks', detail: 'orcamento' }
111
+ ```
112
+
113
+ One line per field that ran out of asks, with the field's slug in `detail`. `maxAsks: 1` means "ask once, do not insist". The field stays unknown: a later step may still collect it, and a later run of the flow starts the count again, because `asked` lives on the run.
114
+
115
+ ## Known fields are never re-extracted
116
+
117
+ Once a field is known it disappears from both calls: the understand call does not list it, the speak envelope does not carry it, and the prompt shows it under "Already known" with the instruction never to ask again. This keeps both calls small, and it means a correction cannot happen by itself. To let the customer change a value, clear it:
118
+
119
+ - `then: { step: 'quem', clear: ['confirmado', 'empresa'] }` clears the fields, then jumps. This is the idiom for a confirmation gate: a "no" clears the disputed field and re-asks it.
120
+ - `clearOnStart: ['confirmado']` on a flow clears the fields when a run starts, before this turn's extraction lands. This is the idiom for `repeat: 'always'` flows that must ask again.
121
+ - `ctx.set({ empresa: undefined })` from a `do` step.
122
+
123
+ `onEnd: 'reset'` keeps the data: the new run starts at step one with everything still known, so only the steps whose fields were cleared will ask.
124
+
125
+ ```ts
126
+ import { falai } from "@falai/agent";
127
+
128
+ const f = falai().fields({
129
+ nome: { type: "string", ask: "Pergunte o nome." },
130
+ empresa: { type: "string", ask: "Pergunte de qual empresa a pessoa fala." },
131
+ orcamento: { type: "number", ask: "Pergunte a faixa de investimento." },
132
+ confirmado: { type: "boolean", ask: "Resuma o que anotou e pergunte se está tudo certo." },
133
+ });
134
+
135
+ const triagem = f.flow({
136
+ id: "triagem",
137
+ name: "Triagem",
138
+ on: [{ message: ["quer saber como funciona"], repeat: "always" }],
139
+ clearOnStart: ["confirmado"],
140
+ steps: [
141
+ { id: "quem", prompt: "Descubra quem é e de onde fala.", collect: ["nome", "empresa"] },
142
+ { id: "grana", collect: ["orcamento"], ask: { orcamento: "Pergunte quanto {{data.empresa}} pensa em investir por mês." }, maxAsks: 2 },
143
+ { id: "confirma", collect: ["confirmado"] },
144
+ { id: "ok", if: { equals: { confirmado: true } }, else: { step: "quem", clear: ["confirmado", "empresa"] } },
145
+ { id: "tchau", say: "Obrigada, {{data.nome}}. Um vendedor continua daqui." },
146
+ ],
147
+ });
148
+
149
+ export { triagem };
150
+ ```
151
+
152
+ ## The wording
153
+
154
+ Three layers of text shape the question, from general to specific.
155
+
156
+ 1. The field's `ask`: the default wording for that field everywhere.
157
+ 2. The step's `ask: { orcamento: '…' }`: wins over the field's, for that step only.
158
+ 3. The step's `prompt`: the guideline for the whole reply. Without one, the default is "Collect what is still missing below, in the flow of the conversation, one or two things per message."
159
+
160
+ All three are templates: `{{data.x}}`, `{{context.x}}` and `{{input.x}}` are filled in before the model reads them. The model sees every pending field of the step with its wording, in collect order, and is told to ask at the pace the prompt sets and to take any value the customer's message already answers.
161
+
162
+ ## What the provider sees
163
+
164
+ `toWireSchema` in `src/utils/schema.ts` is the only way a field definition reaches a provider. It keeps `type`, `description` and `enum` and strips `ask`, `extract` and `optional`: those are for the framework, not the model. The result is a closed JSON schema (`additionalProperties: false`). In both envelopes every property is required and nullable, so the model must answer each field with a value or `null`. A field name that is not a legal property name for the provider, or is spelled `message`, travels under an alias and is mapped back on the way out.
165
+
166
+ ## Where next
167
+
168
+ - [Collect data](../start/03-collect-data.md): the same ideas as a tutorial.
169
+ - [Branching](../guides/branching.md): `when` and `if` branches on a talk step.
170
+ - [Fields](../reference/fields.md): `FieldDef`, `ScalarDef`, `DataOf`, `InferData`.