@falai/agent 3.4.5 → 4.0.0-alpha.2

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 (856) 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 +11 -6
  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/providers/ZaiProvider.d.ts +6 -4
  100. package/dist/cjs/providers/ZaiProvider.d.ts.map +1 -1
  101. package/dist/cjs/providers/ZaiProvider.js +6 -4
  102. package/dist/cjs/providers/ZaiProvider.js.map +1 -1
  103. package/dist/cjs/types/agent.d.ts +153 -383
  104. package/dist/cjs/types/agent.d.ts.map +1 -1
  105. package/dist/cjs/types/agent.js +1 -1
  106. package/dist/cjs/types/ai.d.ts +32 -1
  107. package/dist/cjs/types/ai.d.ts.map +1 -1
  108. package/dist/cjs/types/compaction.d.ts +3 -1
  109. package/dist/cjs/types/compaction.d.ts.map +1 -1
  110. package/dist/cjs/types/errors.d.ts +9 -12
  111. package/dist/cjs/types/errors.d.ts.map +1 -1
  112. package/dist/cjs/types/errors.js +14 -17
  113. package/dist/cjs/types/errors.js.map +1 -1
  114. package/dist/cjs/types/flow.d.ts +265 -513
  115. package/dist/cjs/types/flow.d.ts.map +1 -1
  116. package/dist/cjs/types/flow.js +7 -1
  117. package/dist/cjs/types/flow.js.map +1 -1
  118. package/dist/cjs/types/history.d.ts +7 -18
  119. package/dist/cjs/types/history.d.ts.map +1 -1
  120. package/dist/cjs/types/history.js.map +1 -1
  121. package/dist/cjs/types/index.d.ts +9 -15
  122. package/dist/cjs/types/index.d.ts.map +1 -1
  123. package/dist/cjs/types/index.js +4 -14
  124. package/dist/cjs/types/index.js.map +1 -1
  125. package/dist/cjs/types/session.d.ts +94 -64
  126. package/dist/cjs/types/session.d.ts.map +1 -1
  127. package/dist/cjs/types/session.js +5 -1
  128. package/dist/cjs/types/session.js.map +1 -1
  129. package/dist/cjs/types/tool.d.ts +37 -207
  130. package/dist/cjs/types/tool.d.ts.map +1 -1
  131. package/dist/cjs/types/tool.js +5 -14
  132. package/dist/cjs/types/tool.js.map +1 -1
  133. package/dist/cjs/utils/clock.d.ts +28 -0
  134. package/dist/cjs/utils/clock.d.ts.map +1 -0
  135. package/dist/cjs/utils/clock.js +64 -0
  136. package/dist/cjs/utils/clock.js.map +1 -0
  137. package/dist/cjs/utils/duration.d.ts +11 -0
  138. package/dist/cjs/utils/duration.d.ts.map +1 -0
  139. package/dist/cjs/utils/duration.js +31 -0
  140. package/dist/cjs/utils/duration.js.map +1 -0
  141. package/dist/cjs/utils/history.d.ts +4 -1
  142. package/dist/cjs/utils/history.d.ts.map +1 -1
  143. package/dist/cjs/utils/history.js +2 -2
  144. package/dist/cjs/utils/history.js.map +1 -1
  145. package/dist/cjs/utils/index.d.ts +4 -10
  146. package/dist/cjs/utils/index.d.ts.map +1 -1
  147. package/dist/cjs/utils/index.js +14 -61
  148. package/dist/cjs/utils/index.js.map +1 -1
  149. package/dist/cjs/utils/json.d.ts +2 -0
  150. package/dist/cjs/utils/json.d.ts.map +1 -1
  151. package/dist/cjs/utils/json.js +5 -0
  152. package/dist/cjs/utils/json.js.map +1 -1
  153. package/dist/cjs/utils/outcomes.d.ts +48 -0
  154. package/dist/cjs/utils/outcomes.d.ts.map +1 -0
  155. package/dist/cjs/utils/outcomes.js +51 -0
  156. package/dist/cjs/utils/outcomes.js.map +1 -0
  157. package/dist/cjs/utils/schema.d.ts +50 -0
  158. package/dist/cjs/utils/schema.d.ts.map +1 -0
  159. package/dist/cjs/utils/schema.js +138 -0
  160. package/dist/cjs/utils/schema.js.map +1 -0
  161. package/dist/cjs/utils/streamingMessage.d.ts +3 -2
  162. package/dist/cjs/utils/streamingMessage.d.ts.map +1 -1
  163. package/dist/cjs/utils/streamingMessage.js +38 -4
  164. package/dist/cjs/utils/streamingMessage.js.map +1 -1
  165. package/dist/cjs/utils/template.d.ts +13 -149
  166. package/dist/cjs/utils/template.d.ts.map +1 -1
  167. package/dist/cjs/utils/template.js +31 -363
  168. package/dist/cjs/utils/template.js.map +1 -1
  169. package/dist/cjs/utils/usage.d.ts +19 -0
  170. package/dist/cjs/utils/usage.d.ts.map +1 -0
  171. package/dist/cjs/utils/usage.js +35 -0
  172. package/dist/cjs/utils/usage.js.map +1 -0
  173. package/dist/core/Agent.d.ts +22 -378
  174. package/dist/core/Agent.d.ts.map +1 -1
  175. package/dist/core/Agent.js +107 -1181
  176. package/dist/core/Agent.js.map +1 -1
  177. package/dist/core/CompactionEngine.d.ts.map +1 -1
  178. package/dist/core/CompactionEngine.js +5 -3
  179. package/dist/core/CompactionEngine.js.map +1 -1
  180. package/dist/core/FlowSpec.d.ts +136 -0
  181. package/dist/core/FlowSpec.d.ts.map +1 -0
  182. package/dist/core/FlowSpec.js +516 -0
  183. package/dist/core/FlowSpec.js.map +1 -0
  184. package/dist/core/Migrate.d.ts +38 -0
  185. package/dist/core/Migrate.d.ts.map +1 -0
  186. package/dist/core/Migrate.js +264 -0
  187. package/dist/core/Migrate.js.map +1 -0
  188. package/dist/core/Prompt.d.ts +54 -0
  189. package/dist/core/Prompt.d.ts.map +1 -0
  190. package/dist/core/Prompt.js +133 -0
  191. package/dist/core/Prompt.js.map +1 -0
  192. package/dist/core/Runner.d.ts +160 -0
  193. package/dist/core/Runner.d.ts.map +1 -0
  194. package/dist/core/Runner.js +1127 -0
  195. package/dist/core/Runner.js.map +1 -0
  196. package/dist/core/Speak.d.ts +37 -0
  197. package/dist/core/Speak.d.ts.map +1 -0
  198. package/dist/core/Speak.js +360 -0
  199. package/dist/core/Speak.js.map +1 -0
  200. package/dist/core/Understand.d.ts +28 -0
  201. package/dist/core/Understand.d.ts.map +1 -0
  202. package/dist/core/Understand.js +349 -0
  203. package/dist/core/Understand.js.map +1 -0
  204. package/dist/core/contracts.d.ts +122 -0
  205. package/dist/core/contracts.d.ts.map +1 -0
  206. package/dist/core/contracts.js +10 -0
  207. package/dist/core/contracts.js.map +1 -0
  208. package/dist/core/falai.d.ts +57 -0
  209. package/dist/core/falai.d.ts.map +1 -0
  210. package/dist/core/falai.js +40 -0
  211. package/dist/core/falai.js.map +1 -0
  212. package/dist/core/predicate.d.ts +9 -0
  213. package/dist/core/predicate.d.ts.map +1 -0
  214. package/dist/core/predicate.js +54 -0
  215. package/dist/core/predicate.js.map +1 -0
  216. package/dist/index.d.ts +26 -31
  217. package/dist/index.d.ts.map +1 -1
  218. package/dist/index.js +19 -24
  219. package/dist/index.js.map +1 -1
  220. package/dist/persistence/MemoryStore.d.ts +15 -0
  221. package/dist/persistence/MemoryStore.d.ts.map +1 -0
  222. package/dist/persistence/MemoryStore.js +35 -0
  223. package/dist/persistence/MemoryStore.js.map +1 -0
  224. package/dist/persistence/MongoStore.d.ts +42 -0
  225. package/dist/persistence/MongoStore.d.ts.map +1 -0
  226. package/dist/persistence/MongoStore.js +56 -0
  227. package/dist/persistence/MongoStore.js.map +1 -0
  228. package/dist/persistence/OpenSearchStore.d.ts +86 -0
  229. package/dist/persistence/OpenSearchStore.d.ts.map +1 -0
  230. package/dist/persistence/OpenSearchStore.js +116 -0
  231. package/dist/persistence/OpenSearchStore.js.map +1 -0
  232. package/dist/persistence/PostgresStore.d.ts +41 -0
  233. package/dist/persistence/PostgresStore.d.ts.map +1 -0
  234. package/dist/persistence/PostgresStore.js +54 -0
  235. package/dist/persistence/PostgresStore.js.map +1 -0
  236. package/dist/persistence/PrismaStore.d.ts +65 -0
  237. package/dist/persistence/PrismaStore.d.ts.map +1 -0
  238. package/dist/persistence/PrismaStore.js +91 -0
  239. package/dist/persistence/PrismaStore.js.map +1 -0
  240. package/dist/persistence/RedisStore.d.ts +34 -0
  241. package/dist/persistence/RedisStore.d.ts.map +1 -0
  242. package/dist/persistence/RedisStore.js +57 -0
  243. package/dist/persistence/RedisStore.js.map +1 -0
  244. package/dist/persistence/SQLiteStore.d.ts +45 -0
  245. package/dist/persistence/SQLiteStore.d.ts.map +1 -0
  246. package/dist/persistence/SQLiteStore.js +70 -0
  247. package/dist/persistence/SQLiteStore.js.map +1 -0
  248. package/dist/persistence/sessionRow.d.ts +14 -0
  249. package/dist/persistence/sessionRow.d.ts.map +1 -0
  250. package/dist/persistence/sessionRow.js +45 -0
  251. package/dist/persistence/sessionRow.js.map +1 -0
  252. package/dist/providers/DeepSeekProvider.d.ts.map +1 -1
  253. package/dist/providers/DeepSeekProvider.js +8 -3
  254. package/dist/providers/DeepSeekProvider.js.map +1 -1
  255. package/dist/providers/GeminiProvider.d.ts +4 -3
  256. package/dist/providers/GeminiProvider.d.ts.map +1 -1
  257. package/dist/providers/GeminiProvider.js +4 -3
  258. package/dist/providers/GeminiProvider.js.map +1 -1
  259. package/dist/providers/OpenAICompatibleProvider.d.ts +4 -0
  260. package/dist/providers/OpenAICompatibleProvider.d.ts.map +1 -1
  261. package/dist/providers/OpenAICompatibleProvider.js +2 -0
  262. package/dist/providers/OpenAICompatibleProvider.js.map +1 -1
  263. package/dist/providers/OpenRouterProvider.d.ts.map +1 -1
  264. package/dist/providers/OpenRouterProvider.js +2 -4
  265. package/dist/providers/OpenRouterProvider.js.map +1 -1
  266. package/dist/providers/ProviderAdapter.d.ts +11 -6
  267. package/dist/providers/ProviderAdapter.d.ts.map +1 -1
  268. package/dist/providers/ProviderAdapter.js +34 -11
  269. package/dist/providers/ProviderAdapter.js.map +1 -1
  270. package/dist/providers/ZaiProvider.d.ts +6 -4
  271. package/dist/providers/ZaiProvider.d.ts.map +1 -1
  272. package/dist/providers/ZaiProvider.js +6 -4
  273. package/dist/providers/ZaiProvider.js.map +1 -1
  274. package/dist/types/agent.d.ts +153 -383
  275. package/dist/types/agent.d.ts.map +1 -1
  276. package/dist/types/agent.js +1 -1
  277. package/dist/types/ai.d.ts +32 -1
  278. package/dist/types/ai.d.ts.map +1 -1
  279. package/dist/types/compaction.d.ts +3 -1
  280. package/dist/types/compaction.d.ts.map +1 -1
  281. package/dist/types/errors.d.ts +9 -12
  282. package/dist/types/errors.d.ts.map +1 -1
  283. package/dist/types/errors.js +12 -15
  284. package/dist/types/errors.js.map +1 -1
  285. package/dist/types/flow.d.ts +265 -513
  286. package/dist/types/flow.d.ts.map +1 -1
  287. package/dist/types/flow.js +7 -1
  288. package/dist/types/flow.js.map +1 -1
  289. package/dist/types/history.d.ts +7 -18
  290. package/dist/types/history.d.ts.map +1 -1
  291. package/dist/types/history.js.map +1 -1
  292. package/dist/types/index.d.ts +9 -15
  293. package/dist/types/index.d.ts.map +1 -1
  294. package/dist/types/index.js +2 -7
  295. package/dist/types/index.js.map +1 -1
  296. package/dist/types/session.d.ts +94 -64
  297. package/dist/types/session.d.ts.map +1 -1
  298. package/dist/types/session.js +5 -1
  299. package/dist/types/session.js.map +1 -1
  300. package/dist/types/tool.d.ts +37 -207
  301. package/dist/types/tool.d.ts.map +1 -1
  302. package/dist/types/tool.js +6 -13
  303. package/dist/types/tool.js.map +1 -1
  304. package/dist/utils/clock.d.ts +28 -0
  305. package/dist/utils/clock.d.ts.map +1 -0
  306. package/dist/utils/clock.js +59 -0
  307. package/dist/utils/clock.js.map +1 -0
  308. package/dist/utils/duration.d.ts +11 -0
  309. package/dist/utils/duration.d.ts.map +1 -0
  310. package/dist/utils/duration.js +26 -0
  311. package/dist/utils/duration.js.map +1 -0
  312. package/dist/utils/history.d.ts +4 -1
  313. package/dist/utils/history.d.ts.map +1 -1
  314. package/dist/utils/history.js +2 -2
  315. package/dist/utils/history.js.map +1 -1
  316. package/dist/utils/index.d.ts +4 -10
  317. package/dist/utils/index.d.ts.map +1 -1
  318. package/dist/utils/index.js +4 -21
  319. package/dist/utils/index.js.map +1 -1
  320. package/dist/utils/json.d.ts +2 -0
  321. package/dist/utils/json.d.ts.map +1 -1
  322. package/dist/utils/json.js +4 -0
  323. package/dist/utils/json.js.map +1 -1
  324. package/dist/utils/outcomes.d.ts +48 -0
  325. package/dist/utils/outcomes.d.ts.map +1 -0
  326. package/dist/utils/outcomes.js +48 -0
  327. package/dist/utils/outcomes.js.map +1 -0
  328. package/dist/utils/schema.d.ts +50 -0
  329. package/dist/utils/schema.d.ts.map +1 -0
  330. package/dist/utils/schema.js +129 -0
  331. package/dist/utils/schema.js.map +1 -0
  332. package/dist/utils/streamingMessage.d.ts +3 -2
  333. package/dist/utils/streamingMessage.d.ts.map +1 -1
  334. package/dist/utils/streamingMessage.js +38 -4
  335. package/dist/utils/streamingMessage.js.map +1 -1
  336. package/dist/utils/template.d.ts +13 -149
  337. package/dist/utils/template.d.ts.map +1 -1
  338. package/dist/utils/template.js +28 -355
  339. package/dist/utils/template.js.map +1 -1
  340. package/dist/utils/usage.d.ts +19 -0
  341. package/dist/utils/usage.d.ts.map +1 -0
  342. package/dist/utils/usage.js +31 -0
  343. package/dist/utils/usage.js.map +1 -0
  344. package/docs/README.md +37 -19
  345. package/docs/concepts/architecture.md +117 -239
  346. package/docs/concepts/collection.md +170 -0
  347. package/docs/concepts/pipeline.md +132 -378
  348. package/docs/concepts/runs-and-waits.md +192 -0
  349. package/docs/guides/actions-and-events.md +276 -0
  350. package/docs/guides/branching.md +119 -208
  351. package/docs/guides/compaction.md +63 -158
  352. package/docs/guides/conditions.md +164 -128
  353. package/docs/guides/error-handling.md +168 -164
  354. package/docs/guides/flow-control.md +210 -349
  355. package/docs/guides/flows-from-json.md +224 -0
  356. package/docs/guides/instructions.md +125 -161
  357. package/docs/guides/persistence.md +182 -206
  358. package/docs/guides/streaming.md +50 -114
  359. package/docs/guides/testing.md +284 -0
  360. package/docs/guides/triggers.md +401 -0
  361. package/docs/migration/README.md +8 -15
  362. package/docs/migration/v1-to-v2.md +1 -1
  363. package/docs/migration/v2-3-to-v2-4.md +2 -2
  364. package/docs/migration/v2-6-to-v2-7.md +4 -4
  365. package/docs/migration/v3-to-v4.md +452 -0
  366. package/docs/reference/actions-events-conditions.md +396 -0
  367. package/docs/reference/agent.md +244 -0
  368. package/docs/reference/branches.md +75 -203
  369. package/docs/reference/errors.md +188 -144
  370. package/docs/reference/fields.md +125 -0
  371. package/docs/reference/flow-spec.md +248 -0
  372. package/docs/reference/flow.md +104 -192
  373. package/docs/reference/instruction.md +83 -137
  374. package/docs/reference/outcomes.md +273 -0
  375. package/docs/reference/providers.md +525 -302
  376. package/docs/reference/session.md +210 -0
  377. package/docs/reference/step.md +194 -312
  378. package/docs/reference/stores.md +496 -0
  379. package/docs/reference/tool.md +162 -231
  380. package/docs/reference/trigger.md +180 -0
  381. package/docs/rfc/v4-one-flow.md +477 -0
  382. package/docs/start/01-install.md +59 -44
  383. package/docs/start/02-first-agent.md +97 -147
  384. package/docs/start/03-collect-data.md +78 -183
  385. package/docs/start/04-add-tools.md +159 -227
  386. package/docs/start/05-go-to-production.md +167 -164
  387. package/examples/01-quickstart.ts +26 -16
  388. package/examples/02-fields.ts +75 -0
  389. package/examples/03-tools.ts +79 -119
  390. package/examples/04-instructions.ts +60 -87
  391. package/examples/05-branches.ts +78 -0
  392. package/examples/06-triggers-and-waits.ts +148 -0
  393. package/examples/07-streaming.ts +34 -60
  394. package/examples/08-store-and-migration.ts +97 -0
  395. package/examples/09-flows-from-json.ts +107 -0
  396. package/package.json +9 -6
  397. package/src/core/Agent.ts +116 -1512
  398. package/src/core/CompactionEngine.ts +7 -4
  399. package/src/core/FlowSpec.ts +712 -0
  400. package/src/core/Migrate.ts +256 -0
  401. package/src/core/Prompt.ts +156 -0
  402. package/src/core/Runner.ts +1181 -0
  403. package/src/core/Speak.ts +451 -0
  404. package/src/core/Understand.ts +422 -0
  405. package/src/core/contracts.ts +111 -0
  406. package/src/core/falai.ts +86 -0
  407. package/src/core/predicate.ts +56 -0
  408. package/src/index.ts +119 -147
  409. package/src/persistence/MemoryStore.ts +37 -0
  410. package/src/persistence/MongoStore.ts +89 -0
  411. package/src/persistence/OpenSearchStore.ts +153 -0
  412. package/src/persistence/PostgresStore.ts +89 -0
  413. package/src/persistence/PrismaStore.ts +127 -0
  414. package/src/persistence/RedisStore.ts +90 -0
  415. package/src/persistence/SQLiteStore.ts +103 -0
  416. package/src/persistence/sessionRow.ts +45 -0
  417. package/src/providers/DeepSeekProvider.ts +8 -3
  418. package/src/providers/GeminiProvider.ts +4 -3
  419. package/src/providers/OpenAICompatibleProvider.ts +6 -0
  420. package/src/providers/OpenRouterProvider.ts +2 -4
  421. package/src/providers/ProviderAdapter.ts +46 -13
  422. package/src/providers/ZaiProvider.ts +6 -4
  423. package/src/types/agent.ts +124 -397
  424. package/src/types/ai.ts +33 -1
  425. package/src/types/compaction.ts +3 -1
  426. package/src/types/errors.ts +13 -16
  427. package/src/types/flow.ts +249 -550
  428. package/src/types/history.ts +7 -20
  429. package/src/types/index.ts +87 -139
  430. package/src/types/session.ts +135 -70
  431. package/src/types/tool.ts +42 -267
  432. package/src/utils/clock.ts +70 -0
  433. package/src/utils/duration.ts +33 -0
  434. package/src/utils/history.ts +3 -2
  435. package/src/utils/index.ts +8 -66
  436. package/src/utils/json.ts +5 -0
  437. package/src/utils/outcomes.ts +56 -0
  438. package/src/utils/schema.ts +145 -0
  439. package/src/utils/streamingMessage.ts +34 -4
  440. package/src/utils/template.ts +32 -423
  441. package/src/utils/usage.ts +37 -0
  442. package/dist/adapters/MemoryAdapter.d.ts +0 -47
  443. package/dist/adapters/MemoryAdapter.d.ts.map +0 -1
  444. package/dist/adapters/MemoryAdapter.js +0 -204
  445. package/dist/adapters/MemoryAdapter.js.map +0 -1
  446. package/dist/adapters/MongoAdapter.d.ts +0 -97
  447. package/dist/adapters/MongoAdapter.d.ts.map +0 -1
  448. package/dist/adapters/MongoAdapter.js +0 -196
  449. package/dist/adapters/MongoAdapter.js.map +0 -1
  450. package/dist/adapters/OpenSearchAdapter.d.ts +0 -169
  451. package/dist/adapters/OpenSearchAdapter.d.ts.map +0 -1
  452. package/dist/adapters/OpenSearchAdapter.js +0 -471
  453. package/dist/adapters/OpenSearchAdapter.js.map +0 -1
  454. package/dist/adapters/PostgreSQLAdapter.d.ts +0 -85
  455. package/dist/adapters/PostgreSQLAdapter.d.ts.map +0 -1
  456. package/dist/adapters/PostgreSQLAdapter.js +0 -308
  457. package/dist/adapters/PostgreSQLAdapter.js.map +0 -1
  458. package/dist/adapters/PrismaAdapter.d.ts +0 -115
  459. package/dist/adapters/PrismaAdapter.d.ts.map +0 -1
  460. package/dist/adapters/PrismaAdapter.js +0 -406
  461. package/dist/adapters/PrismaAdapter.js.map +0 -1
  462. package/dist/adapters/RedisAdapter.d.ts +0 -72
  463. package/dist/adapters/RedisAdapter.d.ts.map +0 -1
  464. package/dist/adapters/RedisAdapter.js +0 -286
  465. package/dist/adapters/RedisAdapter.js.map +0 -1
  466. package/dist/adapters/SQLiteAdapter.d.ts +0 -86
  467. package/dist/adapters/SQLiteAdapter.d.ts.map +0 -1
  468. package/dist/adapters/SQLiteAdapter.js +0 -337
  469. package/dist/adapters/SQLiteAdapter.js.map +0 -1
  470. package/dist/adapters/index.d.ts +0 -17
  471. package/dist/adapters/index.d.ts.map +0 -1
  472. package/dist/adapters/index.js +0 -11
  473. package/dist/adapters/index.js.map +0 -1
  474. package/dist/adapters/sessionRow.d.ts +0 -22
  475. package/dist/adapters/sessionRow.d.ts.map +0 -1
  476. package/dist/adapters/sessionRow.js +0 -48
  477. package/dist/adapters/sessionRow.js.map +0 -1
  478. package/dist/cjs/adapters/MemoryAdapter.d.ts +0 -47
  479. package/dist/cjs/adapters/MemoryAdapter.d.ts.map +0 -1
  480. package/dist/cjs/adapters/MemoryAdapter.js +0 -208
  481. package/dist/cjs/adapters/MemoryAdapter.js.map +0 -1
  482. package/dist/cjs/adapters/MongoAdapter.d.ts +0 -97
  483. package/dist/cjs/adapters/MongoAdapter.d.ts.map +0 -1
  484. package/dist/cjs/adapters/MongoAdapter.js +0 -200
  485. package/dist/cjs/adapters/MongoAdapter.js.map +0 -1
  486. package/dist/cjs/adapters/OpenSearchAdapter.d.ts +0 -169
  487. package/dist/cjs/adapters/OpenSearchAdapter.d.ts.map +0 -1
  488. package/dist/cjs/adapters/OpenSearchAdapter.js +0 -475
  489. package/dist/cjs/adapters/OpenSearchAdapter.js.map +0 -1
  490. package/dist/cjs/adapters/PostgreSQLAdapter.d.ts +0 -85
  491. package/dist/cjs/adapters/PostgreSQLAdapter.d.ts.map +0 -1
  492. package/dist/cjs/adapters/PostgreSQLAdapter.js +0 -312
  493. package/dist/cjs/adapters/PostgreSQLAdapter.js.map +0 -1
  494. package/dist/cjs/adapters/PrismaAdapter.d.ts +0 -115
  495. package/dist/cjs/adapters/PrismaAdapter.d.ts.map +0 -1
  496. package/dist/cjs/adapters/PrismaAdapter.js +0 -410
  497. package/dist/cjs/adapters/PrismaAdapter.js.map +0 -1
  498. package/dist/cjs/adapters/RedisAdapter.d.ts +0 -72
  499. package/dist/cjs/adapters/RedisAdapter.d.ts.map +0 -1
  500. package/dist/cjs/adapters/RedisAdapter.js +0 -290
  501. package/dist/cjs/adapters/RedisAdapter.js.map +0 -1
  502. package/dist/cjs/adapters/SQLiteAdapter.d.ts +0 -86
  503. package/dist/cjs/adapters/SQLiteAdapter.d.ts.map +0 -1
  504. package/dist/cjs/adapters/SQLiteAdapter.js +0 -341
  505. package/dist/cjs/adapters/SQLiteAdapter.js.map +0 -1
  506. package/dist/cjs/adapters/index.d.ts +0 -17
  507. package/dist/cjs/adapters/index.d.ts.map +0 -1
  508. package/dist/cjs/adapters/index.js +0 -21
  509. package/dist/cjs/adapters/index.js.map +0 -1
  510. package/dist/cjs/adapters/sessionRow.d.ts +0 -22
  511. package/dist/cjs/adapters/sessionRow.d.ts.map +0 -1
  512. package/dist/cjs/adapters/sessionRow.js +0 -52
  513. package/dist/cjs/adapters/sessionRow.js.map +0 -1
  514. package/dist/cjs/constants/index.d.ts +0 -1
  515. package/dist/cjs/constants/index.d.ts.map +0 -1
  516. package/dist/cjs/constants/index.js +0 -4
  517. package/dist/cjs/constants/index.js.map +0 -1
  518. package/dist/cjs/core/AutoChainExecutor.d.ts +0 -97
  519. package/dist/cjs/core/AutoChainExecutor.d.ts.map +0 -1
  520. package/dist/cjs/core/AutoChainExecutor.js +0 -288
  521. package/dist/cjs/core/AutoChainExecutor.js.map +0 -1
  522. package/dist/cjs/core/BranchEvaluator.d.ts +0 -55
  523. package/dist/cjs/core/BranchEvaluator.d.ts.map +0 -1
  524. package/dist/cjs/core/BranchEvaluator.js +0 -125
  525. package/dist/cjs/core/BranchEvaluator.js.map +0 -1
  526. package/dist/cjs/core/DirectiveChainTracker.d.ts +0 -49
  527. package/dist/cjs/core/DirectiveChainTracker.d.ts.map +0 -1
  528. package/dist/cjs/core/DirectiveChainTracker.js +0 -121
  529. package/dist/cjs/core/DirectiveChainTracker.js.map +0 -1
  530. package/dist/cjs/core/Events.d.ts +0 -26
  531. package/dist/cjs/core/Events.d.ts.map +0 -1
  532. package/dist/cjs/core/Events.js +0 -144
  533. package/dist/cjs/core/Events.js.map +0 -1
  534. package/dist/cjs/core/Flow.d.ts +0 -183
  535. package/dist/cjs/core/Flow.d.ts.map +0 -1
  536. package/dist/cjs/core/Flow.js +0 -551
  537. package/dist/cjs/core/Flow.js.map +0 -1
  538. package/dist/cjs/core/FlowRouter.d.ts +0 -183
  539. package/dist/cjs/core/FlowRouter.d.ts.map +0 -1
  540. package/dist/cjs/core/FlowRouter.js +0 -1047
  541. package/dist/cjs/core/FlowRouter.js.map +0 -1
  542. package/dist/cjs/core/PersistenceManager.d.ts +0 -114
  543. package/dist/cjs/core/PersistenceManager.d.ts.map +0 -1
  544. package/dist/cjs/core/PersistenceManager.js +0 -336
  545. package/dist/cjs/core/PersistenceManager.js.map +0 -1
  546. package/dist/cjs/core/PromptComposer.d.ts +0 -47
  547. package/dist/cjs/core/PromptComposer.d.ts.map +0 -1
  548. package/dist/cjs/core/PromptComposer.js +0 -397
  549. package/dist/cjs/core/PromptComposer.js.map +0 -1
  550. package/dist/cjs/core/PromptSectionCache.d.ts +0 -48
  551. package/dist/cjs/core/PromptSectionCache.d.ts.map +0 -1
  552. package/dist/cjs/core/PromptSectionCache.js +0 -108
  553. package/dist/cjs/core/PromptSectionCache.js.map +0 -1
  554. package/dist/cjs/core/ResponseEngine.d.ts +0 -43
  555. package/dist/cjs/core/ResponseEngine.d.ts.map +0 -1
  556. package/dist/cjs/core/ResponseEngine.js +0 -235
  557. package/dist/cjs/core/ResponseEngine.js.map +0 -1
  558. package/dist/cjs/core/ResponseGenerationError.d.ts +0 -30
  559. package/dist/cjs/core/ResponseGenerationError.d.ts.map +0 -1
  560. package/dist/cjs/core/ResponseGenerationError.js +0 -35
  561. package/dist/cjs/core/ResponseGenerationError.js.map +0 -1
  562. package/dist/cjs/core/ResponseModal.d.ts +0 -305
  563. package/dist/cjs/core/ResponseModal.d.ts.map +0 -1
  564. package/dist/cjs/core/ResponseModal.js +0 -1414
  565. package/dist/cjs/core/ResponseModal.js.map +0 -1
  566. package/dist/cjs/core/ResponsePipeline.d.ts +0 -220
  567. package/dist/cjs/core/ResponsePipeline.d.ts.map +0 -1
  568. package/dist/cjs/core/ResponsePipeline.js +0 -1040
  569. package/dist/cjs/core/ResponsePipeline.js.map +0 -1
  570. package/dist/cjs/core/SessionFinalizer.d.ts +0 -34
  571. package/dist/cjs/core/SessionFinalizer.d.ts.map +0 -1
  572. package/dist/cjs/core/SessionFinalizer.js +0 -88
  573. package/dist/cjs/core/SessionFinalizer.js.map +0 -1
  574. package/dist/cjs/core/SessionManager.d.ts +0 -112
  575. package/dist/cjs/core/SessionManager.d.ts.map +0 -1
  576. package/dist/cjs/core/SessionManager.js +0 -308
  577. package/dist/cjs/core/SessionManager.js.map +0 -1
  578. package/dist/cjs/core/SignalCoordinator.d.ts +0 -103
  579. package/dist/cjs/core/SignalCoordinator.d.ts.map +0 -1
  580. package/dist/cjs/core/SignalCoordinator.js +0 -207
  581. package/dist/cjs/core/SignalCoordinator.js.map +0 -1
  582. package/dist/cjs/core/SignalEvaluator.d.ts +0 -86
  583. package/dist/cjs/core/SignalEvaluator.d.ts.map +0 -1
  584. package/dist/cjs/core/SignalEvaluator.js +0 -319
  585. package/dist/cjs/core/SignalEvaluator.js.map +0 -1
  586. package/dist/cjs/core/SignalProcessor.d.ts +0 -152
  587. package/dist/cjs/core/SignalProcessor.d.ts.map +0 -1
  588. package/dist/cjs/core/SignalProcessor.js +0 -505
  589. package/dist/cjs/core/SignalProcessor.js.map +0 -1
  590. package/dist/cjs/core/Step.d.ts +0 -184
  591. package/dist/cjs/core/Step.d.ts.map +0 -1
  592. package/dist/cjs/core/Step.js +0 -599
  593. package/dist/cjs/core/Step.js.map +0 -1
  594. package/dist/cjs/core/StepLifecycle.d.ts +0 -43
  595. package/dist/cjs/core/StepLifecycle.d.ts.map +0 -1
  596. package/dist/cjs/core/StepLifecycle.js +0 -180
  597. package/dist/cjs/core/StepLifecycle.js.map +0 -1
  598. package/dist/cjs/core/StreamingToolExecutor.d.ts +0 -142
  599. package/dist/cjs/core/StreamingToolExecutor.d.ts.map +0 -1
  600. package/dist/cjs/core/StreamingToolExecutor.js +0 -490
  601. package/dist/cjs/core/StreamingToolExecutor.js.map +0 -1
  602. package/dist/cjs/core/ToolLoopExecutor.d.ts +0 -133
  603. package/dist/cjs/core/ToolLoopExecutor.d.ts.map +0 -1
  604. package/dist/cjs/core/ToolLoopExecutor.js +0 -568
  605. package/dist/cjs/core/ToolLoopExecutor.js.map +0 -1
  606. package/dist/cjs/core/ToolManager.d.ts +0 -250
  607. package/dist/cjs/core/ToolManager.d.ts.map +0 -1
  608. package/dist/cjs/core/ToolManager.js +0 -1104
  609. package/dist/cjs/core/ToolManager.js.map +0 -1
  610. package/dist/cjs/core/createAgent.d.ts +0 -35
  611. package/dist/cjs/core/createAgent.d.ts.map +0 -1
  612. package/dist/cjs/core/createAgent.js +0 -39
  613. package/dist/cjs/core/createAgent.js.map +0 -1
  614. package/dist/cjs/core/flow-namespace.d.ts +0 -64
  615. package/dist/cjs/core/flow-namespace.d.ts.map +0 -1
  616. package/dist/cjs/core/flow-namespace.js +0 -182
  617. package/dist/cjs/core/flow-namespace.js.map +0 -1
  618. package/dist/cjs/core/toolGates.d.ts +0 -24
  619. package/dist/cjs/core/toolGates.d.ts.map +0 -1
  620. package/dist/cjs/core/toolGates.js +0 -52
  621. package/dist/cjs/core/toolGates.js.map +0 -1
  622. package/dist/cjs/types/persistence.d.ts +0 -254
  623. package/dist/cjs/types/persistence.d.ts.map +0 -1
  624. package/dist/cjs/types/persistence.js +0 -7
  625. package/dist/cjs/types/persistence.js.map +0 -1
  626. package/dist/cjs/types/prompt-cache.d.ts +0 -15
  627. package/dist/cjs/types/prompt-cache.d.ts.map +0 -1
  628. package/dist/cjs/types/prompt-cache.js +0 -6
  629. package/dist/cjs/types/prompt-cache.js.map +0 -1
  630. package/dist/cjs/types/signals.d.ts +0 -263
  631. package/dist/cjs/types/signals.d.ts.map +0 -1
  632. package/dist/cjs/types/signals.js +0 -11
  633. package/dist/cjs/types/signals.js.map +0 -1
  634. package/dist/cjs/types/template.d.ts +0 -84
  635. package/dist/cjs/types/template.d.ts.map +0 -1
  636. package/dist/cjs/types/template.js +0 -3
  637. package/dist/cjs/types/template.js.map +0 -1
  638. package/dist/cjs/utils/condition.d.ts +0 -63
  639. package/dist/cjs/utils/condition.d.ts.map +0 -1
  640. package/dist/cjs/utils/condition.js +0 -239
  641. package/dist/cjs/utils/condition.js.map +0 -1
  642. package/dist/cjs/utils/event.d.ts +0 -6
  643. package/dist/cjs/utils/event.d.ts.map +0 -1
  644. package/dist/cjs/utils/event.js +0 -20
  645. package/dist/cjs/utils/event.js.map +0 -1
  646. package/dist/cjs/utils/id.d.ts +0 -33
  647. package/dist/cjs/utils/id.d.ts.map +0 -1
  648. package/dist/cjs/utils/id.js +0 -84
  649. package/dist/cjs/utils/id.js.map +0 -1
  650. package/dist/cjs/utils/serialize.d.ts +0 -36
  651. package/dist/cjs/utils/serialize.d.ts.map +0 -1
  652. package/dist/cjs/utils/serialize.js +0 -77
  653. package/dist/cjs/utils/serialize.js.map +0 -1
  654. package/dist/cjs/utils/session.d.ts +0 -124
  655. package/dist/cjs/utils/session.d.ts.map +0 -1
  656. package/dist/cjs/utils/session.js +0 -396
  657. package/dist/cjs/utils/session.js.map +0 -1
  658. package/dist/constants/index.d.ts +0 -2
  659. package/dist/constants/index.d.ts.map +0 -1
  660. package/dist/constants/index.js +0 -4
  661. package/dist/constants/index.js.map +0 -1
  662. package/dist/core/AutoChainExecutor.d.ts +0 -97
  663. package/dist/core/AutoChainExecutor.d.ts.map +0 -1
  664. package/dist/core/AutoChainExecutor.js +0 -284
  665. package/dist/core/AutoChainExecutor.js.map +0 -1
  666. package/dist/core/BranchEvaluator.d.ts +0 -55
  667. package/dist/core/BranchEvaluator.d.ts.map +0 -1
  668. package/dist/core/BranchEvaluator.js +0 -121
  669. package/dist/core/BranchEvaluator.js.map +0 -1
  670. package/dist/core/DirectiveChainTracker.d.ts +0 -49
  671. package/dist/core/DirectiveChainTracker.d.ts.map +0 -1
  672. package/dist/core/DirectiveChainTracker.js +0 -117
  673. package/dist/core/DirectiveChainTracker.js.map +0 -1
  674. package/dist/core/Events.d.ts +0 -26
  675. package/dist/core/Events.d.ts.map +0 -1
  676. package/dist/core/Events.js +0 -137
  677. package/dist/core/Events.js.map +0 -1
  678. package/dist/core/Flow.d.ts +0 -183
  679. package/dist/core/Flow.d.ts.map +0 -1
  680. package/dist/core/Flow.js +0 -547
  681. package/dist/core/Flow.js.map +0 -1
  682. package/dist/core/FlowRouter.d.ts +0 -183
  683. package/dist/core/FlowRouter.d.ts.map +0 -1
  684. package/dist/core/FlowRouter.js +0 -1043
  685. package/dist/core/FlowRouter.js.map +0 -1
  686. package/dist/core/PersistenceManager.d.ts +0 -114
  687. package/dist/core/PersistenceManager.d.ts.map +0 -1
  688. package/dist/core/PersistenceManager.js +0 -332
  689. package/dist/core/PersistenceManager.js.map +0 -1
  690. package/dist/core/PromptComposer.d.ts +0 -47
  691. package/dist/core/PromptComposer.d.ts.map +0 -1
  692. package/dist/core/PromptComposer.js +0 -393
  693. package/dist/core/PromptComposer.js.map +0 -1
  694. package/dist/core/PromptSectionCache.d.ts +0 -48
  695. package/dist/core/PromptSectionCache.d.ts.map +0 -1
  696. package/dist/core/PromptSectionCache.js +0 -104
  697. package/dist/core/PromptSectionCache.js.map +0 -1
  698. package/dist/core/ResponseEngine.d.ts +0 -43
  699. package/dist/core/ResponseEngine.d.ts.map +0 -1
  700. package/dist/core/ResponseEngine.js +0 -231
  701. package/dist/core/ResponseEngine.js.map +0 -1
  702. package/dist/core/ResponseGenerationError.d.ts +0 -30
  703. package/dist/core/ResponseGenerationError.d.ts.map +0 -1
  704. package/dist/core/ResponseGenerationError.js +0 -31
  705. package/dist/core/ResponseGenerationError.js.map +0 -1
  706. package/dist/core/ResponseModal.d.ts +0 -305
  707. package/dist/core/ResponseModal.d.ts.map +0 -1
  708. package/dist/core/ResponseModal.js +0 -1410
  709. package/dist/core/ResponseModal.js.map +0 -1
  710. package/dist/core/ResponsePipeline.d.ts +0 -220
  711. package/dist/core/ResponsePipeline.d.ts.map +0 -1
  712. package/dist/core/ResponsePipeline.js +0 -1035
  713. package/dist/core/ResponsePipeline.js.map +0 -1
  714. package/dist/core/SessionFinalizer.d.ts +0 -34
  715. package/dist/core/SessionFinalizer.d.ts.map +0 -1
  716. package/dist/core/SessionFinalizer.js +0 -84
  717. package/dist/core/SessionFinalizer.js.map +0 -1
  718. package/dist/core/SessionManager.d.ts +0 -112
  719. package/dist/core/SessionManager.d.ts.map +0 -1
  720. package/dist/core/SessionManager.js +0 -301
  721. package/dist/core/SessionManager.js.map +0 -1
  722. package/dist/core/SignalCoordinator.d.ts +0 -103
  723. package/dist/core/SignalCoordinator.d.ts.map +0 -1
  724. package/dist/core/SignalCoordinator.js +0 -203
  725. package/dist/core/SignalCoordinator.js.map +0 -1
  726. package/dist/core/SignalEvaluator.d.ts +0 -86
  727. package/dist/core/SignalEvaluator.d.ts.map +0 -1
  728. package/dist/core/SignalEvaluator.js +0 -312
  729. package/dist/core/SignalEvaluator.js.map +0 -1
  730. package/dist/core/SignalProcessor.d.ts +0 -152
  731. package/dist/core/SignalProcessor.d.ts.map +0 -1
  732. package/dist/core/SignalProcessor.js +0 -498
  733. package/dist/core/SignalProcessor.js.map +0 -1
  734. package/dist/core/Step.d.ts +0 -184
  735. package/dist/core/Step.d.ts.map +0 -1
  736. package/dist/core/Step.js +0 -594
  737. package/dist/core/Step.js.map +0 -1
  738. package/dist/core/StepLifecycle.d.ts +0 -43
  739. package/dist/core/StepLifecycle.d.ts.map +0 -1
  740. package/dist/core/StepLifecycle.js +0 -176
  741. package/dist/core/StepLifecycle.js.map +0 -1
  742. package/dist/core/StreamingToolExecutor.d.ts +0 -142
  743. package/dist/core/StreamingToolExecutor.d.ts.map +0 -1
  744. package/dist/core/StreamingToolExecutor.js +0 -483
  745. package/dist/core/StreamingToolExecutor.js.map +0 -1
  746. package/dist/core/ToolLoopExecutor.d.ts +0 -133
  747. package/dist/core/ToolLoopExecutor.d.ts.map +0 -1
  748. package/dist/core/ToolLoopExecutor.js +0 -564
  749. package/dist/core/ToolLoopExecutor.js.map +0 -1
  750. package/dist/core/ToolManager.d.ts +0 -250
  751. package/dist/core/ToolManager.d.ts.map +0 -1
  752. package/dist/core/ToolManager.js +0 -1098
  753. package/dist/core/ToolManager.js.map +0 -1
  754. package/dist/core/createAgent.d.ts +0 -35
  755. package/dist/core/createAgent.d.ts.map +0 -1
  756. package/dist/core/createAgent.js +0 -36
  757. package/dist/core/createAgent.js.map +0 -1
  758. package/dist/core/flow-namespace.d.ts +0 -64
  759. package/dist/core/flow-namespace.d.ts.map +0 -1
  760. package/dist/core/flow-namespace.js +0 -179
  761. package/dist/core/flow-namespace.js.map +0 -1
  762. package/dist/core/toolGates.d.ts +0 -24
  763. package/dist/core/toolGates.d.ts.map +0 -1
  764. package/dist/core/toolGates.js +0 -49
  765. package/dist/core/toolGates.js.map +0 -1
  766. package/dist/types/persistence.d.ts +0 -254
  767. package/dist/types/persistence.d.ts.map +0 -1
  768. package/dist/types/persistence.js +0 -6
  769. package/dist/types/persistence.js.map +0 -1
  770. package/dist/types/prompt-cache.d.ts +0 -15
  771. package/dist/types/prompt-cache.d.ts.map +0 -1
  772. package/dist/types/prompt-cache.js +0 -5
  773. package/dist/types/prompt-cache.js.map +0 -1
  774. package/dist/types/signals.d.ts +0 -263
  775. package/dist/types/signals.d.ts.map +0 -1
  776. package/dist/types/signals.js +0 -10
  777. package/dist/types/signals.js.map +0 -1
  778. package/dist/types/template.d.ts +0 -84
  779. package/dist/types/template.d.ts.map +0 -1
  780. package/dist/types/template.js +0 -2
  781. package/dist/types/template.js.map +0 -1
  782. package/dist/utils/condition.d.ts +0 -63
  783. package/dist/utils/condition.d.ts.map +0 -1
  784. package/dist/utils/condition.js +0 -230
  785. package/dist/utils/condition.js.map +0 -1
  786. package/dist/utils/event.d.ts +0 -6
  787. package/dist/utils/event.d.ts.map +0 -1
  788. package/dist/utils/event.js +0 -17
  789. package/dist/utils/event.js.map +0 -1
  790. package/dist/utils/id.d.ts +0 -33
  791. package/dist/utils/id.d.ts.map +0 -1
  792. package/dist/utils/id.js +0 -77
  793. package/dist/utils/id.js.map +0 -1
  794. package/dist/utils/serialize.d.ts +0 -36
  795. package/dist/utils/serialize.d.ts.map +0 -1
  796. package/dist/utils/serialize.js +0 -72
  797. package/dist/utils/serialize.js.map +0 -1
  798. package/dist/utils/session.d.ts +0 -124
  799. package/dist/utils/session.d.ts.map +0 -1
  800. package/dist/utils/session.js +0 -379
  801. package/dist/utils/session.js.map +0 -1
  802. package/docs/concepts/directives.md +0 -369
  803. package/docs/reference/adapters.md +0 -543
  804. package/docs/reference/create-agent.md +0 -216
  805. package/docs/reference/directive.md +0 -242
  806. package/docs/reference/signals.md +0 -368
  807. package/examples/02-data-extraction.ts +0 -90
  808. package/examples/05-branching.ts +0 -140
  809. package/examples/06-flow-control.ts +0 -103
  810. package/examples/08-persistence.ts +0 -98
  811. package/examples/09-signals.ts +0 -144
  812. package/src/adapters/MemoryAdapter.ts +0 -281
  813. package/src/adapters/MongoAdapter.ts +0 -341
  814. package/src/adapters/OpenSearchAdapter.ts +0 -693
  815. package/src/adapters/PostgreSQLAdapter.ts +0 -487
  816. package/src/adapters/PrismaAdapter.ts +0 -617
  817. package/src/adapters/RedisAdapter.ts +0 -439
  818. package/src/adapters/SQLiteAdapter.ts +0 -496
  819. package/src/adapters/index.ts +0 -43
  820. package/src/adapters/sessionRow.ts +0 -57
  821. package/src/constants/index.ts +0 -2
  822. package/src/core/AutoChainExecutor.ts +0 -397
  823. package/src/core/BranchEvaluator.ts +0 -161
  824. package/src/core/DirectiveChainTracker.ts +0 -144
  825. package/src/core/Events.ts +0 -164
  826. package/src/core/Flow.ts +0 -665
  827. package/src/core/FlowRouter.ts +0 -1540
  828. package/src/core/PersistenceManager.ts +0 -446
  829. package/src/core/PromptComposer.ts +0 -448
  830. package/src/core/PromptSectionCache.ts +0 -125
  831. package/src/core/ResponseEngine.ts +0 -338
  832. package/src/core/ResponseGenerationError.ts +0 -53
  833. package/src/core/ResponseModal.ts +0 -1902
  834. package/src/core/ResponsePipeline.ts +0 -1404
  835. package/src/core/SessionFinalizer.ts +0 -108
  836. package/src/core/SessionManager.ts +0 -372
  837. package/src/core/SignalCoordinator.ts +0 -263
  838. package/src/core/SignalEvaluator.ts +0 -404
  839. package/src/core/SignalProcessor.ts +0 -663
  840. package/src/core/Step.ts +0 -782
  841. package/src/core/StepLifecycle.ts +0 -242
  842. package/src/core/StreamingToolExecutor.ts +0 -609
  843. package/src/core/ToolLoopExecutor.ts +0 -749
  844. package/src/core/ToolManager.ts +0 -1379
  845. package/src/core/createAgent.ts +0 -40
  846. package/src/core/flow-namespace.ts +0 -227
  847. package/src/core/toolGates.ts +0 -72
  848. package/src/types/persistence.ts +0 -303
  849. package/src/types/prompt-cache.ts +0 -17
  850. package/src/types/signals.ts +0 -338
  851. package/src/types/template.ts +0 -98
  852. package/src/utils/condition.ts +0 -296
  853. package/src/utils/event.ts +0 -16
  854. package/src/utils/id.ts +0 -91
  855. package/src/utils/serialize.ts +0 -86
  856. package/src/utils/session.ts +0 -501
@@ -1,369 +1,449 @@
1
1
  ---
2
2
  title: "Providers"
3
- description: "Strategy classes that connect an Agent to Gemini, OpenAI, Anthropic, OpenRouter, or DeepSeek — plus the base class for building your own."
3
+ description: "Every provider class the package exports, the AiProvider interface they implement, and the retry, backup and fallback options they share."
4
4
  type: reference
5
- order: 10
5
+ order: 15
6
6
  ---
7
7
 
8
8
  # Providers
9
9
 
10
- > **Where this is introduced:** [Install](../start/01-install.md)
10
+ A provider is the object the agent talks to the model through. You build one and pass it as `provider` to `f.agent()`; the agent calls it for the understand call and the speak call of every turn. All built-in providers implement the same `AiProvider` interface, so changing vendors is one constructor. There is no vendor SDK behind them: each is a thin binding over [`@providerkit/core`](https://www.npmjs.com/package/@providerkit/core), which speaks every vendor's REST API over `fetch`.
11
11
 
12
- Providers are the strategy plug between an `Agent` and a model vendor. Every provider implements the same `AiProvider` interface, so the Agent itself stays vendor-agnostic. Pass an instance to `createAgent({ provider })` and the agent talks to that vendor for every turn (and for compaction, if you wire it in).
12
+ ```ts
13
+ import { GeminiProvider } from "@falai/agent";
13
14
 
14
- `@falai/agent` ships five built-in providers. All five accept an `apiKey` and a required `model`, support `backupModels` for automatic failover, and take the same neutral `RequestConfig` for sampling defaults.
15
-
16
- There are no vendor SDKs behind them. Every provider is a thin binding over [`@providerkit/core`](https://www.npmjs.com/package/@providerkit/core), which speaks each vendor's REST API over `fetch` — so installing this package does not install one vendor's SDK for a consumer who uses another.
17
-
18
- | Provider | Class | Options | Wire |
19
- |----------|-------|---------|------|
20
- | Google Gemini | `GeminiProvider` | `GeminiProviderOptions` | `generateContent` (SSE) |
21
- | OpenAI | `OpenAIProvider` | `OpenAIProviderOptions` | Responses API |
22
- | Anthropic Claude | `AnthropicProvider` | `AnthropicProviderOptions` | Messages API |
23
- | OpenRouter | `OpenRouterProvider` | `OpenRouterProviderOptions` | chat completions |
24
- | DeepSeek | `DeepSeekProvider` | `DeepSeekProviderOptions` | chat completions |
25
-
26
- ## Capabilities
27
-
28
- Every provider declares a required `capabilities: ProviderCapabilities` field — five static flags the engine reads to decide how to drive the vendor (e.g., whether structured output is schema-enforced or prompt-instructed). Custom `AiProvider` implementations **must** declare it.
29
-
30
- ```typescript
31
- interface ProviderCapabilities {
32
- supportsTools: boolean; // tool/function calling
33
- supportsNativeJsonSchema: boolean; // native JSON-schema-enforced output (vs. prompt-based JSON instruction)
34
- supportsStreaming: boolean; // streaming responses
35
- supportsStreamingToolCalls: boolean; // tool calls surfaced during streaming
36
- supportsPromptCaching: boolean; // prompt caching
37
- }
38
- ```
39
-
40
- The five built-ins:
41
-
42
- | Capability | Gemini | OpenAI | Anthropic | OpenRouter | DeepSeek |
43
- |------------|--------|--------|-----------|------------|----------|
44
- | `supportsTools` | ✅ | ✅ | ✅ | ✅ | ✅ |
45
- | `supportsNativeJsonSchema` | ✅ | ✅ | ❌ | ✅ | ✅ |
46
- | `supportsStreaming` | ✅ | ✅ | ✅ | ✅ | ✅ |
47
- | `supportsStreamingToolCalls` | ✅ | ✅ | ✅ | ✅ | ✅ |
48
- | `supportsPromptCaching` | ❌ | ❌ | ✅ | ❌ | ❌ |
49
-
50
- The two asymmetries: Anthropic reports `supportsNativeJsonSchema: false` because its JSON output is enforced via a prompt instruction, not a native schema mode — and it is the only built-in that reports `supportsPromptCaching: true`.
51
-
52
- These flags describe the vendor. What a given **model** does is a separate question, and one of them will cost you a production agent if you guess it — see below.
53
-
54
- ## When the agent narrates a tool instead of calling it
55
-
56
- The symptom: the model answers a turn that clearly needs a tool by *describing* the tool call — _"let me look that price up for you"_ — and stops. The tool handler never runs. It looks like a model with no initiative, and no instruction fixes it.
57
-
58
- It is not the prompt. Every turn this framework sends carries a response schema, because that is how `message` and `collect` fields come back. Some models cannot emit a tool call while their output is pinned to a schema: the call has nowhere to go, so they write the announcement instead. Nothing fails, nothing is logged, and the turn succeeds on the wire.
59
-
60
- Measured 2026-09-07, same request, sampled:
61
-
62
- | model | tool called | with `jsonWithTools: "prompt"` |
63
- |-------|-------------|-------------------------------|
64
- | `z-ai/glm-5.3-flash` | 0/10 | 8/8 |
65
- | `deepseek-v4-flash-0731` | 0/5 | — |
66
- | `gemini-3.8-flash` | 3/10 | — |
67
- | `gemini-3.5-flash-lite` | 10/10 | 6/6 |
68
- | `gpt-5.6-luna` | 10/10 | 6/6 |
69
- | `qwen3.8-flash` | 10/10 | 1/6 |
70
-
71
- `jsonWithTools: "prompt"` on `OpenRouterProvider`, `DeepSeekProvider`, `GeminiProvider` or `createOpenAICompatibleProvider` leaves the response format off the calls that carry tools and sends the schema as prompt there instead. Calls without tools are untouched.
72
-
73
- Do not pick it from the table — the qwen row is why. Ask the model, once, at boot:
74
-
75
- ```typescript
76
- import { probeJsonWithTools } from "@providerkit/core";
77
-
78
- const probe = await probeJsonWithTools(provider);
79
- // { use: "prompt", calls: { response_format: 0, prompt: 3 }, samples: 3 }
80
- if (!probe.use) throw new Error("this model cannot use tools with a schema at all");
15
+ const provider = new GeminiProvider({ apiKey: process.env.GEMINI_API_KEY ?? "", model: "gemini-2.5-flash" });
16
+ console.log(provider.name); // "gemini"
81
17
  ```
82
18
 
83
- Log `calls`, not just `use`. `0/3 and 3/3` is what makes the next model swap's regression obvious.
84
-
85
- ## Use with createAgent
86
-
87
- `createAgent({ provider })` accepts any class that implements `AiProvider`. Swap providers by changing the constructor; nothing else in your agent has to move.
88
-
89
- ```typescript
90
- import {
91
- createAgent,
92
- GeminiProvider,
93
- OpenAIProvider,
94
- AnthropicProvider,
95
- OpenRouterProvider,
96
- DeepSeekProvider,
97
- } from "@falai/agent";
98
-
99
- const provider =
100
- process.env.PROVIDER === "openai"
101
- ? new OpenAIProvider({ apiKey: process.env.OPENAI_API_KEY!, model: "gpt-5.6" })
102
- : process.env.PROVIDER === "anthropic"
103
- ? new AnthropicProvider({ apiKey: process.env.ANTHROPIC_API_KEY!, model: "claude-sonnet-5" })
104
- : process.env.PROVIDER === "openrouter"
105
- ? new OpenRouterProvider({ apiKey: process.env.OPENROUTER_API_KEY!, model: "anthropic/claude-sonnet-5" })
106
- : process.env.PROVIDER === "deepseek"
107
- ? new DeepSeekProvider({ apiKey: process.env.DEEPSEEK_API_KEY!, model: "deepseek-chat" })
108
- : new GeminiProvider({ apiKey: process.env.GEMINI_API_KEY!, model: "gemini-3.1-pro-preview" });
109
-
110
- const agent = createAgent({ provider, schema, flows });
111
- ```
19
+ ## The exported providers
20
+
21
+ | Export | Options type | Talks to | `name` | Structured output |
22
+ |--------|--------------|----------|--------|-------------------|
23
+ | `GeminiProvider` | `GeminiProviderOptions` | Google Gemini, `generateContent` | `gemini` | native response schema |
24
+ | `OpenAIProvider` | `OpenAIProviderOptions` | OpenAI, Responses API | `openai` | native (`responses_parse`) |
25
+ | `AnthropicProvider` | `AnthropicProviderOptions` | Anthropic, Messages API | `anthropic` | schema in a system block |
26
+ | `OpenRouterProvider` | `OpenRouterProviderOptions` | OpenRouter, chat completions | `openrouter` | native (`json_schema`) |
27
+ | `DeepSeekProvider` | `DeepSeekProviderOptions` | DeepSeek, chat completions | `deepseek` | native (`json_schema`) |
28
+ | `ZaiProvider` | `ZaiProviderOptions` | Z.ai Coding Plan, Anthropic-compatible | `zai` | schema in a system block |
29
+ | `FallbackAiProvider` | `FallbackAiProviderOptions` | an ordered list of the above | `fallback(a->b)` | the list's intersection |
30
+ | `createOpenAICompatibleProvider()` | `OpenAICompatibleOptions` | any OpenAI-compatible endpoint | your `name` | `json_schema` by default |
31
+ | `OpenAICompatibleProvider` | `OpenAICompatibleProviderInit` | abstract base for the chat-completions dialect | yours | per `structuredOutput` |
32
+ | `ProviderAdapter` | `ProviderAdapterInit` | abstract base for any `@providerkit/core` provider | yours | yours |
33
+
34
+ ### Capabilities
35
+
36
+ Every provider carries `capabilities: ProviderCapabilities`, five flags that describe what the implementation does. From each class in `src/providers/`.
37
+
38
+ | Flag | Gemini | OpenAI | Anthropic | OpenRouter | DeepSeek | Z.ai | `createOpenAICompatibleProvider` default |
39
+ |------|--------|--------|-----------|------------|----------|------|------------------------------------------|
40
+ | `supportsTools` | yes | yes | yes | yes | yes | yes | yes |
41
+ | `supportsNativeJsonSchema` | yes | yes | no | yes | no | no | yes |
42
+ | `supportsStreaming` | yes | yes | yes | yes | yes | yes | yes |
43
+ | `supportsStreamingToolCalls` | yes | yes | yes | yes | yes | yes | yes |
44
+ | `supportsPromptCaching` | yes | yes | yes | yes | yes | yes | no |
45
+
46
+ Anthropic has no native schema mode, so the schema is sent as an extra system block after the cached one; Z.ai is Anthropic-compatible and reports the same flag, and DeepSeek serves JSON mode but not a schema. In all three the schema reaches the model as prompt, which is why Gemini's own limit matters: on Gemini 2 a response schema and tools cannot ride the same call (`400 "Function calling with a response mime type: 'application/json' is unsupported"`), so those calls send the schema as prompt too. Gemini 3 takes both. `FallbackAiProvider` reports a flag as true only when every provider in its list does. `createOpenAICompatibleProvider` takes `capabilities` overrides merged over its defaults.
47
+
48
+ ## Options every vendor provider takes
49
+
50
+ The six vendor classes share these fields. Where a provider adds or renames one, its own section says so.
51
+
52
+ | Field | Type | Default | Meaning |
53
+ |-------|------|---------|---------|
54
+ | `apiKey` | `string` | required | The vendor key. An empty string throws at construction. |
55
+ | `model` | `string` | required (Z.ai: `glm-5.3-flash`) | The model id. |
56
+ | `backupModels` | `string[]` | `[]` | Tried in order on the same provider when a call fails with a kind that is backup-eligible in `@providerkit/core`, or with `model`. |
57
+ | `fallbacks` | `Array<AiProvider \| Provider>` | none | Other providers tried after this one fails or is on cooldown. Takes this package's providers and `@providerkit/core` providers alike. |
58
+ | `fallbackOptions` | `FallbackOptions<Provider>` | none | Cooldowns per error kind and an `onCooldown` callback for `fallbacks`. Gemini, Anthropic and Z.ai only. |
59
+ | `config` | `RequestConfig` | none | Sampling defaults sent with every call: `temperature`, `topP`, `maxTokens`, `stopSequences`, `effort`. |
60
+ | `retryConfig` | `{ timeout?: number; retries?: number }` | `{ timeout: 60000, retries: 3 }` | Idle-stream deadline in ms and retries after the first attempt. See [Retries](#retries-backup-models-and-fallbacks). |
61
+ | `fetchImpl` | `typeof fetch` | global `fetch` | A replacement `fetch`, for tests that script the wire. |
112
62
 
113
63
  ## GeminiProvider
114
64
 
115
- ### Signature
116
-
117
- ```typescript
118
- new GeminiProvider(options: GeminiProviderOptions)
119
-
65
+ ```ts fragment
120
66
  interface GeminiProviderOptions {
121
67
  apiKey: string;
122
68
  model: string;
123
69
  backupModels?: string[];
70
+ fallbacks?: Array<AiProvider | Provider>;
71
+ fallbackOptions?: FallbackOptions<Provider>;
72
+ /** Any endpoint speaking the Gemini generateContent dialect. */
124
73
  baseUrl?: string;
125
74
  jsonWithTools?: "response_format" | "prompt";
126
- config?: RequestConfig; // temperature, topP, maxTokens, stopSequences
75
+ config?: RequestConfig;
127
76
  retryConfig?: { timeout?: number; retries?: number };
128
- fetchImpl?: typeof fetch; // scripted wire, for tests
77
+ fetchImpl?: typeof fetch;
129
78
  }
130
79
  ```
131
80
 
132
- ### Fields
133
-
134
- | Field | Type | Required | Default | Notes |
135
- |-------|------|----------|---------|-------|
136
- | `apiKey` | `string` | yes* | — | Throws if empty (unless `client` is set). |
137
- | `model` | `string` | yes | — | Use the model id, e.g. `"gemini-3.1-pro-preview"`. |
138
- | `backupModels` | `string[]` | no | `[]` | Tried in order on retriable failures (rate limits, overload, timeouts, network). |
139
- | `jsonWithTools` | `"response_format" \| "prompt"` | no | `"response_format"` | How the schema rides on calls that also carry tools. `gemini-3.5-flash` and `-flash-lite` need nothing; `gemini-3.8-flash` measured 3/10 — [see above](#when-the-agent-narrates-a-tool-instead-of-calling-it). |
140
- | `config` | `Partial<GenerateContentConfig>` | no | — | Vendor-typed defaults (e.g. `temperature`, `systemInstruction`). |
141
- | `retryConfig.timeout` | `number` | no | `60000` | Per-attempt timeout in ms. On streams it also bounds time-to-first-token. |
142
- | `retryConfig.retries` | `number` | no | `3` | Total attempts before giving up. |
143
- | `client` | `GoogleGenAI` | no | — | Pre-configured SDK client; overrides the internally-constructed one. Intended for tests injecting scripted transports; production callers should pass `apiKey`. |
81
+ ```ts
82
+ import { GeminiProvider } from "@falai/agent";
144
83
 
145
- ### Example
146
-
147
- ```typescript
148
84
  const gemini = new GeminiProvider({
149
- apiKey: process.env.GEMINI_API_KEY!,
150
- model: "gemini-3.1-pro-preview",
151
- backupModels: ["gemini-3.1-flash-lite"],
85
+ apiKey: process.env.GEMINI_API_KEY ?? "",
86
+ model: "gemini-2.5-flash",
87
+ backupModels: ["gemini-2.5-flash-lite"],
152
88
  config: { temperature: 0.3 },
153
89
  });
154
90
  ```
155
91
 
156
- ## OpenAIProvider
157
-
158
- ### Signature
92
+ Sends the response schema alongside tools when a call carries both. `jsonWithTools` is explained under [When the model narrates a tool](#when-the-model-narrates-a-tool-instead-of-calling-it).
159
93
 
160
- ```typescript
161
- new OpenAIProvider(options: OpenAIProviderOptions)
94
+ ## OpenAIProvider
162
95
 
96
+ ```ts fragment
163
97
  interface OpenAIProviderOptions {
164
98
  apiKey: string;
165
- organization?: string;
166
99
  model: string;
167
100
  backupModels?: string[];
168
- config?: Partial<Omit<ChatCompletionCreateParamsNonStreaming, "model" | "messages">>;
101
+ fallbacks?: Array<AiProvider | Provider>;
102
+ /** Sent as the `OpenAI-Organization` header. */
103
+ organization?: string;
104
+ config?: RequestConfig;
169
105
  retryConfig?: { timeout?: number; retries?: number };
106
+ fetchImpl?: typeof fetch;
170
107
  }
171
108
  ```
172
109
 
173
- ### Fields
174
-
175
- | Field | Type | Required | Default | Notes |
176
- |-------|------|----------|---------|-------|
177
- | `apiKey` | `string` | yes | — | Throws if empty. |
178
- | `organization` | `string` | no | — | Forwarded as `OpenAI-Organization`. |
179
- | `model` | `string` | yes | — | e.g. `"gpt-5.6"`, `"gpt-5.4-mini"`. |
180
- | `backupModels` | `string[]` | no | `[]` | Tried in order on overload/rate-limit errors. |
181
- | `config` | `RequestConfig` | no | — | Defaults for `temperature`, `topP`, `maxTokens`, `stopSequences`. |
182
- | `retryConfig.timeout` | `number` | no | `60000` | Per-attempt timeout in ms. |
183
- | `retryConfig.retries` | `number` | no | `3` | Total attempts. |
184
-
185
- ### Example
110
+ ```ts
111
+ import { OpenAIProvider } from "@falai/agent";
186
112
 
187
- ```typescript
188
113
  const openai = new OpenAIProvider({
189
- apiKey: process.env.OPENAI_API_KEY!,
114
+ apiKey: process.env.OPENAI_API_KEY ?? "",
190
115
  model: "gpt-5.6",
191
116
  organization: "org_abc",
192
- config: { temperature: 0.2 },
193
117
  });
194
118
  ```
195
119
 
196
- ## AnthropicProvider
197
-
198
- ### Signature
120
+ Structured output goes out on the Responses API (`structuredOutput: "responses_parse"`), which enforces the schema natively.
199
121
 
200
- ```typescript
201
- new AnthropicProvider(options: AnthropicProviderOptions)
122
+ ## AnthropicProvider
202
123
 
124
+ ```ts fragment
203
125
  interface AnthropicProviderOptions {
204
126
  apiKey: string;
205
127
  model: string;
206
128
  backupModels?: string[];
207
- config?: Partial<Omit<MessageCreateParamsNonStreaming, "model" | "messages">>;
129
+ fallbacks?: Array<AiProvider | Provider>;
130
+ fallbackOptions?: FallbackOptions<Provider>;
131
+ /** Any endpoint speaking the Anthropic Messages dialect. */
132
+ baseUrl?: string;
133
+ config?: RequestConfig;
208
134
  retryConfig?: { timeout?: number; retries?: number };
209
- client?: Anthropic; // pre-configured SDK client override
135
+ fetchImpl?: typeof fetch;
210
136
  }
211
137
  ```
212
138
 
213
- ### Fields
214
-
215
- | Field | Type | Required | Default | Notes |
216
- |-------|------|----------|---------|-------|
217
- | `apiKey` | `string` | yes* | — | Throws if empty (unless `client` is set). |
218
- | `model` | `string` | yes | — | e.g. `"claude-sonnet-5"`, `"claude-opus-5"`. |
219
- | `backupModels` | `string[]` | no | `[]` | Tried in order on retriable failures (rate limits, overload incl. 529, timeouts, network). |
220
- | `config` | `RequestConfig` | no | — | Defaults for `temperature`, `topP`, `maxTokens`, `stopSequences`. `maxTokens` falls back to 4096 if neither it nor `parameters.maxOutputTokens` is set. |
221
- | `retryConfig.timeout` | `number` | no | `60000` | Per-attempt timeout in ms. On streams it also bounds time-to-first-token. |
222
- | `retryConfig.retries` | `number` | no | `3` | Total attempts. |
223
- | `client` | `Anthropic` | no | — | Pre-configured SDK client; overrides the internally-constructed one. Intended for tests injecting scripted transports; production callers should pass `apiKey`. |
224
-
225
- ### Example
139
+ ```ts
140
+ import { AnthropicProvider } from "@falai/agent";
226
141
 
227
- ```typescript
228
142
  const anthropic = new AnthropicProvider({
229
- apiKey: process.env.ANTHROPIC_API_KEY!,
143
+ apiKey: process.env.ANTHROPIC_API_KEY ?? "",
230
144
  model: "claude-sonnet-5",
231
145
  config: { maxTokens: 8192 },
232
146
  });
233
147
  ```
234
148
 
235
- ## OpenRouterProvider
236
-
237
- OpenRouter is OpenAI-compatible and brokers many vendors behind one endpoint. Use it to A/B-test models without changing client code.
238
-
239
- ### Signature
149
+ No native schema mode: a structured request carries the schema as a system block placed after the cached one, so a per-call schema does not invalidate the system prompt's cache.
240
150
 
241
- ```typescript
242
- new OpenRouterProvider(options: OpenRouterProviderOptions)
151
+ ## OpenRouterProvider
243
152
 
153
+ ```ts fragment
244
154
  interface OpenRouterProviderOptions {
245
155
  apiKey: string;
246
156
  model: string;
247
157
  backupModels?: string[];
158
+ fallbacks?: Array<AiProvider | Provider>;
159
+ /** Sent as `HTTP-Referer`, for OpenRouter's rankings. */
248
160
  siteUrl?: string;
161
+ /** Sent as `X-Title`, for OpenRouter's rankings. */
249
162
  siteName?: string;
163
+ /** Preferred upstream hosts, in order; keeps the prompt cache on one host. */
164
+ providerOrder?: string[];
250
165
  jsonWithTools?: "response_format" | "prompt";
251
- config?: Partial<Omit<ChatCompletionCreateParamsNonStreaming, "model" | "messages">>;
166
+ config?: RequestConfig;
252
167
  retryConfig?: { timeout?: number; retries?: number };
168
+ fetchImpl?: typeof fetch;
253
169
  }
254
170
  ```
255
171
 
256
- ### Fields
257
-
258
- | Field | Type | Required | Default | Notes |
259
- |-------|------|----------|---------|-------|
260
- | `apiKey` | `string` | yes | — | Throws if empty. |
261
- | `model` | `string` | yes | — | OpenRouter model id, e.g. `"anthropic/claude-sonnet-5"`. See [openrouter.ai/models](https://openrouter.ai/models). |
262
- | `backupModels` | `string[]` | no | `[]` | Tried in order on overload/capacity errors. |
263
- | `siteUrl` | `string` | no | `""` | Sent as `HTTP-Referer` for OpenRouter rankings. |
264
- | `siteName` | `string` | no | `""` | Sent as `X-Title` for OpenRouter rankings. |
265
- | `jsonWithTools` | `"response_format" \| "prompt"` | no | `"response_format"` | How the schema rides on calls that also carry tools. One gateway, hundreds of models, and they disagree — [see above](#when-the-agent-narrates-a-tool-instead-of-calling-it). |
266
- | `config` | OpenAI params | no | — | OpenAI-shaped defaults (forwarded to OpenRouter). |
267
- | `retryConfig.timeout` | `number` | no | `60000` | Per-attempt timeout in ms. |
268
- | `retryConfig.retries` | `number` | no | `3` | Total attempts. |
172
+ ```ts
173
+ import { OpenRouterProvider } from "@falai/agent";
269
174
 
270
- ### Example
271
-
272
- ```typescript
273
175
  const openrouter = new OpenRouterProvider({
274
- apiKey: process.env.OPENROUTER_API_KEY!,
176
+ apiKey: process.env.OPENROUTER_API_KEY ?? "",
275
177
  model: "anthropic/claude-sonnet-5",
276
- backupModels: ["openai/gpt-5.6", "google/gemini-3.1-pro-preview"],
277
- siteName: "My App",
178
+ providerOrder: ["anthropic"],
278
179
  });
279
180
  ```
280
181
 
281
- ## DeepSeekProvider
182
+ Base URL `https://openrouter.ai/api`, chat completions with `json_schema`.
183
+
184
+ **The upstream host is pinned for you.** OpenRouter's prompt cache lives on the upstream host's account, and default routing hops between hosts, so every hop is a cold cache. By default the model's own vendor is preferred — `z-ai/glm-5.3-flash` goes to `z-ai`, `anthropic/claude-sonnet-5` to `anthropic` — with fallbacks on, so it is a preference and never a failed call. Measured 2026-09-21: unpinned, four calls with the same 2.9k-token prefix all landed on a host that reported `cached: 0`; pinned, the second call read 2,880 of 2,904 tokens from cache.
282
185
 
283
- DeepSeek is OpenAI-compatible and offers powerful reasoning models. The `deepseek-reasoner` model streams thinking/reasoning content via `reasoning_content` on the delta, which is logged at debug level.
186
+ Pass `providerOrder` to choose the hosts yourself. There is no way to say it inside `model`: OpenRouter answers `400 "z-ai/glm-5.3-flash@novita is not a valid model ID"`.
284
187
 
285
- ### Signature
188
+ **The route changes the answers, so measure your own model here.** Through this gateway, `z-ai/glm-5.3-flash` put "somos umas 30 pessoas" in the wrong band of a four-value enum on most attempts, in every JSON mode and routing tried, while the same model on [ZaiProvider](#zaiprovider) and `deepseek-chat` got it right every time. Over the 40-case understand eval on 2026-09-21 the same split holds: routing agreement 93% either way, but field agreement 86% (12/14) through OpenRouter against 100% (14/14) on `ZaiProvider`, and a median call three to five times slower. Prefer a model's own endpoint where you have one; run `bun run eval:understand` and `bun run eval:live --only openrouter` against the model you ship.
286
189
 
287
- ```typescript
288
- new DeepSeekProvider(options: DeepSeekProviderOptions)
190
+ ## DeepSeekProvider
289
191
 
192
+ ```ts fragment
290
193
  interface DeepSeekProviderOptions {
291
194
  apiKey: string;
292
195
  model: string;
293
196
  backupModels?: string[];
197
+ fallbacks?: Array<AiProvider | Provider>;
198
+ /** Default "https://api.deepseek.com". Note the spelling: baseURL. */
294
199
  baseURL?: string;
295
200
  jsonWithTools?: "response_format" | "prompt";
296
- config?: Partial<Omit<ChatCompletionCreateParamsNonStreaming, "model" | "messages">>;
201
+ config?: RequestConfig;
297
202
  retryConfig?: { timeout?: number; retries?: number };
203
+ fetchImpl?: typeof fetch;
298
204
  }
299
205
  ```
300
206
 
301
- ### Fields
302
-
303
- | Field | Type | Required | Default | Notes |
304
- |-------|------|----------|---------|-------|
305
- | `apiKey` | `string` | yes | — | Throws if empty. |
306
- | `model` | `string` | yes | — | e.g. `"deepseek-chat"`, `"deepseek-reasoner"`. |
307
- | `backupModels` | `string[]` | no | `[]` | Tried in order on overload/rate-limit errors. |
308
- | `jsonWithTools` | `"response_format" \| "prompt"` | no | `"response_format"` | Reach for it here first: the measured DeepSeek flash models called a tool 0/5 under a response format — [see above](#when-the-agent-narrates-a-tool-instead-of-calling-it). |
309
- | `baseURL` | `string` | no | `"https://api.deepseek.com"` | Custom endpoint for self-hosted or proxy deployments. |
310
- | `config` | OpenAI params | no | — | OpenAI-shaped defaults (forwarded to DeepSeek). |
311
- | `retryConfig.timeout` | `number` | no | `60000` | Per-attempt timeout in ms. |
312
- | `retryConfig.retries` | `number` | no | `3` | Total attempts. |
313
-
314
- ### Example
315
-
316
- ```typescript
317
- const deepseek = new DeepSeekProvider({
318
- apiKey: process.env.DEEPSEEK_API_KEY!,
319
- model: "deepseek-chat",
320
- backupModels: ["deepseek-reasoner"],
321
- config: { temperature: 0.3 },
322
- });
207
+ ```ts
208
+ import { DeepSeekProvider } from "@falai/agent";
209
+
210
+ const deepseek = new DeepSeekProvider({ apiKey: process.env.DEEPSEEK_API_KEY ?? "", model: "deepseek-chat" });
323
211
  ```
324
212
 
325
- ## Cross-provider fallbacks
213
+ Chat completions with `json_object`: DeepSeek answers a `json_schema` response format with `400 "This response_format type is unavailable now"`, so the endpoint guarantees JSON and the schema travels in the prompt. Reasoning arrives on `reasoning_content` and cache hits under `prompt_cache_hit_tokens`; both are read one layer down.
214
+
215
+ ## ZaiProvider
326
216
 
327
- In addition to `backupModels` (which fail over to another model on the *same* provider), providers accept a `fallbacks` list of `FallbackSpec` objects. When the primary provider encounters a transient failure (rate limits, outages, 5xx), the engine automatically falls over to the backup providers with cooldown management:
217
+ ```ts fragment
218
+ interface ZaiProviderOptions {
219
+ apiKey: string;
220
+ /** Default "glm-5.3-flash". Bare ids: "glm-5.3-flash", not "z-ai/glm-5.3-flash". */
221
+ model?: string;
222
+ backupModels?: string[];
223
+ fallbacks?: Array<AiProvider | Provider>;
224
+ fallbackOptions?: FallbackOptions<Provider>;
225
+ /** Any endpoint speaking the Anthropic Messages dialect with the plan's auth. Default: the coding endpoint. */
226
+ baseUrl?: string;
227
+ config?: RequestConfig;
228
+ retryConfig?: { timeout?: number; retries?: number };
229
+ fetchImpl?: typeof fetch;
230
+ }
231
+ ```
328
232
 
329
- ```typescript
233
+ ```ts
330
234
  import { ZaiProvider } from "@falai/agent";
331
235
 
332
- const provider = new ZaiProvider({
333
- apiKey: process.env.ZAI_API_KEY!,
334
- model: "glm-5.3-flash",
335
- fallbacks: [
336
- {
337
- preset: "openrouter",
338
- apiKey: process.env.OPENROUTER_API_KEY!,
339
- model: "z-ai/glm-5.3-flash",
340
- },
341
- {
342
- preset: "deepseek",
343
- apiKey: process.env.DEEPSEEK_API_KEY!,
344
- model: "deepseek-flash",
345
- },
236
+ const zai = new ZaiProvider({ apiKey: process.env.ZAI_API_KEY ?? "" }); // model defaults to glm-5.3-flash
237
+ ```
238
+
239
+ The flat-rate Z.ai Coding Plan hosts GLM on an Anthropic-compatible endpoint. Model ids are bare, and thinking is off unless you ask for it: the endpoint reads an absent `thinking` field as thinking on, so `@providerkit/core` says "no" out loud for you. Measured 2026-09-21: a call with no `config.effort` sends `thinking: { type: "disabled" }`, the same body `effort: "none"` produces. Ask for thinking with `config: { effort: "high" }`.
240
+
241
+ ## FallbackAiProvider
242
+
243
+ Runs an ordered list of providers. Each call goes to the first provider not on cooldown; a failure puts that provider on cooldown for a time chosen by the error's `kind` and moves on to the next. Cooldowns are remembered across calls, so a key that hit a weekly quota is not tried again a second later.
244
+
245
+ ```ts fragment
246
+ interface FallbackAiProviderOptions {
247
+ /** The ordered list of providers to try. The first is primary. */
248
+ providers: AiProvider[];
249
+ /** Cooldown per error kind in ms; null stops fallback for that kind. */
250
+ cooldownMs?: Partial<Record<ErrorKind, number | null>>;
251
+ /** Called when a provider enters cooldown. */
252
+ onCooldown?: (info: { candidate: AiProvider; error: unknown; kind: ErrorKind; retryAtMs: number }) => void;
253
+ }
254
+
255
+ class FallbackAiProvider implements AiProvider {
256
+ readonly name: string; // "fallback(zai->gemini)"
257
+ readonly capabilities: ProviderCapabilities;
258
+ readonly pool: FallbackPool<AiProvider>; // from @providerkit/core
259
+ constructor(options: FallbackAiProviderOptions);
260
+ }
261
+ ```
262
+
263
+ ```ts
264
+ import { FallbackAiProvider, GeminiProvider, ZaiProvider } from "@falai/agent";
265
+
266
+ const provider = new FallbackAiProvider({
267
+ providers: [
268
+ new ZaiProvider({ apiKey: process.env.ZAI_API_KEY ?? "" }),
269
+ new GeminiProvider({ apiKey: process.env.GEMINI_API_KEY ?? "", model: "gemini-2.5-flash" }),
346
270
  ],
271
+ onCooldown: ({ candidate, kind, retryAtMs }) => console.warn(candidate.name, kind, new Date(retryAtMs)),
272
+ });
273
+ console.log(provider.name); // "fallback(zai->gemini)"
274
+ ```
275
+
276
+ An empty `providers` list throws at construction. The difference from a provider's own `fallbacks` option: `FallbackAiProvider` works on whole `AiProvider` objects and keeps its pool on `.pool`; `fallbacks` folds the chain into one `@providerkit/core` provider inside the adapter.
277
+
278
+ ## createOpenAICompatibleProvider
279
+
280
+ Most endpoints that call themselves OpenAI-compatible (Azure OpenAI, Groq, Together, Fireworks, vLLM, LM Studio, Ollama, a gateway of your own) differ from OpenAI only in base URL, headers, and how they want structured output requested. This builds a provider from those settings alone.
281
+
282
+ ```ts fragment
283
+ interface OpenAICompatibleOptions {
284
+ /** Names the provider in errors and logs: "azure", "ollama", "groq". */
285
+ name: string;
286
+ baseURL: string;
287
+ /** Local servers often ignore it; pass any non-empty string. */
288
+ apiKey: string;
289
+ model: string;
290
+ backupModels?: string[];
291
+ fallbacks?: Array<AiProvider | Provider>;
292
+ /** Merged over the defaults (all true except supportsPromptCaching). */
293
+ capabilities?: Partial<ProviderCapabilities>;
294
+ /** Extra request headers, e.g. Azure's `api-key`. */
295
+ defaultHeaders?: Record<string, string>;
296
+ /** Default "json_schema". */
297
+ structuredOutput?: "responses_parse" | "json_schema" | "json_object";
298
+ jsonWithTools?: "response_format" | "prompt";
299
+ config?: RequestConfig;
300
+ retryConfig?: { timeout?: number; retries?: number };
301
+ fetchImpl?: typeof fetch;
302
+ }
303
+
304
+ function createOpenAICompatibleProvider(options: OpenAICompatibleOptions): OpenAICompatibleProvider;
305
+ ```
306
+
307
+ ```ts
308
+ import { createOpenAICompatibleProvider } from "@falai/agent";
309
+
310
+ const ollama = createOpenAICompatibleProvider({
311
+ name: "ollama",
312
+ baseURL: "http://localhost:11434/v1",
313
+ apiKey: "ollama",
314
+ model: "llama3.3",
315
+ });
316
+
317
+ const azure = createOpenAICompatibleProvider({
318
+ name: "azure",
319
+ baseURL: `https://${process.env.AZURE_RESOURCE}.openai.azure.com/openai/deployments/${process.env.AZURE_DEPLOYMENT}`,
320
+ apiKey: process.env.AZURE_OPENAI_KEY ?? "",
321
+ model: process.env.AZURE_DEPLOYMENT ?? "",
322
+ defaultHeaders: { "api-key": process.env.AZURE_OPENAI_KEY ?? "" },
347
323
  });
324
+ console.log(ollama.name, azure.name);
325
+ ```
326
+
327
+ `structuredOutput` decides how a structured request is sent:
328
+
329
+ | Mode | What goes out | Use when |
330
+ |------|---------------|----------|
331
+ | `responses_parse` | OpenAI's Responses API, schema enforced natively | The endpoint is OpenAI itself. Most compatible servers do not implement it. |
332
+ | `json_schema` | Chat completions with a `json_schema` response format | The broadest enforced mode: DeepSeek, Groq, Together, Fireworks, vLLM. The default here. |
333
+ | `json_object` | Chat completions with plain JSON mode | Servers with no schema enforcement at all. The framework reads what comes back leniently. |
334
+
335
+ Missing `name`, `baseURL`, `apiKey` or `model` throws at construction. For behaviour these settings do not cover, subclass `OpenAICompatibleProvider`.
336
+
337
+ ## OpenAICompatibleProvider
338
+
339
+ The abstract base every chat-completions provider extends: `OpenAIProvider`, `OpenRouterProvider`, `DeepSeekProvider` and the class behind `createOpenAICompatibleProvider`. A subclass names itself and its capabilities; the base picks the request shape from `structuredOutput` (default `responses_parse`) and hands everything else to `ProviderAdapter`.
340
+
341
+ ```ts fragment
342
+ interface OpenAICompatibleProviderInit extends Omit<ProviderAdapterInit, "provider"> {
343
+ apiKey: string;
344
+ baseUrl?: string;
345
+ /** Names the provider in errors, and picks core's effort dialect. */
346
+ id: string;
347
+ headers?: Record<string, string>;
348
+ config?: RequestConfig;
349
+ structuredOutput?: StructuredOutputMode;
350
+ jsonWithTools?: JsonWithTools;
351
+ /** OpenRouter upstream-host pin. */
352
+ providerOrder?: string[];
353
+ fetchImpl?: typeof fetch;
354
+ }
355
+
356
+ abstract class OpenAICompatibleProvider extends ProviderAdapter {
357
+ protected readonly config?: RequestConfig;
358
+ protected constructor(init: OpenAICompatibleProviderInit);
359
+ }
360
+ ```
361
+
362
+ ```ts
363
+ import { OpenAICompatibleProvider } from "@falai/agent";
364
+ import type { ProviderCapabilities } from "@falai/agent";
365
+
366
+ class GatewayProvider extends OpenAICompatibleProvider {
367
+ readonly name = "gateway";
368
+ readonly capabilities: ProviderCapabilities = {
369
+ supportsTools: true,
370
+ supportsNativeJsonSchema: true,
371
+ supportsStreaming: true,
372
+ supportsStreamingToolCalls: true,
373
+ supportsPromptCaching: false,
374
+ };
375
+
376
+ constructor(apiKey: string, model: string) {
377
+ super({ id: "gateway", apiKey, baseUrl: "https://llm.example.com/v1", model, structuredOutput: "json_schema" });
378
+ }
379
+ }
380
+
381
+ const gateway = new GatewayProvider(process.env.GATEWAY_KEY ?? "", "glm-5.3-flash");
382
+ console.log(gateway.name);
348
383
  ```
349
384
 
350
- The underlying `@providerkit/core` engine tracks cooldowns per provider, automatically bypassing throttled backends until their cooldown expires.
385
+ ## ProviderAdapter
386
+
387
+ The base class every built-in provider extends. `@providerkit/core` returns normalized stream chunks; this framework works in whole turns: a composed prompt plus history in, a parsed structured reply out. `ProviderAdapter` does that translation once, for every vendor, and adds retries, backup models and fallbacks around it. `generateMessage` is `generateMessageStream` drained, so both paths behave the same.
388
+
389
+ ```ts fragment
390
+ interface ProviderAdapterInit {
391
+ /** The @providerkit/core provider this adapter drives. */
392
+ provider: Provider;
393
+ model: string;
394
+ /** Sampling defaults for every call. */
395
+ defaults?: RequestConfig;
396
+ /** Tried in order after the primary. */
397
+ backupModels?: string[];
398
+ fallbacks?: Array<AiProvider | Provider>;
399
+ fallbackOptions?: FallbackOptions<Provider>;
400
+ retryConfig?: { timeout?: number; retries?: number };
401
+ }
402
+
403
+ interface RequestConfig {
404
+ temperature?: number;
405
+ topP?: number;
406
+ maxTokens?: number;
407
+ stopSequences?: string[];
408
+ /** "none" | "low" | "medium" | "high" | "max". Absent: the model's own default, never sent. */
409
+ effort?: Effort;
410
+ }
411
+
412
+ interface RetryConfig {
413
+ /** Milliseconds a stream may stay silent before it counts as wedged. */
414
+ timeout: number;
415
+ /** Retries after the first attempt; 0 still makes one call. */
416
+ retries: number;
417
+ }
351
418
 
352
- ## Building a custom OpenAI-compatible provider
419
+ function resolveRetryConfig(input?: { timeout?: number; retries?: number }): RetryConfig;
420
+
421
+ abstract class ProviderAdapter implements AiProvider {
422
+ abstract readonly name: string;
423
+ abstract readonly capabilities: ProviderCapabilities;
424
+ protected readonly provider: Provider;
425
+ protected readonly primaryModel: string;
426
+ protected readonly backupModels: string[];
427
+ protected readonly retryConfig: RetryConfig;
428
+ get coreProvider(): Provider;
429
+ protected constructor(init: ProviderAdapterInit);
430
+ probeJsonWithTools(opts?: ProbeOptions): Promise<JsonWithToolsProbe>;
431
+ generateMessage<C, S>(input: GenerateMessageInput<C>): Promise<GenerateMessageOutput<S>>;
432
+ generateMessageStream<C, S>(input: GenerateMessageInput<C>): AsyncGenerator<GenerateMessageStreamChunk<S>>;
433
+ }
434
+ ```
353
435
 
354
- Many vendors (Groq, Together, Fireworks, …) expose OpenAI-compatible chat-completions APIs. Instead of implementing `AiProvider` from scratch, subclass the exported `OpenAICompatibleProvider` base class — history and tool translation, streaming, tool-call assembly, backup-model fallback, retries and normalized `ProviderError`s all come with it. `OpenAIProvider`, `OpenRouterProvider`, and `DeepSeekProvider` are themselves thin subclasses.
436
+ A subclass supplies a `@providerkit/core` provider and a name. Only `@falai/agent` symbols appear below, so the core provider arrives already built:
355
437
 
356
- A minimal subclass supplies the endpoint, naming, and capabilities:
438
+ ```ts
439
+ import { ProviderAdapter, resolveRetryConfig } from "@falai/agent";
440
+ import type { ProviderAdapterInit, ProviderCapabilities } from "@falai/agent";
357
441
 
358
- ```typescript
359
- import {
360
- OpenAICompatibleProvider,
361
- type ProviderCapabilities,
362
- } from "@falai/agent";
442
+ declare const core: ProviderAdapterInit["provider"]; // e.g. createOpenAIProvider(...) from @providerkit/core
363
443
 
364
- export class GroqProvider extends OpenAICompatibleProvider {
365
- public readonly name = "groq";
366
- public readonly capabilities: ProviderCapabilities = {
444
+ class MyProvider extends ProviderAdapter {
445
+ readonly name = "mine";
446
+ readonly capabilities: ProviderCapabilities = {
367
447
  supportsTools: true,
368
448
  supportsNativeJsonSchema: true,
369
449
  supportsStreaming: true,
@@ -371,69 +451,212 @@ export class GroqProvider extends OpenAICompatibleProvider {
371
451
  supportsPromptCaching: false,
372
452
  };
373
453
 
374
- constructor(options: { apiKey: string; model: string; backupModels?: string[] }) {
375
- super({
376
- id: "groq",
377
- apiKey: options.apiKey,
378
- baseUrl: "https://api.groq.com/openai",
379
- model: options.model,
380
- structuredOutput: "json_schema",
381
- backupModels: options.backupModels,
382
- });
454
+ constructor() {
455
+ super({ provider: core, model: "my-model", backupModels: ["my-smaller-model"], retryConfig: { retries: 1 } });
383
456
  }
384
457
  }
458
+
459
+ console.log(resolveRetryConfig({ retries: 1 })); // { timeout: 60000, retries: 1 }
460
+ console.log(resolveRetryConfig({ timeout: 0 })); // { timeout: 60000, retries: 3 }: a 0 ms timeout would abort every call, so it is treated as unset
461
+ console.log(new MyProvider().name);
462
+ ```
463
+
464
+ What the adapter does on every call, from `src/providers/ProviderAdapter.ts`:
465
+
466
+ 1. Turns `history` plus the prompt into the provider's messages. The prompt is always the final user message.
467
+ 2. Turns `tools` into tool definitions and `parameters.jsonSchema` into a JSON output request named `parameters.schemaName` (or `structured_output`). An empty schema means no JSON mode.
468
+ 3. Merges `defaults`, then `parameters.maxOutputTokens` as `maxTokens` and `parameters.reasoning.effort` as `effort`.
469
+ 4. Streams with a silence watchdog of `retryConfig.timeout` ms and `retryConfig.retries + 1` attempts, then moves to the next backup model when the error kind allows.
470
+ 5. Folds the chunks: text becomes `delta` chunks, tool call fragments are assembled and their arguments parsed, usage lands on `metadata` (`tokensUsed`, `promptTokens`, `completionTokens`, `cachedInputTokens`).
471
+ 6. Parses the accumulated text leniently into `structured`. Text that looks like an envelope but did not parse is dropped rather than handed to the customer. A message that is blank after parsing, with no tool calls, throws `Error: No response from <provider>` — after the retries and backup models, so the caller's path (a deferred speak step, or the host replaying the turn) is what picks it up. A stream that never produced any content is caught earlier, inside the retry, as a `ProviderError` of kind `overload`.
472
+
473
+ ## Retries, backup models and fallbacks
474
+
475
+ Three layers, innermost first. All from `src/providers/ProviderAdapter.ts` and `@providerkit/core`.
476
+
477
+ | Layer | Option | What triggers it | What it does |
478
+ |-------|--------|------------------|--------------|
479
+ | Retry | `retryConfig` | A transient error (`timeout`, `network`, `overload`, `rate`), or silence for `timeout` ms. Default `timeout: 60000`, `retries: 3`, so up to 4 attempts. | Same model, same provider. `timeout: 0` is treated as unset; `retries: 0` is honoured. |
480
+ | Backup model | `backupModels` | Retries exhausted with a backup-eligible kind, or `kind === "model"` (the endpoint does not serve that id). | Next model on the list, same provider. |
481
+ | Fallback | `fallbacks` (per provider) or `FallbackAiProvider` | The provider fails or is on cooldown. | Next provider. Cooldowns per `kind`; a server-supplied `Retry-After` always wins over the default interval. |
482
+
483
+ The `timeout` bounds silence, not the whole call: a stream that keeps producing tokens is left alone, one that goes quiet for 60 s is cut and retried.
484
+
485
+ ## Reasoning
486
+
487
+ ```ts fragment
488
+ interface ReasoningConfig {
489
+ effort?: "none" | "low" | "medium" | "high" | "max";
490
+ }
491
+ ```
492
+
493
+ `GenerateMessageInput.parameters.reasoning` is on the interface for a custom caller, but the framework never sets it. The one way to reach the wire is `config.effort` on a provider, which the adapter sends with every call as the provider's default. Absent means the model's own dynamic thinking and is never sent; `"none"` is the only way to say do not think. It matters most under a small `maxTokens`, where thinking tokens and the answer share one budget. Support varies per model; an unsupported level comes back as a 400 (`kind: "invalid"`).
494
+
495
+ ## The AiProvider interface
496
+
497
+ What a provider must implement, from `src/types/ai.ts`. The built-in providers, `FallbackAiProvider` and the test mock all satisfy it.
498
+
499
+ ```ts fragment
500
+ interface AiProvider {
501
+ readonly name: string;
502
+ capabilities: ProviderCapabilities;
503
+ generateMessage<TContext = unknown, TStructured = AgentStructuredResponse>(
504
+ input: GenerateMessageInput<TContext>,
505
+ ): Promise<GenerateMessageOutput<TStructured>>;
506
+ generateMessageStream<TContext = unknown, TStructured = AgentStructuredResponse>(
507
+ input: GenerateMessageInput<TContext>,
508
+ ): AsyncGenerator<GenerateMessageStreamChunk<TStructured>>;
509
+ }
510
+
511
+ interface GenerateMessageInput<TContext = unknown> {
512
+ prompt: string;
513
+ history: HistoryItem[];
514
+ context: TContext;
515
+ tools?: Array<{ id: string; name?: string; description?: string; parameters?: unknown }>;
516
+ parameters?: {
517
+ maxOutputTokens?: number;
518
+ reasoning?: ReasoningConfig;
519
+ jsonSchema: { [key: string]: unknown };
520
+ schemaName?: string;
521
+ };
522
+ signal?: AbortSignal;
523
+ }
524
+
525
+ interface GenerateMessageOutput<TStructured = AgentStructuredResponse> {
526
+ message: string;
527
+ metadata?: { model?: string; tokensUsed?: number; finishReason?: string; [key: string]: unknown };
528
+ structured?: TStructured;
529
+ }
530
+
531
+ interface GenerateMessageStreamChunk<TStructured = AgentStructuredResponse> {
532
+ delta: string;
533
+ accumulated: string;
534
+ done: boolean;
535
+ metadata?: { model?: string; tokensUsed?: number; finishReason?: string; [key: string]: unknown };
536
+ /** Only on the chunk with done: true. */
537
+ structured?: TStructured;
538
+ }
539
+
540
+ interface ProviderCapabilities {
541
+ supportsTools: boolean;
542
+ supportsNativeJsonSchema: boolean;
543
+ supportsStreaming: boolean;
544
+ supportsStreamingToolCalls: boolean;
545
+ supportsPromptCaching: boolean;
546
+ }
547
+ ```
548
+
549
+ ### What the framework sends
550
+
551
+ Every call carries `parameters.jsonSchema` and a `schemaName`, so a custom provider can tell the calls apart and log them. From `src/core/Understand.ts`, `src/core/Speak.ts` and `src/core/CompactionEngine.ts`:
552
+
553
+ | Call | Method | `schemaName` | `tools` | Once per |
554
+ |------|--------|--------------|---------|----------|
555
+ | Understand | `generateMessage` | `"understand"` | never | message turn with something to judge: two or more flows to route between (counting the one on the floor), a mention flow, a `when` branch on the asking step, or a pending `extract: 'anywhere'` field on the flow on the floor or on a flow with `message` hints. Skipped when none of those is live. |
556
+ | Speak | `generateMessage` on `turn()`, `generateMessageStream` on `turnStream()` | `"speak"` | on rounds where tools are offered (`maxToolLoops`, default 5) | talk step or idle answer, plus one call per tool round |
557
+ | Compaction summary | `generateMessage` | none, and `jsonSchema` is `{}` | never | turn whose history crossed the compaction threshold, before both calls above |
558
+
559
+ The framework reads `structured` first. When it is missing it looks for a JSON object inside `message`, so a provider that only returns text still works as long as the text is the envelope. A speak reply whose `message` is blank after the last tool round is treated like a failed call: the step is deferred (see [Errors](./errors.md#where-a-provider-failure-lands-in-a-turn)).
560
+
561
+ ### A custom provider
562
+
563
+ The shortest useful one wraps another provider and logs which call it is. The two methods are generic; declare the type parameters and pass them through.
564
+
565
+ ```ts
566
+ import { falai, GeminiProvider } from "@falai/agent";
567
+ import type { AiProvider, GenerateMessageInput } from "@falai/agent";
568
+
569
+ function logged(inner: AiProvider): AiProvider {
570
+ const tag = (input: GenerateMessageInput<unknown>): string => input.parameters?.schemaName ?? "unnamed";
571
+ return {
572
+ name: `logged(${inner.name})`,
573
+ capabilities: inner.capabilities,
574
+ generateMessage<C, S>(input: GenerateMessageInput<C>) {
575
+ console.log(`[${tag(input)}] ${input.prompt.length} chars, ${input.tools?.length ?? 0} tools`);
576
+ return inner.generateMessage<C, S>(input);
577
+ },
578
+ generateMessageStream<C, S>(input: GenerateMessageInput<C>) {
579
+ console.log(`[${tag(input)}] streaming`);
580
+ return inner.generateMessageStream<C, S>(input);
581
+ },
582
+ };
583
+ }
584
+
585
+ const f = falai().fields({ nome: { type: "string", ask: "Pergunte o nome." } });
586
+ const agent = f.agent({
587
+ name: "Ana",
588
+ provider: logged(new GeminiProvider({ apiKey: process.env.GEMINI_API_KEY ?? "", model: "gemini-2.5-flash" })),
589
+ flows: [f.flow({ id: "oi", name: "Oi", on: [{ message: [] }], steps: [{ id: "nome", collect: ["nome"] }] })],
590
+ });
591
+
592
+ const r = await agent.turn({ sessionId: "s1", message: "oi" });
593
+ console.log(r.llmCalls); // logs "[speak] …" once: one flow with no routing hints and nobody on the floor, so no understand call
385
594
  ```
386
595
 
387
- That is a complete, working provider. Vendor-specific wire behaviour is not this layer's job any more: it lives in `@providerkit/core`, which the provider classes are thin bindings over. `DeepSeekProvider` is the reference pattern for what is left here — an id, a base URL, the structured-output mode the endpoint actually supports, and its capabilities. To bind a core provider this package does not ship a class for, subclass `ProviderAdapter` directly.
596
+ ## When the model narrates a tool instead of calling it
597
+
598
+ Every turn the framework sends pins the model's output to a schema, because that is how `message` and the step's fields come back. Some models cannot emit a tool call while pinned that way. They do not report it: the model writes "deixa eu ver aqui" and stops. On the wire the call succeeded; in the product the agent never uses its tools, and no instruction fixes it.
599
+
600
+ `jsonWithTools` on `GeminiProvider`, `OpenRouterProvider`, `DeepSeekProvider`, `createOpenAICompatibleProvider` and `OpenAICompatibleProviderInit` decides how the schema is sent on calls that also carry tools:
388
601
 
389
- ## Errors
602
+ - `"response_format"` sends both, which every wire documents and most models honour.
603
+ - `"prompt"` leaves the response format off those calls and puts the schema in the prompt instead. Calls without tools are untouched.
390
604
 
391
- All five providers share the same construction-time guards and runtime failure modes.
605
+ The answer belongs to the model, not the endpoint, and it goes both ways. The code's own measurements, sampled on 2026-09-07. Each cell is the samples where the model called its tool:
392
606
 
393
- | When | Error | Why |
394
- |------|-------|-----|
395
- | `apiKey` is empty or missing | `Error("<vendor> API key is required")` | Thrown from the constructor. |
396
- | `model` is empty or missing | `Error("Model is required. ...")` | Thrown from the constructor. |
397
- | Vendor returns no text and no tool calls | `Error("No response from <vendor>")` | Surfaces as a `ResponseGenerationError` once it bubbles through the agent. |
398
- | Primary and every backup model fail | `ProviderError` with a normalized `code` | After exhausting retries and `backupModels`. Propagates bare out of `respond()`. |
399
- | Anthropic streaming with `system: undefined` | Vendor 400 | Set `config.system` or rely on history-derived system messages. |
607
+ | Model | Response format | Prompt |
608
+ |-------|-----------------|--------|
609
+ | `z-ai/glm-5.3-flash` (OpenRouter) | 0/10 | 8/8 |
610
+ | `qwen3.8-flash` (OpenRouter) | 10/10 | 1/6 |
611
+ | DeepSeek's flash models | 0/5 | not sampled |
612
+ | `gemini-3.8-flash` | 3/10 | not sampled |
613
+ | `gemini-3.5-flash`, `gemini-3.5-flash-lite` | every call | not sampled |
400
614
 
401
- The retry/backup logic only kicks in for **transient** errors: rate limits, overload and availability, timeouts, and network faults. Deterministic failures — a wrong key, an exhausted balance, an invalid request, a caller's abort — fail fast without burning the retry budget. Classification reads the response BODY before its status, because vendors file the same cause under whatever status they like.
615
+ Do not pick from that list. Ask the model you ship.
402
616
 
403
- Only failures *before the first chunk* are retried: past that the stream is committed, and a retry would replay text the reader has already seen. The same rule governs the walk to a backup model. `retryConfig.timeout` is the silence deadline — the wait allowed before the first byte, and between any two after it — so a stream that opens and stalls is treated as failed while a long, healthy one is left alone.
617
+ ### The probe
404
618
 
405
- A model the endpoint will not serve also walks to the next model on the list, which is what the list is for.
619
+ Every `ProviderAdapter` subclass has `probeJsonWithTools(opts?)`. It asks the bound model, on the wire, both ways, and reports which shape called the tool on every sample.
620
+
621
+ ```ts fragment
622
+ interface JsonWithToolsProbe {
623
+ /** The shape to configure, or null when neither called the tool on every sample. */
624
+ use: "response_format" | "prompt" | null;
625
+ /** Samples that produced a tool call, per shape. */
626
+ calls: Record<"response_format" | "prompt", number>;
627
+ samples: number;
628
+ }
629
+
630
+ interface ProbeOptions {
631
+ /** Samples per shape. Default 3. */
632
+ samples?: number;
633
+ /** Probe a model other than the bound one. */
634
+ model?: string;
635
+ signal?: AbortSignal;
636
+ }
637
+ ```
406
638
 
407
- ### `ProviderError`
639
+ ```ts
640
+ import { OpenRouterProvider } from "@falai/agent";
408
641
 
409
- Terminal failures — after retries and backup models are exhausted — throw the exported `ProviderError` with a normalized `code`, so callers handle failures uniformly regardless of which vendor is configured. The original SDK/HTTP error is preserved as `cause`.
642
+ const apiKey = process.env.OPENROUTER_API_KEY ?? "";
643
+ const model = "z-ai/glm-5.3-flash";
410
644
 
411
- ```typescript
412
- import { ProviderError } from "@falai/agent";
645
+ const probe = await new OpenRouterProvider({ apiKey, model }).probeJsonWithTools();
646
+ console.log(probe.calls); // e.g. { response_format: 0, prompt: 3 }
647
+ if (!probe.use) throw new Error(`${model} cannot call a tool while pinned to a schema; pick another model`);
413
648
 
414
- type ErrorKind =
415
- | 'aborted' // the caller pressed Stop — never retried
416
- | 'timeout' // our deadline, or a 408
417
- | 'network' // never reached the provider
418
- | 'overload' // theirs and temporary — retry, and try another model
419
- | 'rate' // per-minute throttle — wait, or rotate key or model
420
- | 'quota' // balance or usage window exhausted — waiting will not fix it
421
- | 'entitlement' // the plan never included this API
422
- | 'auth' // the key is wrong, not the request
423
- | 'model' // the model id is not served here
424
- | 'context' // the prompt outgrew the window — send less
425
- | 'content' // safety filter or refusal
426
- | 'invalid' // any other 4xx — a bug in what we sent
427
- | 'unknown'
649
+ const provider = new OpenRouterProvider({ apiKey, model, jsonWithTools: probe.use });
650
+ console.log(provider.name);
428
651
  ```
429
652
 
430
- When the failure surfaces through `agent.respond(...)`, the `ProviderError` propagates **bare** — catch it with `instanceof`, no unwrapping. (On streaming turns, errors arrive wrapped as `ResponseGenerationError` on the final chunk's `error` field, with the original on `.cause`.) See [Errors](./errors.md).
653
+ Run it once, at boot. It costs `samples × 2` short calls (6 by default), and errors propagate: a probe that swallowed a bad key would report "this model cannot call tools", which is worse to believe than "the call failed". Log `calls`, not just `use`; `0/3 and 3/3` is what makes the next model swap's regression obvious. The probe catches the structural failure, a model that cannot emit the call on the easiest question there is; a model that is merely unreliable passes it.
431
654
 
432
- ## Related
655
+ ## See also
433
656
 
434
- - [Install](../start/01-install.md) — provider signup and env keys
435
- - [Architecture](../concepts/architecture.md) — where the provider sits in the engine
436
- - [createAgent](./create-agent.md) — the `provider` field
437
- - [Persistence adapters](./adapters.md) — the other strategy plug
438
- - [Errors](./errors.md) — `ProviderError`, `ResponseGenerationError`, and friends
439
- - [v2.3 → v2.4 migration](../migration/v2-3-to-v2-4.md) — required `capabilities` and the `ProviderError` change
657
+ - [Install](../start/01-install.md): getting a key and running an example.
658
+ - [Agent](./agent.md): the `provider` option and the rest of `AgentOptions`.
659
+ - [Pipeline](../concepts/pipeline.md): where the understand and speak calls sit in a turn and what each costs.
660
+ - [Errors](./errors.md): `ProviderError`, its kinds, and where a failure lands in a turn.
661
+ - [Streaming](../guides/streaming.md): `turnStream` and what `generateMessageStream` must yield.
662
+ - [Testing](../guides/testing.md): a scripted `AiProvider` that answers by `schemaName`.