@mastra/core 1.3.0 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (274) hide show
  1. package/CHANGELOG.md +462 -0
  2. package/datasets.d.ts +1 -0
  3. package/dist/agent/agent.d.ts +1 -1
  4. package/dist/agent/index.cjs +13 -13
  5. package/dist/agent/index.js +2 -2
  6. package/dist/agent/message-list/adapters/AIV4Adapter.d.ts.map +1 -1
  7. package/dist/agent/message-list/adapters/AIV5Adapter.d.ts.map +1 -1
  8. package/dist/agent/message-list/conversion/output-converter.d.ts +2 -1
  9. package/dist/agent/message-list/conversion/output-converter.d.ts.map +1 -1
  10. package/dist/agent/message-list/index.cjs +18 -18
  11. package/dist/agent/message-list/index.js +1 -1
  12. package/dist/agent/workflows/prepare-stream/index.d.ts +1 -1
  13. package/dist/chunk-3JVFFAJX.cjs +1207 -0
  14. package/dist/chunk-3JVFFAJX.cjs.map +1 -0
  15. package/dist/{chunk-WL3AW3YA.js → chunk-3X3CZUXI.js} +4070 -3983
  16. package/dist/chunk-3X3CZUXI.js.map +1 -0
  17. package/dist/{chunk-2GWTJFVM.js → chunk-4EHGOATH.js} +46 -14
  18. package/dist/chunk-4EHGOATH.js.map +1 -0
  19. package/dist/{chunk-YNXIGRQE.cjs → chunk-4IJ4UDZX.cjs} +319 -83
  20. package/dist/chunk-4IJ4UDZX.cjs.map +1 -0
  21. package/dist/{chunk-CGPH7CMG.cjs → chunk-4KFEMXTV.cjs} +46 -14
  22. package/dist/chunk-4KFEMXTV.cjs.map +1 -0
  23. package/dist/{chunk-PHYJYZ32.js → chunk-4TQ4EBYX.js} +16 -8
  24. package/dist/chunk-4TQ4EBYX.js.map +1 -0
  25. package/dist/{chunk-SIZEIYNH.js → chunk-4XSAZPPS.js} +254 -18
  26. package/dist/chunk-4XSAZPPS.js.map +1 -0
  27. package/dist/{chunk-KUTU2YZF.js → chunk-5Q5Y34SS.js} +5 -5
  28. package/dist/{chunk-KUTU2YZF.js.map → chunk-5Q5Y34SS.js.map} +1 -1
  29. package/dist/{chunk-EH6SAGEO.cjs → chunk-64WGYTQK.cjs} +72 -53
  30. package/dist/{chunk-EH6SAGEO.cjs.map → chunk-64WGYTQK.cjs.map} +1 -1
  31. package/dist/{chunk-OOCEAC6U.cjs → chunk-65PHUUMF.cjs} +3 -3
  32. package/dist/{chunk-OOCEAC6U.cjs.map → chunk-65PHUUMF.cjs.map} +1 -1
  33. package/dist/{chunk-JNE2ABVB.js → chunk-7NKUSQEV.js} +1094 -10
  34. package/dist/chunk-7NKUSQEV.js.map +1 -0
  35. package/dist/{chunk-ZHFM7HCQ.js → chunk-AXHBJ4GX.js} +3 -3
  36. package/dist/{chunk-ZHFM7HCQ.js.map → chunk-AXHBJ4GX.js.map} +1 -1
  37. package/dist/{chunk-ILQXPZCD.js → chunk-AY6DBRS3.js} +37 -21
  38. package/dist/chunk-AY6DBRS3.js.map +1 -0
  39. package/dist/{chunk-TERSHTY5.cjs → chunk-BP7VYTOP.cjs} +1116 -21
  40. package/dist/chunk-BP7VYTOP.cjs.map +1 -0
  41. package/dist/{chunk-UE2G2LRP.cjs → chunk-CZ4NQANZ.cjs} +37 -21
  42. package/dist/chunk-CZ4NQANZ.cjs.map +1 -0
  43. package/dist/{chunk-NCC45KOB.cjs → chunk-DBSVT6AR.cjs} +7 -7
  44. package/dist/{chunk-NCC45KOB.cjs.map → chunk-DBSVT6AR.cjs.map} +1 -1
  45. package/dist/{chunk-BXLLXTT4.js → chunk-FLPEGTEK.js} +4 -4
  46. package/dist/{chunk-BXLLXTT4.js.map → chunk-FLPEGTEK.js.map} +1 -1
  47. package/dist/{chunk-ON2KVIUJ.cjs → chunk-HYRYTTMT.cjs} +7 -7
  48. package/dist/{chunk-ON2KVIUJ.cjs.map → chunk-HYRYTTMT.cjs.map} +1 -1
  49. package/dist/chunk-NJ7TL3LQ.js +1196 -0
  50. package/dist/chunk-NJ7TL3LQ.js.map +1 -0
  51. package/dist/{chunk-EUG4AON3.cjs → chunk-NKYWDNCI.cjs} +8 -7
  52. package/dist/{chunk-EUG4AON3.cjs.map → chunk-NKYWDNCI.cjs.map} +1 -1
  53. package/dist/{chunk-UHVG25VW.cjs → chunk-NZG2JAKS.cjs} +23 -15
  54. package/dist/chunk-NZG2JAKS.cjs.map +1 -0
  55. package/dist/{chunk-44SUGDBR.js → chunk-PS5ONCXY.js} +109 -5
  56. package/dist/chunk-PS5ONCXY.js.map +1 -0
  57. package/dist/{chunk-57QAF2ZQ.js → chunk-QTTWRCB5.js} +4 -4
  58. package/dist/{chunk-57QAF2ZQ.js.map → chunk-QTTWRCB5.js.map} +1 -1
  59. package/dist/{chunk-VM25PDSW.js → chunk-RZ4CIIZR.js} +4 -4
  60. package/dist/{chunk-VM25PDSW.js.map → chunk-RZ4CIIZR.js.map} +1 -1
  61. package/dist/{chunk-C3XU7ZDC.cjs → chunk-SU5APAM6.cjs} +123 -4
  62. package/dist/chunk-SU5APAM6.cjs.map +1 -0
  63. package/dist/{chunk-3MJCJLZS.js → chunk-U2HKJZCI.js} +24 -5
  64. package/dist/{chunk-3MJCJLZS.js.map → chunk-U2HKJZCI.js.map} +1 -1
  65. package/dist/{chunk-GCTAD6B7.cjs → chunk-VD5YA6RH.cjs} +12 -12
  66. package/dist/{chunk-GCTAD6B7.cjs.map → chunk-VD5YA6RH.cjs.map} +1 -1
  67. package/dist/{chunk-KAJNBNWP.cjs → chunk-YNNJLLFN.cjs} +4071 -3984
  68. package/dist/chunk-YNNJLLFN.cjs.map +1 -0
  69. package/dist/datasets/dataset.d.ts +153 -0
  70. package/dist/datasets/dataset.d.ts.map +1 -0
  71. package/dist/datasets/experiment/analytics/aggregate.d.ts +46 -0
  72. package/dist/datasets/experiment/analytics/aggregate.d.ts.map +1 -0
  73. package/dist/datasets/experiment/analytics/compare.d.ts +33 -0
  74. package/dist/datasets/experiment/analytics/compare.d.ts.map +1 -0
  75. package/dist/datasets/experiment/analytics/index.d.ts +9 -0
  76. package/dist/datasets/experiment/analytics/index.d.ts.map +1 -0
  77. package/dist/datasets/experiment/analytics/types.d.ts +103 -0
  78. package/dist/datasets/experiment/analytics/types.d.ts.map +1 -0
  79. package/dist/datasets/experiment/executor.d.ts +40 -0
  80. package/dist/datasets/experiment/executor.d.ts.map +1 -0
  81. package/dist/datasets/experiment/index.d.ts +31 -0
  82. package/dist/datasets/experiment/index.d.ts.map +1 -0
  83. package/dist/datasets/experiment/scorer.d.ts +21 -0
  84. package/dist/datasets/experiment/scorer.d.ts.map +1 -0
  85. package/dist/datasets/experiment/types.d.ts +140 -0
  86. package/dist/datasets/experiment/types.d.ts.map +1 -0
  87. package/dist/datasets/index.cjs +69 -0
  88. package/dist/datasets/index.cjs.map +1 -0
  89. package/dist/datasets/index.d.ts +6 -0
  90. package/dist/datasets/index.d.ts.map +1 -0
  91. package/dist/datasets/index.js +4 -0
  92. package/dist/datasets/index.js.map +1 -0
  93. package/dist/datasets/manager.d.ts +73 -0
  94. package/dist/datasets/manager.d.ts.map +1 -0
  95. package/dist/datasets/validation/errors.d.ts +44 -0
  96. package/dist/datasets/validation/errors.d.ts.map +1 -0
  97. package/dist/datasets/validation/index.d.ts +3 -0
  98. package/dist/datasets/validation/index.d.ts.map +1 -0
  99. package/dist/datasets/validation/validator.d.ts +24 -0
  100. package/dist/datasets/validation/validator.d.ts.map +1 -0
  101. package/dist/docs/SKILL.md +1 -3
  102. package/dist/docs/assets/SOURCE_MAP.json +436 -346
  103. package/dist/docs/references/docs-memory-observational-memory.md +86 -11
  104. package/dist/docs/references/docs-streaming-events.md +23 -0
  105. package/dist/docs/references/docs-workspace-filesystem.md +72 -1
  106. package/dist/docs/references/docs-workspace-overview.md +95 -12
  107. package/dist/docs/references/docs-workspace-sandbox.md +2 -0
  108. package/dist/docs/references/guides-agent-frameworks-ai-sdk.md +6 -2
  109. package/dist/docs/references/reference-ai-sdk-with-mastra.md +1 -1
  110. package/dist/docs/references/reference-memory-observational-memory.md +318 -9
  111. package/dist/docs/references/reference-streaming-workflows-stream.md +1 -0
  112. package/dist/docs/references/reference-workflows-workflow-methods-foreach.md +30 -0
  113. package/dist/docs/references/reference.md +3 -0
  114. package/dist/editor/index.d.ts +1 -1
  115. package/dist/editor/index.d.ts.map +1 -1
  116. package/dist/editor/types.d.ts +21 -3
  117. package/dist/editor/types.d.ts.map +1 -1
  118. package/dist/evals/index.cjs +20 -20
  119. package/dist/evals/index.js +3 -3
  120. package/dist/evals/scoreTraces/index.cjs +5 -5
  121. package/dist/evals/scoreTraces/index.js +2 -2
  122. package/dist/features/index.cjs +1 -1
  123. package/dist/features/index.cjs.map +1 -1
  124. package/dist/features/index.d.ts.map +1 -1
  125. package/dist/features/index.js +1 -1
  126. package/dist/features/index.js.map +1 -1
  127. package/dist/index.cjs +2 -7
  128. package/dist/index.d.ts +0 -9
  129. package/dist/index.d.ts.map +1 -1
  130. package/dist/index.js +1 -2
  131. package/dist/llm/index.cjs +10 -10
  132. package/dist/llm/index.js +2 -2
  133. package/dist/llm/model/provider-types.generated.d.ts +1694 -1659
  134. package/dist/loop/index.cjs +12 -12
  135. package/dist/loop/index.js +1 -1
  136. package/dist/loop/network/index.d.ts +1 -1
  137. package/dist/loop/workflows/agentic-execution/index.d.ts +1 -1
  138. package/dist/loop/workflows/agentic-execution/llm-execution-step.d.ts.map +1 -1
  139. package/dist/loop/workflows/agentic-execution/llm-mapping-step.d.ts.map +1 -1
  140. package/dist/loop/workflows/agentic-execution/tool-call-step.d.ts.map +1 -1
  141. package/dist/loop/workflows/agentic-loop/index.d.ts +1 -1
  142. package/dist/loop/workflows/errors.d.ts +4 -0
  143. package/dist/loop/workflows/errors.d.ts.map +1 -0
  144. package/dist/mastra/index.cjs +2 -2
  145. package/dist/mastra/index.d.ts +2 -0
  146. package/dist/mastra/index.d.ts.map +1 -1
  147. package/dist/mastra/index.js +1 -1
  148. package/dist/memory/index.cjs +14 -14
  149. package/dist/memory/index.js +1 -1
  150. package/dist/memory/memory.d.ts +5 -0
  151. package/dist/memory/memory.d.ts.map +1 -1
  152. package/dist/memory/types.d.ts +56 -0
  153. package/dist/memory/types.d.ts.map +1 -1
  154. package/dist/processors/index.cjs +41 -41
  155. package/dist/processors/index.js +1 -1
  156. package/dist/processors/processors/skills.d.ts +1 -1
  157. package/dist/processors/processors/skills.d.ts.map +1 -1
  158. package/dist/processors/runner.d.ts.map +1 -1
  159. package/dist/processors/trailing-assistant-guard.d.ts +34 -0
  160. package/dist/processors/trailing-assistant-guard.d.ts.map +1 -0
  161. package/dist/provider-registry-6LZAGQET.cjs +40 -0
  162. package/dist/{provider-registry-C6XCYX44.cjs.map → provider-registry-6LZAGQET.cjs.map} +1 -1
  163. package/dist/provider-registry-QUNT7S55.js +3 -0
  164. package/dist/{provider-registry-NWU4YFQW.js.map → provider-registry-QUNT7S55.js.map} +1 -1
  165. package/dist/provider-registry.json +4068 -3981
  166. package/dist/relevance/index.cjs +3 -3
  167. package/dist/relevance/index.js +1 -1
  168. package/dist/storage/base.d.ts +4 -1
  169. package/dist/storage/base.d.ts.map +1 -1
  170. package/dist/storage/constants.cjs +87 -27
  171. package/dist/storage/constants.d.ts +21 -2
  172. package/dist/storage/constants.d.ts.map +1 -1
  173. package/dist/storage/constants.js +1 -1
  174. package/dist/storage/domains/agents/inmemory.d.ts.map +1 -1
  175. package/dist/storage/domains/datasets/base.d.ts +83 -0
  176. package/dist/storage/domains/datasets/base.d.ts.map +1 -0
  177. package/dist/storage/domains/datasets/index.d.ts +3 -0
  178. package/dist/storage/domains/datasets/index.d.ts.map +1 -0
  179. package/dist/storage/domains/datasets/inmemory.d.ts +40 -0
  180. package/dist/storage/domains/datasets/inmemory.d.ts.map +1 -0
  181. package/dist/storage/domains/experiments/base.d.ts +28 -0
  182. package/dist/storage/domains/experiments/base.d.ts.map +1 -0
  183. package/dist/storage/domains/experiments/index.d.ts +3 -0
  184. package/dist/storage/domains/experiments/index.d.ts.map +1 -0
  185. package/dist/storage/domains/experiments/inmemory.d.ts +28 -0
  186. package/dist/storage/domains/experiments/inmemory.d.ts.map +1 -0
  187. package/dist/storage/domains/index.d.ts +3 -0
  188. package/dist/storage/domains/index.d.ts.map +1 -1
  189. package/dist/storage/domains/inmemory-db.d.ts +9 -1
  190. package/dist/storage/domains/inmemory-db.d.ts.map +1 -1
  191. package/dist/storage/domains/mcp-clients/base.d.ts +47 -0
  192. package/dist/storage/domains/mcp-clients/base.d.ts.map +1 -0
  193. package/dist/storage/domains/mcp-clients/index.d.ts +3 -0
  194. package/dist/storage/domains/mcp-clients/index.d.ts.map +1 -0
  195. package/dist/storage/domains/mcp-clients/inmemory.d.ts +31 -0
  196. package/dist/storage/domains/mcp-clients/inmemory.d.ts.map +1 -0
  197. package/dist/storage/domains/operations/inmemory.d.ts.map +1 -1
  198. package/dist/storage/index.cjs +201 -117
  199. package/dist/storage/index.js +2 -2
  200. package/dist/storage/mock.d.ts.map +1 -1
  201. package/dist/storage/types.d.ts +338 -3
  202. package/dist/storage/types.d.ts.map +1 -1
  203. package/dist/stream/base/output.d.ts.map +1 -1
  204. package/dist/stream/index.cjs +11 -11
  205. package/dist/stream/index.js +2 -2
  206. package/dist/stream/types.d.ts +15 -0
  207. package/dist/stream/types.d.ts.map +1 -1
  208. package/dist/test-utils/llm-mock.cjs +4 -4
  209. package/dist/test-utils/llm-mock.js +1 -1
  210. package/dist/tool-loop-agent/index.cjs +4 -4
  211. package/dist/tool-loop-agent/index.js +1 -1
  212. package/dist/tool-provider/index.cjs +4 -0
  213. package/dist/tool-provider/index.cjs.map +1 -0
  214. package/dist/tool-provider/index.d.ts +2 -0
  215. package/dist/tool-provider/index.d.ts.map +1 -0
  216. package/dist/tool-provider/index.js +3 -0
  217. package/dist/tool-provider/index.js.map +1 -0
  218. package/dist/tool-provider/types.d.ts +113 -0
  219. package/dist/tool-provider/types.d.ts.map +1 -0
  220. package/dist/utils.cjs +23 -23
  221. package/dist/utils.d.ts +1 -1
  222. package/dist/utils.d.ts.map +1 -1
  223. package/dist/utils.js +1 -1
  224. package/dist/vector/index.cjs +7 -7
  225. package/dist/vector/index.js +1 -1
  226. package/dist/workflows/evented/index.cjs +10 -10
  227. package/dist/workflows/evented/index.js +1 -1
  228. package/dist/workflows/evented/workflow-event-processor/index.d.ts.map +1 -1
  229. package/dist/workflows/handlers/control-flow.d.ts.map +1 -1
  230. package/dist/workflows/index.cjs +25 -25
  231. package/dist/workflows/index.js +1 -1
  232. package/dist/workflows/workflow.d.ts +2 -2
  233. package/dist/workflows/workflow.d.ts.map +1 -1
  234. package/dist/workspace/filesystem/filesystem.d.ts +5 -15
  235. package/dist/workspace/filesystem/filesystem.d.ts.map +1 -1
  236. package/dist/workspace/filesystem/local-filesystem.d.ts +18 -2
  237. package/dist/workspace/filesystem/local-filesystem.d.ts.map +1 -1
  238. package/dist/workspace/filesystem/mastra-filesystem.d.ts +21 -1
  239. package/dist/workspace/filesystem/mastra-filesystem.d.ts.map +1 -1
  240. package/dist/workspace/index.cjs +41 -41
  241. package/dist/workspace/index.d.ts +1 -1
  242. package/dist/workspace/index.d.ts.map +1 -1
  243. package/dist/workspace/index.js +1 -1
  244. package/dist/workspace/lifecycle.d.ts +49 -53
  245. package/dist/workspace/lifecycle.d.ts.map +1 -1
  246. package/dist/workspace/sandbox/local-sandbox.d.ts +1 -1
  247. package/dist/workspace/sandbox/local-sandbox.d.ts.map +1 -1
  248. package/dist/workspace/sandbox/mastra-sandbox.d.ts +3 -2
  249. package/dist/workspace/sandbox/mastra-sandbox.d.ts.map +1 -1
  250. package/dist/workspace/sandbox/sandbox.d.ts +3 -4
  251. package/dist/workspace/sandbox/sandbox.d.ts.map +1 -1
  252. package/dist/workspace/workspace.d.ts +2 -15
  253. package/dist/workspace/workspace.d.ts.map +1 -1
  254. package/package.json +7 -7
  255. package/src/llm/model/provider-types.generated.d.ts +1694 -1659
  256. package/tool-provider.d.ts +1 -0
  257. package/dist/chunk-2GWTJFVM.js.map +0 -1
  258. package/dist/chunk-44SUGDBR.js.map +0 -1
  259. package/dist/chunk-C3XU7ZDC.cjs.map +0 -1
  260. package/dist/chunk-CGPH7CMG.cjs.map +0 -1
  261. package/dist/chunk-ILQXPZCD.js.map +0 -1
  262. package/dist/chunk-JNE2ABVB.js.map +0 -1
  263. package/dist/chunk-KAJNBNWP.cjs.map +0 -1
  264. package/dist/chunk-PHYJYZ32.js.map +0 -1
  265. package/dist/chunk-SIZEIYNH.js.map +0 -1
  266. package/dist/chunk-TERSHTY5.cjs.map +0 -1
  267. package/dist/chunk-UE2G2LRP.cjs.map +0 -1
  268. package/dist/chunk-UHVG25VW.cjs.map +0 -1
  269. package/dist/chunk-WL3AW3YA.js.map +0 -1
  270. package/dist/chunk-YNXIGRQE.cjs.map +0 -1
  271. package/dist/docs/references/reference-cli-mastra.md +0 -336
  272. package/dist/docs/references/reference-deployer-cloudflare.md +0 -56
  273. package/dist/provider-registry-C6XCYX44.cjs +0 -40
  274. package/dist/provider-registry-NWU4YFQW.js +0 -3
@@ -24,11 +24,21 @@ export const agent = new Agent({
24
24
  });
25
25
  ```
26
26
 
27
- That's it. The agent now has humanlike long-term memory that persists across conversations.
27
+ That's it. The agent now has humanlike long-term memory that persists across conversations. Setting `observationalMemory: true` uses `google/gemini-2.5-flash` by default. To use a different model or customize thresholds, pass a config object instead:
28
+
29
+ ```typescript
30
+ const memory = new Memory({
31
+ options: {
32
+ observationalMemory: {
33
+ model: "deepseek/deepseek-reasoner",
34
+ },
35
+ },
36
+ });
37
+ ```
28
38
 
29
39
  See [configuration options](https://mastra.ai/reference/memory/observational-memory) for full API details.
30
40
 
31
- > **Note:** OM currently only supports `@mastra/pg`, `@mastra/libsql`, and `@mastra/mongodb` storage adapters. It also uses background agents for managing memory. The default model (configurable) is `google/gemini-2.5-flash` as it's the one we've tested the most.
41
+ > **Note:** OM currently only supports `@mastra/pg`, `@mastra/libsql`, and `@mastra/mongodb` storage adapters. It uses background agents for managing memory. When using `observationalMemory: true`, the default model is `google/gemini-2.5-flash`. When passing a config object, a `model` must be explicitly set.
32
42
 
33
43
  ## Benefits
34
44
 
@@ -77,7 +87,9 @@ The result is a three-tier system:
77
87
 
78
88
  The Observer and Reflector run in the background. Any model that works with Mastra's model routing (e.g. `openai/...`, `google/...`, `deepseek/...`) can be used.
79
89
 
80
- The default is `google/gemini-2.5-flash` it works well for both observation and reflection, and its 1M token context window gives the Reflector headroom.
90
+ When using `observationalMemory: true`, the default model is `google/gemini-2.5-flash`. When passing a config object, a `model` must be explicitly set.
91
+
92
+ We recommend `google/gemini-2.5-flash` — it works well for both observation and reflection, and its 1M token context window gives the Reflector headroom.
81
93
 
82
94
  We've also tested `deepseek`, `qwen3`, and `glm-4.7` for the Observer. For the Reflector, make sure the model's context window can fit all observations. Note that Claude 4.5 models currently don't work well as observer or reflector.
83
95
 
@@ -97,24 +109,40 @@ See [model configuration](https://mastra.ai/reference/memory/observational-memor
97
109
 
98
110
  ### Thread scope (default)
99
111
 
100
- Each thread has its own observations.
112
+ Each thread has its own observations. This scope is well tested and works well as a general purpose memory system, especially for long horizon agentic use-cases.
101
113
 
102
114
  ```typescript
103
- observationalMemory: {
104
- scope: "thread",
105
- }
115
+ const memory = new Memory({
116
+ options: {
117
+ observationalMemory: {
118
+ model: "google/gemini-2.5-flash",
119
+ scope: "thread",
120
+ },
121
+ },
122
+ });
106
123
  ```
107
124
 
108
- ### Resource scope
125
+ ### Resource scope (experimental)
109
126
 
110
127
  Observations are shared across all threads for a resource (typically a user). Enables cross-conversation memory.
111
128
 
112
129
  ```typescript
113
- observationalMemory: {
114
- scope: "resource",
115
- }
130
+ const memory = new Memory({
131
+ options: {
132
+ observationalMemory: {
133
+ model: "google/gemini-2.5-flash",
134
+ scope: "resource",
135
+ },
136
+ },
137
+ });
116
138
  ```
117
139
 
140
+ Resource scope works, however it's marked as experimental for now until we prove task adherence/continuity across multiple ongoing simultaneous threads. As of today, you may need to tweak your system prompt to prevent one thread from continuing the work that another had already started (but hadn't finished).
141
+
142
+ This is because in resource scope, each thread is a perspective on _all_ threads for the resource.
143
+
144
+ For your use-case this may not be a problem, so your mileage may vary.
145
+
118
146
  > **Warning:** In resource scope, unobserved messages across _all_ threads are processed together. For users with many existing threads, this can be slow. Use thread scope for existing apps.
119
147
 
120
148
  ## Token Budgets
@@ -125,6 +153,7 @@ OM uses token thresholds to decide when to observe and reflect. See [token budge
125
153
  const memory = new Memory({
126
154
  options: {
127
155
  observationalMemory: {
156
+ model: "google/gemini-2.5-flash",
128
157
  observation: {
129
158
  // when to run the Observer (default: 30,000)
130
159
  messageTokens: 30_000,
@@ -134,12 +163,58 @@ const memory = new Memory({
134
163
  observationTokens: 40_000,
135
164
  },
136
165
  // let message history borrow from observation budget
166
+ // requires bufferTokens: false (temporary limitation)
137
167
  shareTokenBudget: false,
138
168
  },
139
169
  },
140
170
  });
141
171
  ```
142
172
 
173
+ ## Async Buffering
174
+
175
+ Without async buffering, the Observer runs synchronously when the message threshold is reached — the agent pauses mid-conversation while the Observer LLM call completes. With async buffering (enabled by default), observations are pre-computed in the background as the conversation grows. When the threshold is hit, buffered observations activate instantly with no pause.
176
+
177
+ ### How it works
178
+
179
+ As the agent converses, message tokens accumulate. At regular intervals (`bufferTokens`), a background Observer call runs without blocking the agent. Each call produces a "chunk" of observations that's stored in a buffer.
180
+
181
+ When message tokens reach the `messageTokens` threshold, buffered chunks activate: their observations move into the active observation log, and the corresponding raw messages are removed from the context window. The agent never pauses.
182
+
183
+ If the agent produces messages faster than the Observer can process them, a `blockAfter` safety threshold forces a synchronous observation as a last resort.
184
+
185
+ Reflection works similarly — the Reflector runs in the background when observations reach a fraction of the reflection threshold.
186
+
187
+ ### Settings
188
+
189
+ | Setting | Default | What it controls |
190
+ | ------------------------------ | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
191
+ | `observation.bufferTokens` | `0.2` | How often to buffer. `0.2` means every 20% of `messageTokens` — with the default 30k threshold, that's roughly every 6k tokens. Can also be an absolute token count (e.g. `5000`). |
192
+ | `observation.bufferActivation` | `0.8` | How aggressively to clear the message window on activation. `0.8` means remove enough messages to keep only 20% of `messageTokens` remaining. Lower values keep more message history. |
193
+ | `observation.blockAfter` | `1.2` | Safety threshold as a multiplier of `messageTokens`. At `1.2`, synchronous observation is forced at 36k tokens (1.2 × 30k). Only matters if buffering can't keep up. |
194
+ | `reflection.bufferActivation` | `0.5` | When to start background reflection. `0.5` means reflection begins when observations reach 50% of the `observationTokens` threshold. |
195
+ | `reflection.blockAfter` | `1.2` | Safety threshold for reflection, same logic as observation. |
196
+
197
+ ### Disabling
198
+
199
+ To disable async buffering and use synchronous observation/reflection instead:
200
+
201
+ ```typescript
202
+ const memory = new Memory({
203
+ options: {
204
+ observationalMemory: {
205
+ model: "google/gemini-2.5-flash",
206
+ observation: {
207
+ bufferTokens: false,
208
+ },
209
+ },
210
+ },
211
+ });
212
+ ```
213
+
214
+ Setting `bufferTokens: false` disables both observation and reflection async buffering. See [async buffering configuration](https://mastra.ai/reference/memory/observational-memory) for the full API.
215
+
216
+ > **Note:** Async buffering is not supported with `scope: 'resource'`. It is automatically disabled in resource scope.
217
+
143
218
  ## Migrating existing threads
144
219
 
145
220
  No manual migration needed. OM reads existing messages and observes them lazily when thresholds are exceeded.
@@ -126,6 +126,29 @@ Below is an example of events that may be emitted. Each event always includes a
126
126
  }
127
127
  ```
128
128
 
129
+ ### Foreach progress events
130
+
131
+ When a workflow uses `.foreach()`, each iteration emits a `workflow-step-progress` event. You can use these to track real-time progress:
132
+
133
+ ```typescript
134
+ for await (const chunk of stream) {
135
+ if (chunk.type === 'workflow-step-progress') {
136
+ console.log(
137
+ `${chunk.payload.id}: ${chunk.payload.completedCount}/${chunk.payload.totalCount} — ${chunk.payload.iterationStatus}`
138
+ );
139
+ }
140
+ }
141
+ ```
142
+
143
+ Each progress event includes:
144
+
145
+ - **`id`**: The step ID of the foreach step
146
+ - **`completedCount`**: Number of iterations completed so far
147
+ - **`totalCount`**: Total number of iterations
148
+ - **`currentIndex`**: Index of the iteration that just completed
149
+ - **`iterationStatus`**: Status of the iteration (`success`, `failed`, or `suspended`)
150
+ - **`iterationOutput`**: Output of the iteration (when successful)
151
+
129
152
  ## Inspecting agent networks
130
153
 
131
154
  When using multi-agent collaboration with `agent.network()`, iterate over the stream to track how tasks are delegated and executed across agents, workflows, and tools.
@@ -17,8 +17,10 @@ A filesystem provider handles all file operations for a workspace:
17
17
  Available providers:
18
18
 
19
19
  - [`LocalFilesystem`](https://mastra.ai/reference/workspace/local-filesystem) - Stores files in a directory on disk
20
+ - [`S3Filesystem`](https://mastra.ai/reference/workspace/s3-filesystem) - Stores files in Amazon S3 or S3-compatible storage (R2, MinIO)
21
+ - [`GCSFilesystem`](https://mastra.ai/reference/workspace/gcs-filesystem) - Stores files in Google Cloud Storage
20
22
 
21
- > **Tip:** `LocalFilesystem` is the simplest way to get started as it requires no external services.
23
+ > **Tip:** `LocalFilesystem` is the simplest way to get started as it requires no external services. For cloud storage, use `S3Filesystem` or `GCSFilesystem`.
22
24
 
23
25
  ## Basic usage
24
26
 
@@ -45,6 +47,25 @@ const agent = new Agent({
45
47
  const response = await agent.generate('List all files in the workspace');
46
48
  ```
47
49
 
50
+ ## Containment
51
+
52
+ By default, `LocalFilesystem` runs in **contained mode** — all file operations are restricted to stay within `basePath`. This prevents path traversal attacks and symlink escapes.
53
+
54
+ In contained mode, absolute paths that fall within `basePath` are used as-is, while other absolute paths are treated as virtual paths relative to `basePath` (e.g. `/file.txt` resolves to `basePath/file.txt`). Any resolved path that escapes `basePath` throws a `PermissionError`.
55
+
56
+ If your agent needs to access paths outside `basePath` (for example, global skills directories or user home folders), disable containment:
57
+
58
+ ```typescript
59
+ const workspace = new Workspace({
60
+ filesystem: new LocalFilesystem({
61
+ basePath: './workspace',
62
+ contained: false,
63
+ }),
64
+ });
65
+ ```
66
+
67
+ When `contained` is `false`, absolute paths are treated as real filesystem paths with no restriction.
68
+
48
69
  ## Read-only mode
49
70
 
50
71
  To prevent agents from modifying files, enable read-only mode:
@@ -60,6 +81,54 @@ const workspace = new Workspace({
60
81
 
61
82
  When read-only, write tools (`write_file`, `edit_file`, `delete`, `mkdir`) are not added to the agent's toolset. The agent can still read and list files.
62
83
 
84
+ ## Mounts and CompositeFilesystem
85
+
86
+ When you use the `mounts` option on a workspace, Mastra creates a `CompositeFilesystem` that routes file operations to the correct provider based on path prefix.
87
+
88
+ ```typescript
89
+ import { Workspace } from '@mastra/core/workspace';
90
+ import { S3Filesystem } from '@mastra/s3';
91
+ import { GCSFilesystem } from '@mastra/gcs';
92
+ import { E2BSandbox } from '@mastra/e2b';
93
+
94
+ const workspace = new Workspace({
95
+ mounts: {
96
+ '/data': new S3Filesystem({
97
+ bucket: 'my-bucket',
98
+ region: 'us-east-1',
99
+ accessKeyId: process.env.AWS_ACCESS_KEY_ID,
100
+ secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
101
+ }),
102
+ '/skills': new GCSFilesystem({
103
+ bucket: 'agent-skills',
104
+ }),
105
+ },
106
+ sandbox: new E2BSandbox({ id: 'dev-sandbox' }),
107
+ });
108
+ ```
109
+
110
+ With this configuration:
111
+
112
+ - `read_file('/data/input.csv')` reads from the S3 bucket
113
+ - `write_file('/skills/guide.md', content)` writes to the GCS bucket
114
+ - `list_directory('/')` returns virtual entries for `/data` and `/skills`
115
+ - Commands in the sandbox can access files at `/data` and `/skills` via FUSE mounts
116
+
117
+ ### Path routing
118
+
119
+ All file paths must start with a mount prefix. Operations on paths that don't match any mount will fail. Listing the root directory (`/`) returns virtual directory entries for each mount point.
120
+
121
+ Mount paths cannot be nested — for example, you cannot mount at both `/data` and `/data/sub`.
122
+
123
+ ### `filesystem` vs `mounts`
124
+
125
+ `filesystem` and `mounts` are mutually exclusive options on a workspace:
126
+
127
+ - Use **`filesystem`** when you have a single storage provider and don't need to mount it into a sandbox. The agent gets file tools that operate directly against the provider.
128
+ - Use **`mounts`** when you need cloud storage accessible inside a sandbox, or when you want to combine multiple providers. The workspace creates a CompositeFilesystem for file tools and FUSE-mounts the storage into the sandbox.
129
+
130
+ For local development, you typically don't need `mounts` — a `LocalFilesystem` and `LocalSandbox` pointed at the same directory gives you both file tools and command execution on the same files. See [configuration patterns](https://mastra.ai/docs/workspace/overview) for more detail.
131
+
63
132
  ## Agent tools
64
133
 
65
134
  When you configure a filesystem on a workspace, agents receive tools for reading, writing, listing, and deleting files. See [workspace class reference](https://mastra.ai/reference/workspace/workspace-class) for details.
@@ -67,5 +136,7 @@ When you configure a filesystem on a workspace, agents receive tools for reading
67
136
  ## Related
68
137
 
69
138
  - [LocalFilesystem reference](https://mastra.ai/reference/workspace/local-filesystem)
139
+ - [S3Filesystem reference](https://mastra.ai/reference/workspace/s3-filesystem)
140
+ - [GCSFilesystem reference](https://mastra.ai/reference/workspace/gcs-filesystem)
70
141
  - [Workspace overview](https://mastra.ai/docs/workspace/overview)
71
142
  - [Sandbox](https://mastra.ai/docs/workspace/sandbox)
@@ -75,31 +75,88 @@ export const myAgent = new Agent({
75
75
  });
76
76
  ```
77
77
 
78
- ## Initialization
78
+ ## Configuration patterns
79
79
 
80
- Calling `init()` is optional in most cases—some providers initialize on first operation. Call `init()` manually when using a workspace outside of Mastra (standalone scripts, tests) or when you need to pre-provision resources before the first agent interaction.
80
+ Workspaces support several configuration patterns depending on what capabilities your agent needs. The two main building blocks are `filesystem` (file tools) and `sandbox` (command execution), with `mounts` as the way to bridge cloud storage into sandboxes.
81
81
 
82
- ```typescript
83
- import { Workspace, LocalFilesystem, LocalSandbox } from '@mastra/core/workspace';
82
+ ### Filesystem + sandbox (local)
83
+
84
+ For local development, pair a `LocalFilesystem` and `LocalSandbox` pointed at the same directory. Since both operate on the local machine, files written through the filesystem are immediately available to commands in the sandbox:
84
85
 
86
+ ```typescript
85
87
  const workspace = new Workspace({
86
88
  filesystem: new LocalFilesystem({ basePath: './workspace' }),
87
89
  sandbox: new LocalSandbox({ workingDirectory: './workspace' }),
88
90
  });
91
+ ```
89
92
 
90
- // Optional: pre-create directories and sandbox before first use
91
- await workspace.init();
93
+ The agent receives both file tools and `execute_command`. This is the simplest full-featured setup.
94
+
95
+ ### Mounts + sandbox (cloud storage)
96
+
97
+ When you need cloud storage accessible inside a sandbox, use `mounts`. This FUSE-mounts the cloud filesystem into the sandbox so commands can read and write files at the mount path:
98
+
99
+ ```typescript
100
+ const workspace = new Workspace({
101
+ mounts: {
102
+ '/data': new S3Filesystem({
103
+ bucket: 'my-bucket',
104
+ region: 'us-east-1',
105
+ accessKeyId: process.env.AWS_ACCESS_KEY_ID,
106
+ secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
107
+ }),
108
+ '/skills': new GCSFilesystem({
109
+ bucket: 'agent-skills',
110
+ }),
111
+ },
112
+ sandbox: new E2BSandbox({ id: 'dev-sandbox' }),
113
+ });
92
114
  ```
93
115
 
94
- ### What init() does
116
+ Under the hood, `mounts` creates a [CompositeFilesystem](https://mastra.ai/docs/workspace/filesystem) that routes file tool operations to the correct provider based on path prefix. Commands in the sandbox access the mounted paths directly (e.g., `ls /data`).
95
117
 
96
- Initialization runs setup logic for each configured provider:
118
+ You can mount multiple providers at different paths. Each mount path must be unique and non-overlapping.
97
119
 
98
- - `LocalFilesystem`: Creates the base directory if it doesn't exist
99
- - `LocalSandbox`: Creates the working directory
100
- - `Search` (if configured): Indexes files from `autoIndexPaths`, see [Search and Indexing](https://mastra.ai/docs/workspace/search)
120
+ > **Note:** `filesystem` and `mounts` are mutually exclusive — you cannot use both in the same workspace. Use `filesystem` for a single provider without a sandbox, or `mounts` when you need to combine cloud storage with a sandbox.
101
121
 
102
- External providers may perform additional setup like establishing connections or authenticating.
122
+ ### Filesystem only
123
+
124
+ Use a single `filesystem` when agents only need to read and write files. No command execution is available.
125
+
126
+ ```typescript
127
+ const workspace = new Workspace({
128
+ filesystem: new S3Filesystem({
129
+ bucket: 'my-bucket',
130
+ region: 'us-east-1',
131
+ accessKeyId: process.env.AWS_ACCESS_KEY_ID,
132
+ secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
133
+ }),
134
+ });
135
+ ```
136
+
137
+ The agent receives file tools (`read_file`, `write_file`, `list_directory`, etc.) that operate directly against the storage provider.
138
+
139
+ ### Sandbox only
140
+
141
+ Use a single `sandbox` when agents only need to execute commands. No file tools are added.
142
+
143
+ ```typescript
144
+ const workspace = new Workspace({
145
+ sandbox: new E2BSandbox({ id: 'dev-sandbox' }),
146
+ });
147
+ ```
148
+
149
+ The agent receives the `execute_command` tool.
150
+
151
+ ### Which pattern should I use?
152
+
153
+ | Scenario | Pattern |
154
+ | ----------------------------------------------------- | ----------------------------------------------------- |
155
+ | Local development with files and commands | `filesystem` + `sandbox` (both local, same directory) |
156
+ | Cloud storage accessible inside a cloud sandbox | `mounts` + `sandbox` |
157
+ | Multiple cloud providers in one sandbox | `mounts` + `sandbox` (one mount per provider) |
158
+ | Agent reads/writes files, no command execution needed | `filesystem` only |
159
+ | Agent runs commands, no file tools needed | `sandbox` only |
103
160
 
104
161
  ## Tool configuration
105
162
 
@@ -147,6 +204,32 @@ When `requireReadBeforeWrite` is enabled on write tools, agents must read a file
147
204
  - **Existing files**: Must be read first
148
205
  - **Externally modified files**: If a file changed since the agent read it, the write fails
149
206
 
207
+ ## Initialization
208
+
209
+ Calling `init()` is optional in most cases—some providers initialize on first operation. Call `init()` manually when using a workspace outside of Mastra (standalone scripts, tests) or when you need to pre-provision resources before the first agent interaction.
210
+
211
+ ```typescript
212
+ import { Workspace, LocalFilesystem, LocalSandbox } from '@mastra/core/workspace';
213
+
214
+ const workspace = new Workspace({
215
+ filesystem: new LocalFilesystem({ basePath: './workspace' }),
216
+ sandbox: new LocalSandbox({ workingDirectory: './workspace' }),
217
+ });
218
+
219
+ // Optional: pre-create directories and sandbox before first use
220
+ await workspace.init();
221
+ ```
222
+
223
+ ### What init() does
224
+
225
+ Initialization runs setup logic for each configured provider:
226
+
227
+ - `LocalFilesystem`: Creates the base directory if it doesn't exist
228
+ - `LocalSandbox`: Creates the working directory
229
+ - `Search` (if configured): Indexes files from `autoIndexPaths`, see [Search and Indexing](https://mastra.ai/docs/workspace/search)
230
+
231
+ External providers may perform additional setup like establishing connections or authenticating.
232
+
150
233
  ## Related
151
234
 
152
235
  - [Filesystem](https://mastra.ai/docs/workspace/filesystem)
@@ -19,6 +19,7 @@ When you assign a workspace with a sandbox to an agent, Mastra automatically inc
19
19
  Available providers:
20
20
 
21
21
  - [`LocalSandbox`](https://mastra.ai/reference/workspace/local-sandbox) - Executes commands on the local machine
22
+ - [`E2BSandbox`](https://mastra.ai/reference/workspace/e2b-sandbox) - Executes commands in isolated E2B cloud sandboxes
22
23
 
23
24
  ## Basic usage
24
25
 
@@ -57,5 +58,6 @@ When you configure a sandbox on a workspace, agents receive the `execute_command
57
58
  ## Related
58
59
 
59
60
  - [`LocalSandbox` reference](https://mastra.ai/reference/workspace/local-sandbox)
61
+ - [`E2BSandbox` reference](https://mastra.ai/reference/workspace/e2b-sandbox)
60
62
  - [Workspace overview](https://mastra.ai/docs/workspace/overview)
61
63
  - [Filesystem](https://mastra.ai/docs/workspace/filesystem)
@@ -83,9 +83,11 @@ const storage = new LibSQLStore({
83
83
  });
84
84
  await storage.init();
85
85
 
86
+ const memoryStorage = await storage.getStore('memory');
87
+
86
88
  const model = withMastra(openai('gpt-4o'), {
87
89
  memory: {
88
- storage,
90
+ storage: memoryStorage!,
89
91
  threadId: 'user-thread-123',
90
92
  resourceId: 'user-123',
91
93
  lastMessages: 10,
@@ -111,11 +113,13 @@ import { LibSQLStore } from '@mastra/libsql';
111
113
  const storage = new LibSQLStore({ id: 'my-app', url: 'file:./data.db' });
112
114
  await storage.init();
113
115
 
116
+ const memoryStorage = await storage.getStore('memory');
117
+
114
118
  const model = withMastra(openai('gpt-4o'), {
115
119
  inputProcessors: [myGuardProcessor],
116
120
  outputProcessors: [myLoggingProcessor],
117
121
  memory: {
118
- storage,
122
+ storage: memoryStorage!,
119
123
  threadId: 'thread-123',
120
124
  resourceId: 'user-123',
121
125
  lastMessages: 10,
@@ -40,7 +40,7 @@ const { text } = await generateText({
40
40
 
41
41
  **options.memory?:** (`WithMastraMemoryOptions`): Memory configuration - enables automatic message history persistence.
42
42
 
43
- **options.memory.storage:** (`MemoryStorage`): Storage adapter for message persistence (e.g., LibSQLStore, PostgresStore).
43
+ **options.memory.storage:** (`MemoryStorage`): Memory storage domain for message persistence. Get it from a composite store using \`await storage.getStore('memory')\`.
44
44
 
45
45
  **options.memory.threadId:** (`string`): Thread ID for conversation persistence.
46
46