@mastra/mcp-docs-server 1.1.46-alpha.2 → 1.1.46-alpha.4

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 (147) hide show
  1. package/.docs/docs/agent-builder/browser.md +1 -1
  2. package/.docs/docs/agent-builder/channels.md +1 -1
  3. package/.docs/docs/agent-builder/integrations.md +73 -0
  4. package/.docs/docs/agent-builder/overview.md +1 -0
  5. package/.docs/docs/agents/adding-voice.md +1 -1
  6. package/.docs/docs/agents/agent-approval.md +2 -2
  7. package/.docs/docs/agents/background-tasks.md +1 -1
  8. package/.docs/docs/agents/channels.md +2 -2
  9. package/.docs/docs/agents/code-mode.md +20 -56
  10. package/.docs/docs/agents/overview.md +1 -0
  11. package/.docs/docs/agents/sdk-agents.md +165 -1
  12. package/.docs/docs/agents/supervisor-agents.md +40 -2
  13. package/.docs/docs/agents/using-tools.md +59 -1
  14. package/.docs/docs/browser/agent-browser.md +1 -1
  15. package/.docs/docs/browser/browser-viewer.md +22 -15
  16. package/.docs/docs/browser/overview.md +1 -1
  17. package/.docs/docs/browser/stagehand.md +1 -1
  18. package/.docs/docs/editor/overview.md +6 -6
  19. package/.docs/docs/editor/prompts.md +3 -3
  20. package/.docs/docs/editor/tools.md +2 -2
  21. package/.docs/docs/evals/evals-with-memory.md +8 -8
  22. package/.docs/docs/mastra-platform/observability.md +1 -1
  23. package/.docs/docs/mastra-platform/server.md +1 -1
  24. package/.docs/docs/mcp/mcp-apps.md +4 -4
  25. package/.docs/docs/memory/observational-memory.md +1 -1
  26. package/.docs/docs/memory/working-memory.md +2 -2
  27. package/.docs/docs/observability/integrations/bridges/datadog.md +1 -1
  28. package/.docs/docs/observability/integrations/bridges/otel.md +1 -1
  29. package/.docs/docs/observability/integrations/exporters/laminar.md +1 -1
  30. package/.docs/docs/observability/integrations/exporters/langfuse.md +26 -1
  31. package/.docs/docs/observability/integrations/exporters/mastra-platform.md +1 -1
  32. package/.docs/docs/observability/integrations/exporters/mastra-storage.md +4 -4
  33. package/.docs/docs/observability/integrations/exporters/otel.md +1 -1
  34. package/.docs/docs/observability/integrations/overview.md +1 -1
  35. package/.docs/docs/observability/logging.md +1 -1
  36. package/.docs/docs/observability/metrics/overview.md +3 -3
  37. package/.docs/docs/observability/metrics/querying.md +2 -2
  38. package/.docs/docs/observability/storage.md +2 -2
  39. package/.docs/docs/observability/tracing/overview.md +1 -1
  40. package/.docs/docs/server/auth/fga.md +15 -15
  41. package/.docs/docs/server/auth/okta.md +2 -2
  42. package/.docs/docs/server/auth/workos.md +1 -1
  43. package/.docs/docs/server/custom-api-routes.md +1 -1
  44. package/.docs/docs/server/pubsub.md +4 -4
  45. package/.docs/docs/studio/auth.md +1 -1
  46. package/.docs/docs/studio/observability.md +3 -1
  47. package/.docs/docs/workflows/scheduled-workflows.md +13 -13
  48. package/.docs/docs/workspace/filesystem.md +1 -1
  49. package/.docs/docs/workspace/lsp.md +1 -1
  50. package/.docs/docs/workspace/overview.md +35 -1
  51. package/.docs/docs/workspace/sandbox.md +4 -3
  52. package/.docs/guides/build-your-ui/ai-sdk-ui.md +2 -2
  53. package/.docs/guides/deployment/aws-bedrock-agentcore.md +3 -3
  54. package/.docs/guides/deployment/inngest.md +5 -5
  55. package/.docs/guides/deployment/temporal.md +3 -3
  56. package/.docs/guides/getting-started/nestjs.md +1 -1
  57. package/.docs/guides/migrations/mastra-cloud.md +3 -3
  58. package/.docs/guides/migrations/upgrade-to-v1/overview.md +1 -1
  59. package/.docs/guides/migrations/upgrade-to-v1/tracing.md +1 -1
  60. package/.docs/models/gateways/custom-gateways.md +57 -7
  61. package/.docs/reference/acp/acp-agent.md +2 -2
  62. package/.docs/reference/agents/agent.md +44 -0
  63. package/.docs/reference/agents/channels.md +1 -1
  64. package/.docs/reference/agents/durable-agent.md +2 -2
  65. package/.docs/reference/agents/generate.md +2 -0
  66. package/.docs/reference/agents/generateLegacy.md +2 -0
  67. package/.docs/reference/ai-sdk/handle-chat-stream.md +1 -1
  68. package/.docs/reference/ai-sdk/to-ai-sdk-stream.md +1 -1
  69. package/.docs/reference/auth/okta.md +1 -1
  70. package/.docs/reference/auth/workos.md +1 -1
  71. package/.docs/reference/browser/agent-browser.md +1 -1
  72. package/.docs/reference/browser/browser-viewer.md +11 -9
  73. package/.docs/reference/browser/stagehand-browser.md +1 -1
  74. package/.docs/reference/cli/mastra.md +3 -1
  75. package/.docs/reference/client-js/responses.md +2 -2
  76. package/.docs/reference/client-js/workflows.md +1 -1
  77. package/.docs/reference/configuration.md +1 -1
  78. package/.docs/reference/core/mastra-model-gateway.md +15 -1
  79. package/.docs/reference/core/removeWorkspace.md +26 -0
  80. package/.docs/reference/editor/browser-provider.md +1 -1
  81. package/.docs/reference/editor/storage-browser-ref.md +3 -3
  82. package/.docs/reference/editor/storage-workspace-ref.md +1 -1
  83. package/.docs/reference/evals/rubric.md +113 -0
  84. package/.docs/reference/evals/trajectory-accuracy.md +3 -3
  85. package/.docs/reference/harness/harness-class.md +81 -62
  86. package/.docs/reference/index.md +5 -0
  87. package/.docs/reference/memory/serialized-memory-config.md +1 -1
  88. package/.docs/reference/observability/metrics/automatic-metrics.md +3 -3
  89. package/.docs/reference/observability/tracing/bridges/datadog.md +1 -1
  90. package/.docs/reference/observability/tracing/exporters/cloud-exporter.md +3 -3
  91. package/.docs/reference/observability/tracing/exporters/default-exporter.md +1 -1
  92. package/.docs/reference/observability/tracing/exporters/mastra-platform-exporter.md +5 -5
  93. package/.docs/reference/observability/tracing/exporters/mastra-storage-exporter.md +1 -1
  94. package/.docs/reference/observability/tracing/exporters/otel.md +1 -1
  95. package/.docs/reference/observability/tracing/processors/sensitive-data-filter.md +2 -2
  96. package/.docs/reference/processors/cost-guard-processor.md +2 -2
  97. package/.docs/reference/processors/processor-interface.md +4 -4
  98. package/.docs/reference/processors/response-cache.md +2 -2
  99. package/.docs/reference/processors/skill-search-processor.md +3 -3
  100. package/.docs/reference/processors/tool-search-processor.md +108 -4
  101. package/.docs/reference/pubsub/base.md +1 -1
  102. package/.docs/reference/pubsub/caching-pubsub.md +2 -2
  103. package/.docs/reference/pubsub/event-emitter.md +3 -3
  104. package/.docs/reference/pubsub/google-cloud-pubsub.md +1 -1
  105. package/.docs/reference/pubsub/redis-streams.md +1 -1
  106. package/.docs/reference/pubsub/unix-socket-pubsub.md +1 -1
  107. package/.docs/reference/server/nestjs-adapter.md +2 -2
  108. package/.docs/reference/signals/task-signal-provider.md +62 -0
  109. package/.docs/reference/storage/clickhouse.md +49 -4
  110. package/.docs/reference/storage/composite.md +33 -1
  111. package/.docs/reference/storage/convex.md +2 -2
  112. package/.docs/reference/storage/dsql.md +7 -7
  113. package/.docs/reference/storage/duckdb.md +3 -3
  114. package/.docs/reference/storage/redis.md +3 -3
  115. package/.docs/reference/storage/spanner.md +7 -7
  116. package/.docs/reference/streaming/agents/stream.md +2 -0
  117. package/.docs/reference/streaming/agents/streamLegacy.md +2 -0
  118. package/.docs/reference/streaming/agents/streamUntilIdle.md +1 -1
  119. package/.docs/reference/tools/brightdata.md +3 -3
  120. package/.docs/reference/tools/create-code-mode.md +124 -0
  121. package/.docs/reference/tools/create-tool.md +1 -1
  122. package/.docs/reference/tools/mcp-client.md +5 -5
  123. package/.docs/reference/tools/mcp-server.md +45 -0
  124. package/.docs/reference/tools/perplexity.md +4 -4
  125. package/.docs/reference/tools/tavily.md +3 -3
  126. package/.docs/reference/voice/aws-nova-sonic.md +1 -1
  127. package/.docs/reference/voice/google-gemini-live.md +1 -1
  128. package/.docs/reference/voice/inworld-realtime.md +5 -5
  129. package/.docs/reference/voice/inworld.md +1 -1
  130. package/.docs/reference/voice/sarvam.md +1 -1
  131. package/.docs/reference/workspace/agentcore-runtime-sandbox.md +7 -7
  132. package/.docs/reference/workspace/azure-blob-filesystem.md +2 -2
  133. package/.docs/reference/workspace/files-sdk-filesystem.md +3 -3
  134. package/.docs/reference/workspace/google-drive-filesystem.md +7 -7
  135. package/.docs/reference/workspace/modal-sandbox.md +1 -1
  136. package/.docs/reference/workspace/railway-sandbox.md +230 -0
  137. package/.docs/reference/workspace/vercel-microvm-sandbox.md +1 -1
  138. package/.docs/reference/workspace/vercel.md +2 -2
  139. package/.docs/reference/workspace/workspace-class.md +39 -3
  140. package/CHANGELOG.md +17 -0
  141. package/dist/chunk-GLPCVXXO.js +2075 -0
  142. package/dist/chunk-GLPCVXXO.js.map +1 -0
  143. package/dist/index.js +3 -0
  144. package/dist/index.js.map +1 -0
  145. package/dist/stdio.js +1 -2070
  146. package/dist/stdio.js.map +1 -1
  147. package/package.json +4 -4
@@ -27,13 +27,17 @@ const toolSearch = new ToolSearchProcessor({
27
27
 
28
28
  **options.tools** (`Record<string, Tool>`): All tools that can be searched and loaded dynamically. These tools are not immediately available to the agent — they must be discovered via search and loaded on demand.
29
29
 
30
- **options.search** (`{ topK?: number; minScore?: number }`): Configuration for the search behavior.
30
+ **options.search** (`{ topK?: number; minScore?: number; autoLoad?: boolean }`): Configuration for the search behavior.
31
31
 
32
32
  **options.search.topK** (`number`): Maximum number of tools to return in search results.
33
33
 
34
34
  **options.search.minScore** (`number`): Minimum relevance score (0-1) for including a tool in search results.
35
35
 
36
- **options.ttl** (`number`): Time-to-live for thread state in milliseconds. After this duration of inactivity, thread state will be cleaned up. Set to 0 to disable cleanup.
36
+ **options.search.autoLoad** (`boolean`): When true, tools returned by search\_tools are activated immediately as part of the search. The load\_tool meta-tool is not exposed, collapsing the two-step search then load flow into a single search step. Discovered tools become available on the next turn. Keep topK conservative since every match is activated.
37
+
38
+ **options.storage** (`'in-memory' | 'context'`): Where loaded-tool state lives. 'in-memory' (default) tracks loaded tools in an in-memory map per thread with TTL cleanup (see ttl); state is lost on restart and anonymous requests share a 'default' entry. 'context' derives loaded state from the conversation messages — a tool is loaded while a search\_tools/load\_tool result naming it remains in the messages; it is restart-safe, requires no memory, and de-loads automatically once that result is no longer present in the messages. The 'context' store is opt-in.
39
+
40
+ **options.ttl** (`number`): Time-to-live for in-memory thread state, in milliseconds. Only applies to the default storage: 'in-memory' store; after this duration of inactivity thread state is cleaned up. Set to 0 to disable cleanup. Ignored by the 'context' store.
37
41
 
38
42
  **options.filter** (`(args: ToolSearchFilterArgs) => boolean | Promise<boolean>`): Optional request-aware hook for hiding tools from search results, blocking tool loading, or hiding already-loaded tools for the current request.
39
43
 
@@ -45,6 +49,48 @@ const toolSearch = new ToolSearchProcessor({
45
49
 
46
50
  **processInputStep** (`(args: ProcessInputStepArgs) => Promise<ProcessInputStepResult>`): Processes each step to inject search/load meta-tools and any previously loaded tools into the agent's tool set.
47
51
 
52
+ ## Methods
53
+
54
+ ### State inspection (legacy `'in-memory'` store)
55
+
56
+ These methods operate on the default `'in-memory'` store only. They're no-ops for the `'context'` store, whose state lives in the conversation messages rather than an in-process map.
57
+
58
+ #### `clearState(threadId)`
59
+
60
+ Clears the loaded-tool state for a single thread.
61
+
62
+ ```typescript
63
+ processor.clearState('thread-123')
64
+ ```
65
+
66
+ #### `clearAllState()`
67
+
68
+ Clears loaded-tool state for every thread.
69
+
70
+ ```typescript
71
+ processor.clearAllState()
72
+ ```
73
+
74
+ #### `getStateStats()`
75
+
76
+ Returns the number of tracked threads and the oldest access time, for debugging in-memory growth.
77
+
78
+ ```typescript
79
+ const { threadCount, oldestAccessTime } = processor.getStateStats()
80
+ ```
81
+
82
+ Returns: `{ threadCount: number; oldestAccessTime: number | null }`
83
+
84
+ #### `cleanupNow()`
85
+
86
+ Immediately runs TTL cleanup instead of waiting for the scheduled sweep.
87
+
88
+ ```typescript
89
+ const cleaned = processor.cleanupNow()
90
+ ```
91
+
92
+ Returns: `number` — the count of threads cleaned up.
93
+
48
94
  ## Request-aware filtering
49
95
 
50
96
  Use `filter` to apply request-specific policy to dynamic tools. The hook receives the resolved tool ID as `toolName`, the tool, request context, and phase. `toolName` is the ID returned by `search_tools`, which may differ from the key used in the `tools` object.
@@ -70,9 +116,9 @@ The `phase` value describes where the filter is being applied:
70
116
 
71
117
  - `search`: Filters results returned by `search_tools`.
72
118
  - `load`: Blocks `load_tool` from loading disallowed tools.
73
- - `active`: Hides already-loaded tools from the current request if they are no longer allowed.
119
+ - `active`: Hides already-loaded tools from the current request if they're no longer allowed.
74
120
 
75
- If the hook throws or rejects, `ToolSearchProcessor` treats the tool as disallowed for that request. The hook may run for every matching search candidate, so keep async policy checks cheap or cached. The meta-tools `search_tools` and `load_tool` are always available. Tools passed directly through the agent or `processInputStep` remain available unless you filter them outside `ToolSearchProcessor`.
121
+ If the hook throws or rejects, `ToolSearchProcessor` treats the tool as disallowed for that request. The hook may run for every matching search candidate, so keep async policy checks cheap or cached. The `search_tools` meta-tool is always available; `load_tool` is available unless `search.autoLoad` is enabled. Tools passed directly through the agent or `processInputStep` remain available unless you filter them outside `ToolSearchProcessor`.
76
122
 
77
123
  ## Extended usage example
78
124
 
@@ -114,6 +160,64 @@ The agent workflow is:
114
160
  4. The loaded tool becomes available on the next turn
115
161
  5. Agent uses the loaded tool normally
116
162
 
163
+ ## Single-step discovery with `autoLoad`
164
+
165
+ Set `search.autoLoad` to `true` to skip the separate load step. The tools returned by `search_tools` are activated immediately, and the `load_tool` meta-tool isn't exposed. This removes one model turn per discovery, which lowers token usage and latency, and works the same across providers.
166
+
167
+ ```typescript
168
+ const toolSearch = new ToolSearchProcessor({
169
+ tools: allTools,
170
+ search: {
171
+ topK: 3,
172
+ autoLoad: true,
173
+ },
174
+ })
175
+ ```
176
+
177
+ With `autoLoad` the workflow becomes:
178
+
179
+ 1. Agent receives a user message
180
+ 2. Agent calls `search_tools` with keywords
181
+ 3. The matching tools are activated automatically and become available on the next turn
182
+ 4. Agent uses the tool normally
183
+
184
+ Every match is activated, so keep `topK` small (for example, `3`) to avoid adding tools the agent didn't need. Activated tools are appended after existing tools, which keeps the cached prompt prefix stable for providers that support prompt caching.
185
+
186
+ ## Loaded-tool storage
187
+
188
+ The `storage` option controls where the set of loaded tools is tracked. The default is `'in-memory'`; the `'context'` store is opt-in.
189
+
190
+ ### `'in-memory'` (default)
191
+
192
+ Loaded tools are tracked in an in-memory map per thread, with TTL-based cleanup controlled by the `ttl` option (default one hour). This is the original behavior:
193
+
194
+ - Requires no memory configuration.
195
+ - State is lost on process restart.
196
+ - Requests with no thread ID share a single `'default'` entry.
197
+
198
+ Use `clearState`, `clearAllState`, `getStateStats`, and `cleanupNow` to inspect or reset this store.
199
+
200
+ ### `'context'`
201
+
202
+ Loaded state is derived from the conversation messages: a tool is loaded while a `search_tools` or `load_tool` result naming it remains in the messages. This mode:
203
+
204
+ - Requires no memory configuration.
205
+ - Is restart-safe — the durable record is the persisted message history.
206
+ - De-loads a tool automatically once that result is no longer present in the messages.
207
+
208
+ ```typescript
209
+ import { ToolSearchProcessor } from '@mastra/core/processors'
210
+
211
+ const toolSearch = new ToolSearchProcessor({
212
+ tools: allTools,
213
+ storage: 'context',
214
+ })
215
+ ```
216
+
217
+ Loading tools is cache-friendly in both modes: loads are append-only, so the cached prompt prefix stays stable for providers that support prompt caching.
218
+
219
+ Unloading a tool changes the tool definitions sent to the model, which shifts the cached prefix and causes the next turn to pay a cache write instead of a cache hit. In `'in-memory'` mode this happens when a thread's state is evicted by `ttl`. In `'context'` mode it happens when a tool's discovery result is no longer present in the messages (for example, when older messages are trimmed) — the tool de-loads and the model must search for it again before reuse. This is expected: removing an unused tool trades one cache write for a smaller prefix on later turns.
220
+
117
221
  ## Combining with other processors
118
222
 
119
223
  ```typescript
@@ -165,7 +165,7 @@ await pubsub.subscribeFromOffset('my-topic', 42, event => {
165
165
 
166
166
  ### `SubscribeBatchOptions`
167
167
 
168
- Per-subscription batching policy. The callback signature does not change; a batch of N events becomes N consecutive callback invocations in publish order.
168
+ Per-subscription batching policy. The callback signature doesn't change; a batch of N events becomes N consecutive callback invocations in publish order.
169
169
 
170
170
  **maxSize** (`number`): Maximum events held before forcing a flush.
171
171
 
@@ -2,9 +2,9 @@
2
2
 
3
3
  `CachingPubSub` wraps any [`PubSub`](https://mastra.ai/reference/pubsub/base) implementation and adds event caching and replay. It records every published event per topic in a cache, so a subscriber that connects late or reconnects after a disconnect can replay the events it missed before continuing with live events.
4
4
 
5
- Use it to build resumable streams on top of a transport that does not keep history, such as [`EventEmitterPubSub`](https://mastra.ai/reference/pubsub/event-emitter). Transports that already persist events, such as [`RedisStreamsPubSub`](https://mastra.ai/reference/pubsub/redis-streams), do not need this wrapper.
5
+ Use it to build resumable streams on top of a transport that doesn't keep history, such as [`EventEmitterPubSub`](https://mastra.ai/reference/pubsub/event-emitter). Transports that already persist events, such as [`RedisStreamsPubSub`](https://mastra.ai/reference/pubsub/redis-streams), don't need this wrapper.
6
6
 
7
- `CachingPubSub` is transparent to batching: `subscribe()` forwards `options.batch` to the inner pub/sub, and `supportsNativeBatching` mirrors the inner's value. Wrapping an inner that does not support batching results in unbatched delivery even when `options.batch` is passed.
7
+ `CachingPubSub` is transparent to batching: `subscribe()` forwards `options.batch` to the inner pub/sub, and `supportsNativeBatching` mirrors the inner's value. Wrapping an inner that doesn't support batching results in unbatched delivery even when `options.batch` is passed.
8
8
 
9
9
  ## Usage example
10
10
 
@@ -4,11 +4,11 @@
4
4
 
5
5
  Use it for single-process applications. For delivery across processes on one host, see [`UnixSocketPubSub`](https://mastra.ai/reference/pubsub/unix-socket-pubsub). For distributed delivery, see [`RedisStreamsPubSub`](https://mastra.ai/reference/pubsub/redis-streams) or [`GoogleCloudPubSub`](https://mastra.ai/reference/pubsub/google-cloud-pubsub).
6
6
 
7
- Because it is in-process, events are not persisted and are not shared with other processes. Wrap it in [`CachingPubSub`](https://mastra.ai/reference/pubsub/caching-pubsub) when you need replay for resumable streams.
7
+ Because it's in-process, events aren't persisted and aren't shared with other processes. Wrap it in [`CachingPubSub`](https://mastra.ai/reference/pubsub/caching-pubsub) when you need replay for resumable streams.
8
8
 
9
9
  ## Usage example
10
10
 
11
- `EventEmitterPubSub` is used automatically when you do not configure a `pubsub` option, so most applications never construct it directly. Create one explicitly only when you want to configure or share it.
11
+ `EventEmitterPubSub` is used automatically when you don't configure a `pubsub` option, so most applications never construct it directly. Create one explicitly only when you want to configure or share it.
12
12
 
13
13
  ```typescript
14
14
  import { Mastra } from '@mastra/core'
@@ -104,4 +104,4 @@ await pubsub.subscribe(
104
104
  )
105
105
  ```
106
106
 
107
- The buffer is in-memory and per-process, so batched state is not persisted and does not survive a restart. A flush triggered by `maxWaitMs` is best-effort: if a step such as a throwing `coalesce` fails, the error is surfaced through the configured `logger` rather than thrown. `flush()` drains every batched subscriber buffer before resolving.
107
+ The buffer is in-memory and per-process, so batched state isn't persisted and doesn't survive a restart. A flush triggered by `maxWaitMs` is best-effort: if a step such as a throwing `coalesce` fails, the error is surfaced through the configured `logger` rather than thrown. `flush()` drains every batched subscriber buffer before resolving.
@@ -57,7 +57,7 @@ export const mastra = new Mastra({
57
57
 
58
58
  ### `init(topicName, group?)`
59
59
 
60
- Creates the topic and a subscription if they do not already exist, and returns the subscription. `subscribe` calls this internally, so you rarely call it directly.
60
+ Creates the topic and a subscription if they don't already exist, and returns the subscription. `subscribe` calls this internally, so you rarely call it directly.
61
61
 
62
62
  ```typescript
63
63
  await pubsub.init('workflow.events')
@@ -105,4 +105,4 @@ await pubsub.close()
105
105
 
106
106
  ## Redelivery and reclaim
107
107
 
108
- When a subscriber calls `nack`, the event is republished with an incremented `deliveryAttempt` and the original is acknowledged. Once an event reaches `maxDeliveryAttempts`, it is dropped instead of redelivered. Separately, each subscription periodically reclaims events that an earlier consumer in the group read but never acknowledged, controlled by `reclaimIntervalMs` and `reclaimIdleMs`.
108
+ When a subscriber calls `nack`, the event is republished with an incremented `deliveryAttempt` and the original is acknowledged. Once an event reaches `maxDeliveryAttempts`, it's dropped instead of redelivered. Separately, each subscription periodically reclaims events that an earlier consumer in the group read but never acknowledged, controlled by `reclaimIntervalMs` and `reclaimIdleMs`.
@@ -4,7 +4,7 @@
4
4
 
5
5
  Use it when several local processes need to share a stream, such as coordinating thread streams across the Mastra Code terminal interface. For single-process delivery, use [`EventEmitterPubSub`](https://mastra.ai/reference/pubsub/event-emitter). For distributed delivery across hosts, use [`RedisStreamsPubSub`](https://mastra.ai/reference/pubsub/redis-streams) or [`GoogleCloudPubSub`](https://mastra.ai/reference/pubsub/google-cloud-pubsub).
6
6
 
7
- `UnixSocketPubSub` is a push transport: events arrive without a read loop, so Mastra does not run a pull worker for it.
7
+ `UnixSocketPubSub` is a push transport: events arrive without a read loop, so Mastra doesn't run a pull worker for it.
8
8
 
9
9
  ## Usage example
10
10
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  The `@mastra/nestjs` package provides a NestJS module for running Mastra with the Express-based NestJS platform.
4
4
 
5
- It is intentionally Express-only for v1. If Nest is bootstrapped with a different HTTP adapter, `MastraModule` throws during startup instead of attempting a partial integration.
5
+ It's intentionally Express-only for v1. If Nest is bootstrapped with a different HTTP adapter, `MastraModule` throws during startup instead of attempting a partial integration.
6
6
 
7
7
  > **Info:** For general adapter concepts, see [Server Adapters](https://mastra.ai/docs/server/server-adapters).
8
8
 
@@ -51,7 +51,7 @@ import { mastra } from './mastra'
51
51
  export class AppModule {}
52
52
  ```
53
53
 
54
- > **Note:** `MastraModule` registers a catch-all controller (`@All('*')`). If it is imported before your app modules, it can intercept unrelated routes and return 404s. To avoid conflicts, import `MastraModule` last or mount it under a dedicated prefix (e.g., `/api/v1/mastra`).
54
+ > **Note:** `MastraModule` registers a catch-all controller (`@All('*')`). If it's imported before your app modules, it can intercept unrelated routes and return 404s. To avoid conflicts, import `MastraModule` last or mount it under a dedicated prefix (e.g., `/api/v1/mastra`).
55
55
 
56
56
  ```typescript
57
57
  import { NestFactory } from '@nestjs/core'
@@ -0,0 +1,62 @@
1
+ # TaskSignalProvider
2
+
3
+ Bundles the built-in task tools (`task_write`, `task_update`, `task_complete`, `task_check`) and the `TaskStateProcessor` behind a single agent registration. Use it to add a structured, durable task list to an agent without wiring the tools and processor separately.
4
+
5
+ Extends [`SignalProvider`](https://mastra.ai/reference/signals/signal-provider). The task list is stored in the thread-scoped `tasks` storage domain (the source of truth) and projected onto the agent state-signal lane by the processor, so it survives observational-memory truncation without invalidating the prompt cache.
6
+
7
+ ## Usage example
8
+
9
+ Register the provider on an agent that has `Memory` and a Mastra `storage`:
10
+
11
+ ```typescript
12
+ import { Agent } from '@mastra/core/agent'
13
+ import { TaskSignalProvider } from '@mastra/core/signals'
14
+
15
+ const agent = new Agent({
16
+ name: 'coder',
17
+ instructions: '...',
18
+ model,
19
+ memory,
20
+ signals: [new TaskSignalProvider()],
21
+ })
22
+ ```
23
+
24
+ The Agent automatically merges the four task tools into its toolset and registers the processor on its input-processor chain. No other wiring is required.
25
+
26
+ Task tracking requires a memory-backed thread (`threadId` + `resourceId`). Without memory the task tools no-op and return a result explaining that task tracking requires agent memory. The `tasks` storage domain is wired in-memory by default, so task tracking works without configuring a storage backend.
27
+
28
+ ## Constructor parameters
29
+
30
+ `TaskSignalProvider` takes no constructor arguments.
31
+
32
+ ## Properties
33
+
34
+ **id** (`'task-signals'`): Stable identifier for the provider instance.
35
+
36
+ ## Methods
37
+
38
+ ### Agent integration
39
+
40
+ These methods are called automatically by the Agent when the provider is passed to `signals`. You normally do not call them directly.
41
+
42
+ #### `getTools()`
43
+
44
+ Returns the four task tools keyed by their tool ids (`task_write`, `task_update`, `task_complete`, `task_check`). The Agent merges these into its toolset.
45
+
46
+ ```typescript
47
+ const tools = new TaskSignalProvider().getTools()
48
+ // { task_write, task_update, task_complete, task_check }
49
+ ```
50
+
51
+ Returns: `Record<string, Tool>`
52
+
53
+ #### `getInputProcessors()`
54
+
55
+ Returns the provider's `TaskStateProcessor` instance. The Agent registers it on the input-processor chain, which propagates the Mastra instance so the processor can resolve the `tasks` store.
56
+
57
+ ```typescript
58
+ const [processor] = new TaskSignalProvider().getInputProcessors()
59
+ // processor instanceof TaskStateProcessor
60
+ ```
61
+
62
+ Returns: `InputProcessorOrWorkflow[]`
@@ -8,7 +8,7 @@ ClickHouse is most commonly used as the dedicated observability backend in a [co
8
8
 
9
9
  Production observability for traces, logs, metrics, scores, and feedback.
10
10
 
11
- For local development, use a composite store that combines [LibSQL](https://mastra.ai/reference/storage/libsql) (for memory and workflows) and `@mastra/duckdb` (for observability). Neither alone covers a development setup: LibSQL does not implement the observability domain, and DuckDB does not implement the other domains. See the [observability overview](https://mastra.ai/docs/observability/overview) for an example.
11
+ For local development, use a composite store that combines [LibSQL](https://mastra.ai/reference/storage/libsql) (for memory and workflows) and `@mastra/duckdb` (for observability). Neither alone covers a development setup: LibSQL doesn't implement the observability domain, and DuckDB doesn't implement the other domains. See the [observability overview](https://mastra.ai/docs/observability/overview) for an example.
12
12
 
13
13
  ## Installation
14
14
 
@@ -44,7 +44,7 @@ You will also need a running ClickHouse server. See [Hosting options](#hosting-o
44
44
 
45
45
  `ObservabilityStorageClickhouseVNext` is the current observability domain implementation. It uses an insert-only schema backed by `ReplacingMergeTree` and is optimized for the volume produced by traces, logs, metrics, scores, and feedback.
46
46
 
47
- Compose it with another storage adapter so observability writes do not contend with your application data:
47
+ Compose it with another storage adapter so observability writes don't contend with your application data:
48
48
 
49
49
  ```typescript
50
50
  import { Mastra } from '@mastra/core'
@@ -85,7 +85,7 @@ export const mastra = new Mastra({
85
85
 
86
86
  ### Observability with the legacy domain
87
87
 
88
- `ObservabilityStorageClickhouse` is the original observability adapter and remains supported for projects that have not migrated to the vNext schema. The configuration shape is the same as the vNext class.
88
+ `ObservabilityStorageClickhouse` is the original observability adapter and remains supported for projects that haven't migrated to the vNext schema. The configuration shape is the same as the vNext class.
89
89
 
90
90
  ```typescript
91
91
  import { ObservabilityStorageClickhouse } from '@mastra/clickhouse'
@@ -182,10 +182,55 @@ The same `client` form is accepted by `ObservabilityStorageClickhouse` and `Obse
182
182
 
183
183
  **ttl** (`object`): Per-table TTL configuration applied at table creation time. Accepts row-level and column-level TTLs in interval units from \`NANOSECOND\` through \`YEAR\`.
184
184
 
185
+ **replication** (`{ cluster?: string; zookeeperPath?: string; replicaName?: string }`): Opt-in replicated table configuration for multi-replica ClickHouse clusters. When set, Mastra creates replicated MergeTree tables. When \`cluster\` is set, Mastra also adds \`ON CLUSTER\` to Mastra-owned data definition language (DDL).
186
+
185
187
  **disableInit** (`boolean`): When \`true\`, the store does not run table creation or migrations on first use. Call \`storage.init()\` explicitly from your deployment scripts. (Default: `false`)
186
188
 
187
189
  `ClickhouseStore` also accepts every option from `ClickHouseClientConfigOptions` (such as `database`, `request_timeout`, `compression`, `keep_alive`, and `max_open_connections`).
188
190
 
191
+ ### Replicated clusters
192
+
193
+ Use `replication` when Mastra writes to a multi-replica ClickHouse cluster through a load balancer.
194
+
195
+ ```typescript
196
+ const storage = new ClickhouseStoreVNext({
197
+ id: 'clickhouse-storage',
198
+ url: process.env.CLICKHOUSE_URL!,
199
+ username: process.env.CLICKHOUSE_USERNAME!,
200
+ password: process.env.CLICKHOUSE_PASSWORD!,
201
+ replication: {
202
+ cluster: 'company_cluster',
203
+ },
204
+ })
205
+ ```
206
+
207
+ When `replication` is set, Mastra rewrites its `MergeTree` and `ReplacingMergeTree` table engines to `ReplicatedMergeTree` and `ReplicatedReplacingMergeTree`. The default engine arguments are:
208
+
209
+ - `zookeeperPath`: `'/clickhouse/tables/{shard}/{database}/{table}'`
210
+ - `replicaName`: `'{replica}'`
211
+
212
+ The defaults match the most common self-managed convention. If your cluster's existing tables use a different layout (for example `/clickhouse/tables/{shard}/{table}` without the `{database}` segment), set `zookeeperPath` explicitly to match. Mastra does not read your cluster's convention from Keeper, so a mismatched default writes Mastra's metadata to a separate branch from the rest of the cluster.
213
+
214
+ ```typescript
215
+ new ClickhouseStoreVNext({
216
+ url: process.env.CLICKHOUSE_URL!,
217
+ username: process.env.CLICKHOUSE_USERNAME!,
218
+ password: process.env.CLICKHOUSE_PASSWORD!,
219
+ replication: {
220
+ cluster: 'company_cluster',
221
+ zookeeperPath: '/clickhouse/tables/{shard}/{table}',
222
+ },
223
+ })
224
+ ```
225
+
226
+ Set `cluster` to add `ON CLUSTER` to Mastra-owned DDL such as table creation, materialized view creation, column migrations, TTL changes, and table drops.
227
+
228
+ Manual maintenance such as `optimizeTable()` and `materializeTtl()` runs on every replica when `cluster` is set. These operations can be expensive on a large cluster. Prefer running them outside peak hours, and let routine merges happen on the background merge queue rather than triggering them on every restart.
229
+
230
+ If existing Mastra tables use local `MergeTree` or `ReplacingMergeTree` engines, initialization fails while `replication` is enabled. Mastra refuses to silently convert local tables because copy-and-swap is unsafe across replicas. To migrate, recreate the affected tables as `Replicated*` before enabling replication. The typical sequence is: rename the local table, run `CREATE TABLE ... ENGINE = ReplicatedMergeTree(...) ON CLUSTER ...`, run `INSERT INTO ... SELECT * FROM <renamed_local>`, then drop the renamed local table.
231
+
232
+ Do not set `replication` on ClickHouse Cloud. Cloud rewrites `MergeTree` to `SharedMergeTree` server-side, and explicit `ReplicatedMergeTree` engines produce incorrect DDL. `replication` is only for self-managed multi-replica clusters.
233
+
189
234
  ### Observability domain options
190
235
 
191
236
  `ObservabilityStorageClickhouse` and `ObservabilityStorageClickhouseVNext` accept the same connection options as `ClickhouseStore` (`url`, `username`, `password`, or a pre-configured `client`).
@@ -261,7 +306,7 @@ Two ways to provision the database:
261
306
 
262
307
  The same approach applies to other hosts with ephemeral filesystems. For application data that should also live off-host, pair this setup with a managed PostgreSQL or LibSQL/Turso instance for the `default` storage.
263
308
 
264
- > **Warning:** Do not point an embedded backend like DuckDB at a path inside an ephemeral container filesystem. Data written there is lost when the container restarts, and on some platforms the path is read-only.
309
+ > **Warning:** Don't point an embedded backend like DuckDB at a path inside an ephemeral container filesystem. Data written there is lost when the container restarts, and on some platforms the path is read-only.
265
310
 
266
311
  ## Initialization
267
312
 
@@ -240,6 +240,38 @@ const storage = new MastraCompositeStore({
240
240
  })
241
241
  ```
242
242
 
243
- > **Note:** `ObservabilityStorageClickhouseVNext` is the current observability domain implementation. The legacy `ObservabilityStorageClickhouse` class is also exported and remains supported for projects that have not migrated. See the [ClickHouse storage reference](https://mastra.ai/reference/storage/clickhouse) for details.
243
+ > **Note:** `ObservabilityStorageClickhouseVNext` is the current observability domain implementation. The legacy `ObservabilityStorageClickhouse` class is also exported and remains supported for projects that haven't migrated. See the [ClickHouse storage reference](https://mastra.ai/reference/storage/clickhouse) for details.
244
+
245
+ ### Replicated ClickHouse for multi-replica clusters
246
+
247
+ For self-managed ClickHouse clusters with multiple replicas, set `replication` so Mastra emits `ReplicatedMergeTree` engines and applies `ON CLUSTER` to its DDL:
248
+
249
+ ```typescript
250
+ import { MastraCompositeStore } from '@mastra/core/storage'
251
+ import { MemoryPG, WorkflowsPG, ScoresPG } from '@mastra/pg'
252
+ import { ObservabilityStorageClickhouseVNext } from '@mastra/clickhouse'
253
+
254
+ const storage = new MastraCompositeStore({
255
+ id: 'composite',
256
+ domains: {
257
+ memory: new MemoryPG({ connectionString: process.env.DATABASE_URL }),
258
+ workflows: new WorkflowsPG({ connectionString: process.env.DATABASE_URL }),
259
+ scores: new ScoresPG({ connectionString: process.env.DATABASE_URL }),
260
+ observability: new ObservabilityStorageClickhouseVNext({
261
+ url: process.env.CLICKHOUSE_URL,
262
+ username: process.env.CLICKHOUSE_USERNAME,
263
+ password: process.env.CLICKHOUSE_PASSWORD,
264
+ replication: {
265
+ cluster: 'production_cluster',
266
+ // Optional (defaults shown):
267
+ // zookeeperPath: '/clickhouse/tables/{shard}/{database}/{table}',
268
+ // replicaName: '{replica}',
269
+ },
270
+ }),
271
+ },
272
+ })
273
+ ```
274
+
275
+ Do not set `replication` on ClickHouse Cloud. Cloud rewrites `MergeTree` to `SharedMergeTree` server-side. See the [ClickHouse storage reference](https://mastra.ai/reference/storage/clickhouse) for the full config shape and operator notes.
244
276
 
245
277
  > **Info:** This approach is also required when using storage providers that don't support observability (like Convex, DynamoDB, or Cloudflare). See the [MastraStorageExporter documentation](https://mastra.ai/docs/observability/integrations/exporters/mastra-storage) for the full list of supported providers.
@@ -176,13 +176,13 @@ For very large cache namespaces, clear incrementally or use narrower prefixes to
176
176
 
177
177
  During batched cleanup, cache metadata can temporarily use an internal `deleted` state. The next cleanup pass removes those rows. Avoid writing new values with the same prefix until `clear()` finishes.
178
178
 
179
- `clear()` only removes rows whose stored `keyPrefix` exactly matches the configured `keyPrefix`. It does not clear nested prefixes by string prefix matching. Each `listPush()` refreshes the list TTL using the cache's configured `ttlMs`.
179
+ `clear()` only removes rows whose stored `keyPrefix` exactly matches the configured `keyPrefix`. It doesn't clear nested prefixes by string prefix matching. Each `listPush()` refreshes the list TTL using the cache's configured `ttlMs`.
180
180
 
181
181
  Use a non-empty `keyPrefix` unless you intentionally want `clear()` to remove every cache key in the deployment. Expired list rows are reclaimed incrementally during reads and writes; `clear()` removes all rows for the prefix.
182
182
 
183
183
  `ConvexServerCache` works best for durable replay of moderate-frequency events. For high-frequency token streams, prefer batching events or using a lower-latency cache backend.
184
184
 
185
- `ConvexServerCache` does not replace a distributed pub/sub transport. If your app needs live cross-process event delivery, configure a production pub/sub backend separately.
185
+ `ConvexServerCache` doesn't replace a distributed pub/sub transport. If your app needs live cross-process event delivery, configure a production pub/sub backend separately.
186
186
 
187
187
  ## Additional notes
188
188
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  The Aurora DSQL storage implementation provides storage using Amazon Aurora DSQL with IAM authentication.
4
4
 
5
- Aurora DSQL does not support PostgreSQL extensions (`CREATE EXTENSION`), including `pgvector`. For vector storage, use a separate vector store such as `@mastra/s3vectors`.
5
+ Aurora DSQL doesn't support PostgreSQL extensions (`CREATE EXTENSION`), including `pgvector`. For vector storage, use a separate vector store such as `@mastra/s3vectors`.
6
6
 
7
7
  ## Installation
8
8
 
@@ -170,7 +170,7 @@ const memoryStore = await storage.getStore('memory')
170
170
  const thread = await memoryStore?.getThreadById({ threadId: '...' })
171
171
  ```
172
172
 
173
- > **Warning:** If `init()` is not called, tables won't be created and storage operations will fail silently or throw errors.
173
+ > **Warning:** If `init()` isn't called, tables won't be created and storage operations will fail silently or throw errors.
174
174
 
175
175
  ### Direct Database and Pool Access
176
176
 
@@ -193,7 +193,7 @@ This approach is intended for advanced scenarios where low-level access is requi
193
193
 
194
194
  #### IAM-only authentication
195
195
 
196
- Connections are authenticated with IAM. There are no database passwords. `@mastra/dsql` uses `@aws/aurora-dsql-node-postgres-connector` to generate short-lived auth tokens. You can provide a custom credentials provider via `customCredentialsProvider`.
196
+ Connections are authenticated with IAM. No database passwords are required. `@mastra/dsql` uses `@aws/aurora-dsql-node-postgres-connector` to generate short-lived auth tokens. You can provide a custom credentials provider via `customCredentialsProvider`.
197
197
 
198
198
  #### Single database, schema-based isolation
199
199
 
@@ -201,7 +201,7 @@ Each cluster exposes a single database named `postgres`. Logical separation is d
201
201
 
202
202
  #### No PostgreSQL extensions
203
203
 
204
- `CREATE EXTENSION` is not supported. This includes `pgvector`, `PostGIS`, and others. For vector storage, use a separate store such as `@mastra/s3vectors` alongside `DSQLStore`.
204
+ `CREATE EXTENSION` isn't supported. This includes `pgvector`, `PostGIS`, and others. For vector storage, use a separate store such as `@mastra/s3vectors` alongside `DSQLStore`.
205
205
 
206
206
  #### JSON stored as text
207
207
 
@@ -209,7 +209,7 @@ JSON/JSONB are available as query types but not as column types. `@mastra/dsql`
209
209
 
210
210
  #### Schema and DDL constraints
211
211
 
212
- Some PostgreSQL features are not available:
212
+ Some PostgreSQL features aren't available:
213
213
 
214
214
  - Foreign key constraints
215
215
  - `TRUNCATE`
@@ -219,7 +219,7 @@ Indexes are created asynchronously using `CREATE INDEX ASYNC`. The store's `init
219
219
 
220
220
  #### Transactions and optimistic concurrency
221
221
 
222
- Aurora DSQL uses optimistic concurrency control (OCC) and may return retriable OCC errors under contention. There are limits on transaction duration and size. Large bulk operations should be split into smaller batches at the application level.
222
+ Aurora DSQL uses optimistic concurrency control (OCC) and may return retriable OCC errors under contention. Limits exist on transaction duration and size. Large bulk operations should be split into smaller batches at the application level.
223
223
 
224
224
  #### Connection lifetime
225
225
 
@@ -332,7 +332,7 @@ await storage.createIndex({
332
332
  })
333
333
  ```
334
334
 
335
- Aurora DSQL does not allow `ASC`/`DESC` in `CREATE INDEX ASYNC`. If you include them, they will be automatically stripped.
335
+ Aurora DSQL doesn't allow `ASC`/`DESC` in `CREATE INDEX ASYNC`. If you include them, they will be automatically stripped.
336
336
 
337
337
  ### Index Options
338
338
 
@@ -6,11 +6,11 @@ For vector search, see the [DuckDB vector store reference](https://mastra.ai/ref
6
6
 
7
7
  ## When to use DuckDB
8
8
 
9
- Local development of observability features. DuckDB is embedded and file-based, so it does not require a server and starts instantly. It supports the same observability signals as ClickHouse, which makes it useful for testing dashboards and trace exploration before deploying to a production backend.
9
+ Local development of observability features. DuckDB is embedded and file-based, so it doesn't require a server and starts instantly. It supports the same observability signals as ClickHouse, which makes it useful for testing dashboards and trace exploration before deploying to a production backend.
10
10
 
11
11
  DuckDB currently implements only the `observability` domain. Pair it with another storage adapter (such as [LibSQL](https://mastra.ai/reference/storage/libsql)) for `memory` and `workflows` in a [composite storage](https://mastra.ai/reference/storage/composite) setup.
12
12
 
13
- > **Warning:** DuckDB is for development and not recommended for production. It runs in-process, persists to a single local file, and does not work on platforms with ephemeral filesystems (such as Railway, Fly.io, Render, Heroku, or serverless containers). For production observability, use [ClickHouse](https://mastra.ai/reference/storage/clickhouse).
13
+ > **Warning:** DuckDB is for development and not recommended for production. It runs in-process, persists to a single local file, and doesn't work on platforms with ephemeral filesystems (such as Railway, Fly.io, Render, Heroku, or serverless containers). For production observability, use [ClickHouse](https://mastra.ai/reference/storage/clickhouse).
14
14
 
15
15
  ## Installation
16
16
 
@@ -110,7 +110,7 @@ const duckdb = new DuckDBStore({ path: ':memory:' })
110
110
 
111
111
  ### Lower-level types
112
112
 
113
- `@mastra/duckdb` also exports `DuckDBConnection` for sharing a single underlying database across multiple Mastra storage instances, and the corresponding `DuckDBStorageConfig` type. Most applications will not need these directly.
113
+ `@mastra/duckdb` also exports `DuckDBConnection` for sharing a single underlying database across multiple Mastra storage instances, and the corresponding `DuckDBStorageConfig` type. Most applications won't need these directly.
114
114
 
115
115
  ## Supported domains
116
116
 
@@ -1,6 +1,6 @@
1
1
  # Redis Storage
2
2
 
3
- The Redis storage implementation provides a high-performance storage solution using direct Redis connections via [node-redis](https://github.com/redis/node-redis) (the official Redis client for Node.js). It supports standalone Redis, and through custom client configuration, Redis Sentinel and Cluster deployments.
3
+ The Redis storage implementation provides a high-performance storage solution using direct Redis connections via [`node-redis`](https://github.com/redis/node-redis) (the official Redis client for Node.js). It supports standalone Redis, and through custom client configuration, Redis Sentinel and Cluster deployments.
4
4
 
5
5
  ## Installation
6
6
 
@@ -41,7 +41,7 @@ await storage.init()
41
41
 
42
42
  ### Using Pre-configured Client
43
43
 
44
- For advanced configurations like Sentinel or Cluster, you can pass a pre-configured redis client:
44
+ For advanced configurations like Sentinel or Cluster, you can pass a pre-configured Redis client:
45
45
 
46
46
  ```typescript
47
47
  import { RedisStore } from '@mastra/redis'
@@ -142,7 +142,7 @@ const storage = new RedisStore({
142
142
 
143
143
  ### Accessing the Underlying Client
144
144
 
145
- You can access the underlying redis client for custom operations:
145
+ You can access the underlying Redis client for custom operations:
146
146
 
147
147
  ```typescript
148
148
  const storage = new RedisStore({
@@ -138,7 +138,7 @@ Two tables also carry Spanner-specific `STORED` generated columns that the adapt
138
138
 
139
139
  Both are added via `ALTER TABLE ... ADD COLUMN IF NOT EXISTS` during `init()` and skipped under `initMode: 'validate'` (where the schema is owned externally). When the column is absent, the adapter falls back to a `JSON_VALUE` filter at runtime.
140
140
 
141
- The adapter does not create or use named schemas; use a dedicated database for isolation.
141
+ The adapter doesn't create or use named schemas; use a dedicated database for isolation.
142
142
 
143
143
  ### Initialization
144
144
 
@@ -160,7 +160,7 @@ const mastra = new Mastra({
160
160
  })
161
161
  ```
162
162
 
163
- If you use storage directly, call `init()` once before the first operation. Spanner does not allow concurrent schema changes, so `SpannerStore.init()` runs each domain's setup sequentially.
163
+ If you use storage directly, call `init()` once before the first operation. Spanner doesn't allow concurrent schema changes, so `SpannerStore.init()` runs each domain's setup sequentially.
164
164
 
165
165
  ```typescript
166
166
  const storage = new SpannerStore({
@@ -175,18 +175,18 @@ const memory = await storage.getStore('memory')
175
175
  const thread = await memory?.getThreadById({ threadId: '...' })
176
176
  ```
177
177
 
178
- > **Warning:** If `init()` is not called and `disableInit` is true, the required tables will not exist and storage operations will fail.
178
+ > **Warning:** If `init()` isn't called and `disableInit` is true, the required tables won't exist and storage operations will fail.
179
179
 
180
180
  ### GoogleSQL specifics
181
181
 
182
182
  A few behaviors differ from other relational adapters:
183
183
 
184
- - Upserts use `INSERT OR UPDATE`. Spanner does not provide a `RETURNING` clause for upserts, so callers needing the post-write state must read it back.
185
- - There is no `TRUNCATE`; `dangerouslyClearAll()` issues `DELETE WHERE TRUE`.
184
+ - Upserts use `INSERT OR UPDATE`. Spanner doesn't provide a `RETURNING` clause for upserts, so callers needing the post-write state must read it back.
185
+ - No `TRUNCATE` exists; `dangerouslyClearAll()` issues `DELETE WHERE TRUE`.
186
186
  - Identifiers are quoted with backticks.
187
187
  - DDL is applied through `database.updateSchema(...)`, which is asynchronous (long-running operation).
188
- - `NULLS FIRST/LAST` is not supported. Ordering with NULL handling is emulated through an `IS NULL` ordering key.
189
- - JSON containment is not supported natively. `listTraces` `metadata` and `scope` filters compile to per-key `JSON_VALUE(...) = @v` equality checks, and `tags` filters compile to `EXISTS` over `JSON_QUERY_ARRAY(...)`. This differs from Postgres' `@>` containment operator (which can match nested structure in a single index scan) — most one-shot lookups still work but deeply nested structural matches are not expressible.
188
+ - `NULLS FIRST/LAST` isn't supported. Ordering with NULL handling is emulated through an `IS NULL` ordering key.
189
+ - JSON containment isn't supported natively. `listTraces` `metadata` and `scope` filters compile to per-key `JSON_VALUE(...) = @v` equality checks, and `tags` filters compile to `EXISTS` over `JSON_QUERY_ARRAY(...)`. This differs from Postgres' `@>` containment operator (which can match nested structure in a single index scan) — most one-shot lookups still work but deeply nested structural matches aren't expressible.
190
190
 
191
191
  ### Direct database access
192
192
 
@@ -168,6 +168,8 @@ const stream = await agent.stream('message for agent')
168
168
 
169
169
  **options.clientTools** (`ToolsInput`): Tools that are executed on the 'client' side of the request. These tools do not have execute functions in the definition.
170
170
 
171
+ **options.hooks** (`ToolHooks`): Per-execution hooks that run before and after tool calls. Overrides matching agent-level hooks for this execution. \`beforeToolCall\` can return \`{ proceed: false, output }\` to skip the tool call.
172
+
171
173
  **options.savePerStep** (`boolean`): Save messages incrementally after each stream step completes (default: false).
172
174
 
173
175
  **options.requireToolApproval** (`boolean`): When true, all tool calls require explicit approval before execution. The stream will emit \`tool-call-approval\` chunks and pause until \`approveToolCall()\` or \`declineToolCall()\` is called.
@@ -82,6 +82,8 @@ await agent.streamLegacy('message for agent')
82
82
 
83
83
  **options.clientTools** (`ToolsInput`): Tools that are executed on the 'client' side of the request. These tools do not have execute functions in the definition.
84
84
 
85
+ **options.hooks** (`ToolHooks`): Per-execution hooks that run before and after tool calls. Overrides matching agent-level hooks for this execution. \`beforeToolCall\` can return \`{ proceed: false, output }\` to skip the tool call.
86
+
85
87
  **options.savePerStep** (`boolean`): Save messages incrementally after each stream step completes (default: false).
86
88
 
87
89
  **options.providerOptions** (`Record<string, Record<string, JSONValue>>`): Additional provider-specific options that are passed through to the underlying LLM provider. The structure is \`{ providerName: { optionKey: value } }\`. For example: \`{ openai: { reasoningEffort: 'high' }, anthropic: { maxTokens: 1000 } }\`.