@mastra/mcp-docs-server 1.2.17-alpha.18 → 1.2.17-alpha.20
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.
- package/.docs/docs/deployment/cloud-providers.md +1 -0
- package/.docs/docs/deployment/overview.md +1 -0
- package/.docs/docs/sandbox/overview.md +1 -0
- package/.docs/docs/storage.md +1 -0
- package/.docs/docs/workflows/control-flow.md +0 -4
- package/.docs/docs/workflows/human-in-the-loop.md +0 -4
- package/.docs/docs/workflows/suspend-and-resume.md +0 -4
- package/.docs/integrations/deploy/render.md +389 -0
- package/.docs/integrations/sandboxes/cloudflare-sandbox.md +118 -0
- package/.docs/integrations.md +4 -0
- package/.docs/models/environment-variables.md +2 -2
- package/.docs/models/gateways/merge-gateway.md +212 -0
- package/.docs/models/gateways/openrouter.md +4 -1
- package/.docs/models/gateways/vercel.md +2 -1
- package/.docs/models/gateways.md +1 -0
- package/.docs/models/index.md +1 -1
- package/.docs/models/providers/ambient.md +2 -2
- package/.docs/models/providers/chutes.md +1 -1
- package/.docs/models/providers/edenai.md +5 -5
- package/.docs/models/providers/hetzner.md +6 -8
- package/.docs/models/providers/hyper.md +5 -5
- package/.docs/models/providers/kilo.md +5 -3
- package/.docs/models/providers/llmgateway.md +3 -3
- package/.docs/models/providers/scx-ai.md +76 -0
- package/.docs/models/providers/wandb.md +2 -1
- package/.docs/models/providers.md +1 -2
- package/.docs/reference/editor/tool-provider.md +107 -0
- package/.docs/reference/processors/skill-search-processor.md +2 -0
- package/.docs/reference/tools/mcp-server.md +1 -1
- package/CHANGELOG.md +14 -0
- package/package.json +5 -5
- package/.docs/models/providers/merge-gateway.md +0 -268
|
@@ -21,5 +21,6 @@ The following pages show you how to deploy Mastra to specific cloud providers.
|
|
|
21
21
|
- [Inngest](https://mastra.ai/integrations/deploy/inngest)
|
|
22
22
|
- [Kubernetes](https://mastra.ai/integrations/deploy/kubernetes)
|
|
23
23
|
- [Netlify](https://mastra.ai/integrations/deploy/netlify)
|
|
24
|
+
- [Render](https://mastra.ai/integrations/deploy/render)
|
|
24
25
|
- [Temporal](https://mastra.ai/integrations/deploy/temporal)
|
|
25
26
|
- [Vercel](https://mastra.ai/integrations/deploy/vercel)
|
|
@@ -52,6 +52,7 @@ Use this option for auto-scaling, minimal infrastructure management, or when you
|
|
|
52
52
|
- [Inngest](https://mastra.ai/integrations/deploy/inngest)
|
|
53
53
|
- [Kubernetes](https://mastra.ai/integrations/deploy/kubernetes)
|
|
54
54
|
- [Netlify](https://mastra.ai/integrations/deploy/netlify)
|
|
55
|
+
- [Render](https://mastra.ai/integrations/deploy/render)
|
|
55
56
|
- [Temporal](https://mastra.ai/integrations/deploy/temporal)
|
|
56
57
|
- [Vercel](https://mastra.ai/integrations/deploy/vercel)
|
|
57
58
|
|
|
@@ -111,6 +111,7 @@ Use a remote or container backend when commands need a stronger boundary from th
|
|
|
111
111
|
- [AgentCore](https://mastra.ai/integrations/sandboxes/agentcore)
|
|
112
112
|
- [Apple Container](https://mastra.ai/integrations/sandboxes/apple-container)
|
|
113
113
|
- [Blaxel](https://mastra.ai/integrations/sandboxes/blaxel)
|
|
114
|
+
- [Cloudflare Sandbox](https://mastra.ai/integrations/sandboxes/cloudflare-sandbox)
|
|
114
115
|
- [Daytona](https://mastra.ai/integrations/sandboxes/daytona)
|
|
115
116
|
- [Docker](https://mastra.ai/integrations/sandboxes/docker)
|
|
116
117
|
- [E2B](https://mastra.ai/integrations/sandboxes/e2b)
|
package/.docs/docs/storage.md
CHANGED
|
@@ -200,6 +200,7 @@ Each provider page includes installation instructions, configuration parameters,
|
|
|
200
200
|
- [Google Cloud Spanner](https://mastra.ai/integrations/databases/spanner)
|
|
201
201
|
- [LanceDB](https://mastra.ai/integrations/databases/lancedb)
|
|
202
202
|
- [libSQL](https://mastra.ai/integrations/databases/libsql)
|
|
203
|
+
- [Mastra](https://mastra.ai/docs/mastra-platform/database)
|
|
203
204
|
- [MongoDB](https://mastra.ai/integrations/databases/mongodb)
|
|
204
205
|
- [MSSQL](https://mastra.ai/integrations/databases/mssql)
|
|
205
206
|
- [Neon Postgres](https://mastra.ai/integrations/databases/neon)
|
|
@@ -17,8 +17,6 @@ Each step connects to the next in the workflow through defined schemas that keep
|
|
|
17
17
|
|
|
18
18
|
Use `.then()` to run steps in order, allowing each step to access the result of the step before it.
|
|
19
19
|
|
|
20
|
-

|
|
21
|
-
|
|
22
20
|
```typescript
|
|
23
21
|
const step1 = createStep({
|
|
24
22
|
inputSchema: z.object({
|
|
@@ -55,8 +53,6 @@ export const testWorkflow = createWorkflow({
|
|
|
55
53
|
|
|
56
54
|
Use `.parallel()` to run steps simultaneously. All parallel steps must complete before the workflow continues to the next step. Each step's `id` is used when defining a following step's `inputSchema` and becomes the key on the `inputData` object used to access the previous step's values. The outputs of parallel steps can then be referenced or combined by a following step.
|
|
57
55
|
|
|
58
|
-

|
|
59
|
-
|
|
60
56
|
```typescript
|
|
61
57
|
const step1 = createStep({
|
|
62
58
|
id: 'step-1',
|
|
@@ -8,8 +8,6 @@ Some workflows need to pause for human input before continuing. When a workflow
|
|
|
8
8
|
|
|
9
9
|
Human-in-the-loop (HITL) input works much like [pausing a workflow](https://mastra.ai/docs/workflows/suspend-and-resume) using `suspend()`. The key difference is that when human input is required, you can return `suspend()` with a payload that provides context or guidance to the user on how to continue.
|
|
10
10
|
|
|
11
|
-

|
|
12
|
-
|
|
13
11
|
```typescript
|
|
14
12
|
import { createWorkflow, createStep } from '@mastra/core/workflows'
|
|
15
13
|
import { z } from 'zod'
|
|
@@ -93,8 +91,6 @@ The data returned by the step can include a reason and help the user understand
|
|
|
93
91
|
|
|
94
92
|
As with [restarting a workflow](https://mastra.ai/docs/workflows/suspend-and-resume), use `resume()` with `resumeData` to continue a workflow after receiving input from a human. The workflow resumes from the step where it was paused.
|
|
95
93
|
|
|
96
|
-

|
|
97
|
-
|
|
98
94
|
```typescript
|
|
99
95
|
const workflow = mastra.getWorkflow('testWorkflow')
|
|
100
96
|
const run = await workflow.createRun()
|
|
@@ -11,8 +11,6 @@ Use `suspend()` to pause workflow execution at a specific step. You can define a
|
|
|
11
11
|
- If the condition isn’t met, the workflow pauses and returns `suspend()`.
|
|
12
12
|
- If the condition is met, the workflow continues with the remaining logic in the step.
|
|
13
13
|
|
|
14
|
-

|
|
15
|
-
|
|
16
14
|
```typescript
|
|
17
15
|
const step1 = createStep({
|
|
18
16
|
id: 'step-1',
|
|
@@ -56,8 +54,6 @@ export const testWorkflow = createWorkflow({
|
|
|
56
54
|
|
|
57
55
|
Use `resume()` to restart a suspended workflow from the step where it paused. Pass `resumeData` matching the step's `resumeSchema` to satisfy the suspend condition and continue execution.
|
|
58
56
|
|
|
59
|
-

|
|
60
|
-
|
|
61
57
|
```typescript
|
|
62
58
|
import { step1 } from './workflows/test-workflow'
|
|
63
59
|
|
|
@@ -0,0 +1,389 @@
|
|
|
1
|
+
> Discover all available pages from the documentation index: https://mastra.ai/llms.txt
|
|
2
|
+
|
|
3
|
+
# Render
|
|
4
|
+
|
|
5
|
+
Deploy Mastra applications on [Render](https://render.com/). Host the Mastra API as a [web service](https://render.com/docs/web-services), or use [Render Workflows](https://render.com/docs/workflows) for long-running tasks with independent retry policies.
|
|
6
|
+
|
|
7
|
+
Choose the deployment path that fits your application:
|
|
8
|
+
|
|
9
|
+
- **Mastra API**: Deploy Mastra's [server](https://mastra.ai/docs/server/overview) as a web service with a public endpoint. The [Web Services guide](https://render.com/docs/web-services) explains how to deploy custom code or a supported [server adapter](https://mastra.ai/docs/server/server-adapters).
|
|
10
|
+
- **Mastra workflow**: Run an entire Mastra workflow within one task. Render controls the outer run, while Mastra manages its steps and state. See [Defining Workflow Tasks](https://render.com/docs/workflows-defining) for configuration details.
|
|
11
|
+
- **Distributed agent operations**: Give each operation its own compute plan, timeout, and retry policy. Render Workflows handles the execution queue and provides run observability.
|
|
12
|
+
|
|
13
|
+
This guide builds an editorial pipeline that reviews a draft from three perspectives in parallel, then passes the feedback to an editor agent. Use the links above if you want to deploy a Mastra API or execute an entire Mastra workflow as one task.
|
|
14
|
+
|
|
15
|
+
## How Render Workflows integrates with Mastra
|
|
16
|
+
|
|
17
|
+
Mastra supplies the agents and application logic, while Render Workflows defines the execution boundaries. A typical pipeline has three layers:
|
|
18
|
+
|
|
19
|
+
1. A parent task coordinates the run.
|
|
20
|
+
2. Child tasks invoke Mastra agents for focused work.
|
|
21
|
+
3. A final task combines the results.
|
|
22
|
+
|
|
23
|
+
Calling one task from another creates a chained run in a separate instance, with its own compute plan, timeout, and retry policy.
|
|
24
|
+
|
|
25
|
+
## Setup
|
|
26
|
+
|
|
27
|
+
Create an empty Mastra project named `render-workflows`:
|
|
28
|
+
|
|
29
|
+
**npm**:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
npm create mastra@latest render-workflows -- --empty
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
**pnpm**:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
pnpm create mastra render-workflows --empty
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
**Yarn**:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
yarn create mastra render-workflows --empty
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
**Bun**:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
bunx create-mastra render-workflows --empty
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Install two additional dependencies:
|
|
54
|
+
|
|
55
|
+
**npm**:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
npm install @renderinc/sdk tsx
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
**pnpm**:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
pnpm add @renderinc/sdk tsx
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
**Yarn**:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
yarn add @renderinc/sdk tsx
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
**Bun**:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
bun add @renderinc/sdk tsx
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Add your API key to an `.env` file. This example uses OpenAI, but any supported [model provider](https://mastra.ai/models) works.
|
|
80
|
+
|
|
81
|
+
```text
|
|
82
|
+
OPENAI_API_KEY=your_openai_api_key
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Install the [Render CLI](https://render.com/docs/cli) to run workflow commands from your terminal.
|
|
86
|
+
|
|
87
|
+
## Distributed agent pipeline
|
|
88
|
+
|
|
89
|
+
### Create the agents
|
|
90
|
+
|
|
91
|
+
In `src/mastra`, create an `agents` directory with `reviewer-agent.ts` and `editor-agent.ts`. Define both agents:
|
|
92
|
+
|
|
93
|
+
```ts
|
|
94
|
+
import { Agent } from '@mastra/core/agent'
|
|
95
|
+
|
|
96
|
+
export const reviewerAgent = new Agent({
|
|
97
|
+
id: 'reviewer-agent',
|
|
98
|
+
name: 'Reviewer Agent',
|
|
99
|
+
model: 'openai/gpt-5.6-sol',
|
|
100
|
+
instructions: `
|
|
101
|
+
Review the supplied draft only from the requested perspective.
|
|
102
|
+
Identify concrete problems and recommend specific changes.
|
|
103
|
+
Do not rewrite the full draft.
|
|
104
|
+
`,
|
|
105
|
+
})
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
```ts
|
|
109
|
+
import { Agent } from '@mastra/core/agent'
|
|
110
|
+
|
|
111
|
+
export const editorAgent = new Agent({
|
|
112
|
+
id: 'editor-agent',
|
|
113
|
+
name: 'Editor Agent',
|
|
114
|
+
model: 'openai/gpt-5.6-sol',
|
|
115
|
+
instructions: `
|
|
116
|
+
Revise the supplied draft using the reviewers' feedback.
|
|
117
|
+
Return the complete revised draft and nothing else.
|
|
118
|
+
Preserve accurate details and do not introduce unsupported claims.
|
|
119
|
+
`,
|
|
120
|
+
})
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Configure the Mastra instance
|
|
124
|
+
|
|
125
|
+
Add both agents to the Mastra instance in `src/mastra/index.ts`:
|
|
126
|
+
|
|
127
|
+
```ts
|
|
128
|
+
import { Mastra } from '@mastra/core/mastra'
|
|
129
|
+
import { editorAgent } from './agents/editor-agent.js'
|
|
130
|
+
import { reviewerAgent } from './agents/reviewer-agent.js'
|
|
131
|
+
|
|
132
|
+
export const mastra = new Mastra({
|
|
133
|
+
agents: {
|
|
134
|
+
editorAgent,
|
|
135
|
+
reviewerAgent,
|
|
136
|
+
},
|
|
137
|
+
})
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### Create the tasks
|
|
141
|
+
|
|
142
|
+
In `src`, create a `tasks` directory with `review-task.ts`, `revision-task.ts`, and `editorial-task.ts`.
|
|
143
|
+
|
|
144
|
+
#### Review task
|
|
145
|
+
|
|
146
|
+
The reviewer agent handles one area of focus. Its compute plan, five-minute timeout, and retry policy apply only to that analysis. A temporary model-provider failure can trigger another attempt without restarting the other reviewers.
|
|
147
|
+
|
|
148
|
+
```typescript
|
|
149
|
+
import { task } from '@renderinc/sdk/workflows'
|
|
150
|
+
import { mastra } from '../mastra/index.js'
|
|
151
|
+
|
|
152
|
+
type Review = {
|
|
153
|
+
focus: string
|
|
154
|
+
feedback: string
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export const reviewDraft = task(
|
|
158
|
+
{
|
|
159
|
+
name: 'review_draft',
|
|
160
|
+
plan: 'starter',
|
|
161
|
+
timeoutSeconds: 300,
|
|
162
|
+
retry: {
|
|
163
|
+
maxRetries: 2,
|
|
164
|
+
waitDurationMs: 1_000,
|
|
165
|
+
backoffScaling: 2,
|
|
166
|
+
},
|
|
167
|
+
},
|
|
168
|
+
async function reviewDraft(draft: string, focus: string): Promise<Review> {
|
|
169
|
+
const reviewer = mastra.getAgentById('reviewer-agent')
|
|
170
|
+
const response = await reviewer.generate(`
|
|
171
|
+
Review this draft for ${focus}.
|
|
172
|
+
Draft: ${draft}
|
|
173
|
+
`)
|
|
174
|
+
if (!response.text) {
|
|
175
|
+
throw new Error(`The ${focus} review returned no text`)
|
|
176
|
+
}
|
|
177
|
+
return {
|
|
178
|
+
focus,
|
|
179
|
+
feedback: response.text,
|
|
180
|
+
}
|
|
181
|
+
},
|
|
182
|
+
)
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
#### Revision task
|
|
186
|
+
|
|
187
|
+
This task combines the feedback and produces a revised draft. It uses a larger compute plan and a longer timeout than each reviewer.
|
|
188
|
+
|
|
189
|
+
```typescript
|
|
190
|
+
import { task } from '@renderinc/sdk/workflows'
|
|
191
|
+
import { mastra } from '../mastra/index.js'
|
|
192
|
+
|
|
193
|
+
type Review = {
|
|
194
|
+
focus: string
|
|
195
|
+
feedback: string
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
export const reviseDraft = task(
|
|
199
|
+
{
|
|
200
|
+
name: 'revise_draft',
|
|
201
|
+
plan: 'standard',
|
|
202
|
+
timeoutSeconds: 600,
|
|
203
|
+
retry: {
|
|
204
|
+
maxRetries: 2,
|
|
205
|
+
waitDurationMs: 1_000,
|
|
206
|
+
backoffScaling: 2,
|
|
207
|
+
},
|
|
208
|
+
},
|
|
209
|
+
async function reviseDraft(draft: string, reviews: Review[]): Promise<{ draft: string }> {
|
|
210
|
+
const editor = mastra.getAgentById('editor-agent')
|
|
211
|
+
const response = await editor.generate(`
|
|
212
|
+
Revise the draft using the review feedback.
|
|
213
|
+
Draft: ${draft}
|
|
214
|
+
Reviews: ${JSON.stringify(reviews, null, 2)}
|
|
215
|
+
`)
|
|
216
|
+
if (!response.text) {
|
|
217
|
+
throw new Error('The editor returned no text')
|
|
218
|
+
}
|
|
219
|
+
return {
|
|
220
|
+
draft: response.text,
|
|
221
|
+
}
|
|
222
|
+
},
|
|
223
|
+
)
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
#### Editorial task
|
|
227
|
+
|
|
228
|
+
The parent dispatches three reviews in parallel with `Promise.all()`, then sends their combined feedback to the revision step. Retries are disabled at this level because each child defines its own policy. If you enable orchestration retries, ensure that another attempt can't duplicate external side effects or other non-idempotent work.
|
|
229
|
+
|
|
230
|
+
```typescript
|
|
231
|
+
import { task } from '@renderinc/sdk/workflows'
|
|
232
|
+
import { reviewDraft } from './review-task.js'
|
|
233
|
+
import { reviseDraft } from './revision-task.js'
|
|
234
|
+
|
|
235
|
+
export const editorialPipeline = task(
|
|
236
|
+
{
|
|
237
|
+
name: 'editorial_pipeline',
|
|
238
|
+
plan: 'starter',
|
|
239
|
+
timeoutSeconds: 1_200,
|
|
240
|
+
retry: {
|
|
241
|
+
maxRetries: 0,
|
|
242
|
+
waitDurationMs: 1_000,
|
|
243
|
+
backoffScaling: 2,
|
|
244
|
+
},
|
|
245
|
+
},
|
|
246
|
+
async function editorialPipeline(draft: string): Promise<{ draft: string }> {
|
|
247
|
+
const focuses = ['technical clarity', 'structure and flow', 'reader usefulness']
|
|
248
|
+
const reviews = await Promise.all(focuses.map(focus => reviewDraft(draft, focus)))
|
|
249
|
+
return reviseDraft(draft, reviews)
|
|
250
|
+
},
|
|
251
|
+
)
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
### Set up the entry point
|
|
255
|
+
|
|
256
|
+
Create `src/index.ts` and import the editorial task:
|
|
257
|
+
|
|
258
|
+
```ts
|
|
259
|
+
import './tasks/editorial-task.js'
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
In `package.json`, add scripts to build the TypeScript project and run the workflow:
|
|
263
|
+
|
|
264
|
+
```json
|
|
265
|
+
{
|
|
266
|
+
"scripts": {
|
|
267
|
+
"build": "tsc",
|
|
268
|
+
"dev:workflows": "tsx src/index.ts",
|
|
269
|
+
"start:workflows": "node dist/index.js"
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
Configure `tsconfig.json` for the build:
|
|
275
|
+
|
|
276
|
+
```json
|
|
277
|
+
{
|
|
278
|
+
"compilerOptions": {
|
|
279
|
+
"target": "ES2022",
|
|
280
|
+
"module": "NodeNext",
|
|
281
|
+
"moduleResolution": "NodeNext",
|
|
282
|
+
"rootDir": "src",
|
|
283
|
+
"outDir": "dist",
|
|
284
|
+
"strict": true,
|
|
285
|
+
"esModuleInterop": true,
|
|
286
|
+
"skipLibCheck": true
|
|
287
|
+
},
|
|
288
|
+
"include": ["src/**/*"]
|
|
289
|
+
}
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
Build the project. The command compiles the JavaScript files into `dist`.
|
|
293
|
+
|
|
294
|
+
**npm**:
|
|
295
|
+
|
|
296
|
+
```bash
|
|
297
|
+
npm run build
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
**pnpm**:
|
|
301
|
+
|
|
302
|
+
```bash
|
|
303
|
+
pnpm run build
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
**Yarn**:
|
|
307
|
+
|
|
308
|
+
```bash
|
|
309
|
+
yarn build
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
**Bun**:
|
|
313
|
+
|
|
314
|
+
```bash
|
|
315
|
+
bun run build
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
## Run the pipeline
|
|
319
|
+
|
|
320
|
+
### Locally
|
|
321
|
+
|
|
322
|
+
Start the local development server with the Render CLI:
|
|
323
|
+
|
|
324
|
+
```bash
|
|
325
|
+
render workflows dev -- npm run dev:workflows
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
The server lists the registered tasks:
|
|
329
|
+
|
|
330
|
+
```bash
|
|
331
|
+
➜ render workflows dev -- npm run dev:workflows
|
|
332
|
+
Workflow server listening on port 8120
|
|
333
|
+
Loaded environment variables from .env
|
|
334
|
+
3 tasks found in npm run dev:workflows
|
|
335
|
+
• editorial_pipeline
|
|
336
|
+
• review_draft
|
|
337
|
+
• revise_draft
|
|
338
|
+
|
|
339
|
+
To browse and run tasks, open another terminal and run:
|
|
340
|
+
render workflows tasks list --local
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
In another terminal, confirm that the tasks are available:
|
|
344
|
+
|
|
345
|
+
```bash
|
|
346
|
+
render workflows tasks list --local
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
The command displays each task's name, ID, and creation time. Press `Ctrl+C`, then start the editorial pipeline from the same terminal:
|
|
350
|
+
|
|
351
|
+
```bash
|
|
352
|
+
render workflows tasks runs start editorial_pipeline \
|
|
353
|
+
--local \
|
|
354
|
+
--input='["Render Workflows runs long-running tasks outside the request lifecycle."]'
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
The development server records the parent run, three parallel reviews, and the final revision.
|
|
358
|
+
|
|
359
|
+
### Production
|
|
360
|
+
|
|
361
|
+
Create a workflow service from the current repository:
|
|
362
|
+
|
|
363
|
+
```bash
|
|
364
|
+
render workflows create \
|
|
365
|
+
--name mastra-workflows \
|
|
366
|
+
--repo . \
|
|
367
|
+
--runtime node \
|
|
368
|
+
--build-command "npm install && npm run build" \
|
|
369
|
+
--run-command "npm run start:workflows"
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
Add `OPENAI_API_KEY`, or the key for your chosen model provider, to the service's environment variables.
|
|
373
|
+
|
|
374
|
+
After deployment, start a production run. If needed, replace `mastra-workflows/editorial_pipeline` with the task slug shown in the Render Dashboard.
|
|
375
|
+
|
|
376
|
+
```bash
|
|
377
|
+
render workflows tasks start mastra-workflows/editorial_pipeline \
|
|
378
|
+
--input='["Render Workflows runs long-running tasks outside the request lifecycle."]'
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
Open the workflow service in the Render Dashboard to inspect each task run, attempt, result, and log stream.
|
|
382
|
+
|
|
383
|
+
## Related
|
|
384
|
+
|
|
385
|
+
- [Render Workflows documentation](https://render.com/docs/workflows)
|
|
386
|
+
- [Defining Render workflow tasks](https://render.com/docs/workflows-defining)
|
|
387
|
+
- [Triggering task runs](https://render.com/docs/workflows-running)
|
|
388
|
+
- [Render Workflows TypeScript SDK](https://render.com/docs/workflows-sdk-typescript)
|
|
389
|
+
- [Render Workflows limits and pricing](https://render.com/docs/workflows-limits)
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
> Discover all available pages from the documentation index: https://mastra.ai/llms.txt
|
|
2
|
+
|
|
3
|
+
# Cloudflare Sandbox
|
|
4
|
+
|
|
5
|
+
`CloudflareSandbox` executes commands and manages files in a remote [Cloudflare Sandbox](https://developers.cloudflare.com/sandbox/) through the [Sandbox Bridge HTTP API](https://developers.cloudflare.com/sandbox/bridge/http-api/).
|
|
6
|
+
|
|
7
|
+
> **Warning:** Deploy and secure a [Sandbox Bridge Worker](https://developers.cloudflare.com/sandbox/bridge/) before using this provider. The bridge can create and delete sandboxes, execute commands, and write files on behalf of its callers.
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
**npm**:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install @mastra/cloudflare-sandbox
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
**pnpm**:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
pnpm add @mastra/cloudflare-sandbox
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
**Yarn**:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
yarn add @mastra/cloudflare-sandbox
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
**Bun**:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
bun add @mastra/cloudflare-sandbox
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Usage
|
|
36
|
+
|
|
37
|
+
Add `CloudflareSandbox` to a workspace and assign it to an agent:
|
|
38
|
+
|
|
39
|
+
```typescript
|
|
40
|
+
import { Agent } from '@mastra/core/agent'
|
|
41
|
+
import { Workspace } from '@mastra/core/workspace'
|
|
42
|
+
import { CloudflareSandbox } from '@mastra/cloudflare-sandbox'
|
|
43
|
+
|
|
44
|
+
const workspace = new Workspace({
|
|
45
|
+
sandbox: new CloudflareSandbox({
|
|
46
|
+
baseUrl: process.env.CLOUDFLARE_SANDBOX_BRIDGE_URL!,
|
|
47
|
+
apiToken: process.env.CLOUDFLARE_SANDBOX_API_KEY,
|
|
48
|
+
workingDirectory: '/workspace',
|
|
49
|
+
commandTimeout: 300_000,
|
|
50
|
+
}),
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
export const agent = new Agent({
|
|
54
|
+
id: 'dev-agent',
|
|
55
|
+
name: 'Development agent',
|
|
56
|
+
instructions: 'You are a helpful development assistant.',
|
|
57
|
+
model: 'anthropic/claude-sonnet-4-6',
|
|
58
|
+
workspace,
|
|
59
|
+
})
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
The provider creates a remote sandbox when the workspace starts. Pass `sandboxId` to reconnect to an existing sandbox instead.
|
|
63
|
+
|
|
64
|
+
## Execute commands
|
|
65
|
+
|
|
66
|
+
Pass command arguments, environment variables, a working directory, and streaming callbacks through `executeCommand()`. The provider sends the command as an `argv` array, so the bridge handles shell escaping:
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
const result = await workspace.sandbox?.executeCommand?.('npm', ['test'], {
|
|
70
|
+
cwd: '/workspace/project',
|
|
71
|
+
env: {
|
|
72
|
+
NODE_ENV: 'test',
|
|
73
|
+
},
|
|
74
|
+
onStdout: chunk => process.stdout.write(chunk),
|
|
75
|
+
onStderr: chunk => process.stderr.write(chunk),
|
|
76
|
+
})
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Write files
|
|
80
|
+
|
|
81
|
+
Relative paths are resolved under `/workspace`. Absolute paths must also resolve within `/workspace`. Each file is sent as its own bridge request, and the bridge caps a single file at 32 MiB.
|
|
82
|
+
|
|
83
|
+
```typescript
|
|
84
|
+
await workspace.sandbox?.writeFiles?.([
|
|
85
|
+
{ path: 'src/index.ts', content: "console.log('hello')\n" },
|
|
86
|
+
{ path: '/workspace/package.json', content: JSON.stringify({ type: 'module' }) },
|
|
87
|
+
])
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Constructor parameters
|
|
91
|
+
|
|
92
|
+
**baseUrl** (`string`): URL of the deployed Cloudflare Sandbox Bridge Worker.
|
|
93
|
+
|
|
94
|
+
**apiToken** (`string`): Bearer token matching the Worker's SANDBOX\_API\_KEY secret.
|
|
95
|
+
|
|
96
|
+
**sandboxId** (`string`): Existing Cloudflare sandbox ID to reconnect to instead of creating a sandbox.
|
|
97
|
+
|
|
98
|
+
**id** (`string`): Stable Mastra identifier. Defaults to a generated UUID-based value.
|
|
99
|
+
|
|
100
|
+
**name** (`string`): Human-readable sandbox name. (Default: `Cloudflare Sandbox`)
|
|
101
|
+
|
|
102
|
+
**env** (`Record<string, string>`): Environment variables applied to every command.
|
|
103
|
+
|
|
104
|
+
**workingDirectory** (`string`): Working directory applied to every command.
|
|
105
|
+
|
|
106
|
+
**commandTimeout** (`number`): Default command timeout in milliseconds. (Default: `300000`)
|
|
107
|
+
|
|
108
|
+
**instructions** (`string | ((options) => string)`): Custom instructions returned by getInstructions().
|
|
109
|
+
|
|
110
|
+
## Lifecycle behavior
|
|
111
|
+
|
|
112
|
+
- `start()`: Reconnects to `sandboxId` or creates a remote sandbox.
|
|
113
|
+
- `stop()`: Detaches the Mastra lifecycle without deleting the remote sandbox because the bridge doesn't expose a suspend operation.
|
|
114
|
+
- `destroy()`: Deletes the remote sandbox.
|
|
115
|
+
|
|
116
|
+
## Limitations
|
|
117
|
+
|
|
118
|
+
The provider supports command execution, streamed output, and file writes. It doesn't currently expose the bridge's bucket mounts, sessions, PTY terminals, or workspace persistence routes, and it doesn't support background process management, stdin, snapshots, or port URLs.
|
package/.docs/integrations.md
CHANGED
|
@@ -36,6 +36,7 @@
|
|
|
36
36
|
- [AgentCore](https://mastra.ai/integrations/sandboxes/agentcore)
|
|
37
37
|
- [Apple Container](https://mastra.ai/integrations/sandboxes/apple-container)
|
|
38
38
|
- [Blaxel](https://mastra.ai/integrations/sandboxes/blaxel)
|
|
39
|
+
- [Cloudflare Sandbox](https://mastra.ai/integrations/sandboxes/cloudflare-sandbox)
|
|
39
40
|
- [Daytona](https://mastra.ai/integrations/sandboxes/daytona)
|
|
40
41
|
- [Docker](https://mastra.ai/integrations/sandboxes/docker)
|
|
41
42
|
- [E2B](https://mastra.ai/integrations/sandboxes/e2b)
|
|
@@ -54,6 +55,7 @@
|
|
|
54
55
|
- [Laminar](https://mastra.ai/integrations/observability/laminar)
|
|
55
56
|
- [Langfuse](https://mastra.ai/integrations/observability/langfuse)
|
|
56
57
|
- [LangSmith](https://mastra.ai/integrations/observability/langsmith)
|
|
58
|
+
- [Mastra](https://mastra.ai/docs/mastra-platform/observability)
|
|
57
59
|
- [OpenTelemetry](https://mastra.ai/integrations/observability/opentelemetry)
|
|
58
60
|
- [PostHog](https://mastra.ai/integrations/observability/posthog)
|
|
59
61
|
- [Sentry](https://mastra.ai/integrations/observability/sentry)
|
|
@@ -70,6 +72,7 @@
|
|
|
70
72
|
- [Google Cloud Spanner](https://mastra.ai/integrations/databases/spanner)
|
|
71
73
|
- [LanceDB](https://mastra.ai/integrations/databases/lancedb)
|
|
72
74
|
- [libSQL](https://mastra.ai/integrations/databases/libsql)
|
|
75
|
+
- [Mastra](https://mastra.ai/docs/mastra-platform/database)
|
|
73
76
|
- [MongoDB](https://mastra.ai/integrations/databases/mongodb)
|
|
74
77
|
- [MSSQL](https://mastra.ai/integrations/databases/mssql)
|
|
75
78
|
- [Neon Postgres](https://mastra.ai/integrations/databases/neon)
|
|
@@ -90,6 +93,7 @@
|
|
|
90
93
|
- [Kubernetes](https://mastra.ai/integrations/deploy/kubernetes)
|
|
91
94
|
- [Mastra](https://mastra.ai/docs/mastra-platform/deploy)
|
|
92
95
|
- [Netlify](https://mastra.ai/integrations/deploy/netlify)
|
|
96
|
+
- [Render](https://mastra.ai/integrations/deploy/render)
|
|
93
97
|
- [Temporal](https://mastra.ai/integrations/deploy/temporal)
|
|
94
98
|
- [Vercel](https://mastra.ai/integrations/deploy/vercel)
|
|
95
99
|
|
|
@@ -90,7 +90,6 @@ List of required environment variables for each model provider and gateway suppo
|
|
|
90
90
|
| [LucidQuery](https://mastra.ai/models/providers/lucidquery) | `lucidquery/*` | `LUCIDQUERY_API_KEY` |
|
|
91
91
|
| [Lynkr](https://mastra.ai/models/providers/lynkr) | `lynkr/*` | `LYNKR_API_KEY` |
|
|
92
92
|
| [Meganova](https://mastra.ai/models/providers/meganova) | `meganova/*` | `MEGANOVA_API_KEY` |
|
|
93
|
-
| [Merge Gateway](https://mastra.ai/models/providers/merge-gateway) | `merge-gateway/*` | `MERGE_GATEWAY_API_KEY` |
|
|
94
93
|
| [Meta](https://mastra.ai/models/providers/meta) | `meta/*` | `META_MODEL_API_KEY` |
|
|
95
94
|
| [MiniMax (minimax.io)](https://mastra.ai/models/providers/minimax) | `minimax/*` | `MINIMAX_API_KEY` |
|
|
96
95
|
| [MiniMax (minimaxi.com)](https://mastra.ai/models/providers/minimax-cn) | `minimax-cn/*` | `MINIMAX_API_KEY` |
|
|
@@ -136,7 +135,7 @@ List of required environment variables for each model provider and gateway suppo
|
|
|
136
135
|
| [Sarvam AI](https://mastra.ai/models/providers/sarvam) | `sarvam/*` | `SARVAM_API_KEY` |
|
|
137
136
|
| [Scaleway](https://mastra.ai/models/providers/scaleway) | `scaleway/*` | `SCALEWAY_API_KEY` |
|
|
138
137
|
| [SCNet Token Plan](https://mastra.ai/models/providers/scnet-token-plan) | `scnet-token-plan/*` | `SCNET_API_KEY` |
|
|
139
|
-
| [SCX.ai](https://mastra.ai/models/providers/scx)
|
|
138
|
+
| [SCX.ai](https://mastra.ai/models/providers/scx-ai) | `scx-ai/*` | `SCX_API_KEY` |
|
|
140
139
|
| [SiliconFlow](https://mastra.ai/models/providers/siliconflow) | `siliconflow/*` | `SILICONFLOW_API_KEY` |
|
|
141
140
|
| [SiliconFlow (China)](https://mastra.ai/models/providers/siliconflow-cn) | `siliconflow-cn/*` | `SILICONFLOW_CN_API_KEY` |
|
|
142
141
|
| [Snowflake Cortex](https://mastra.ai/models/providers/snowflake-cortex) | `snowflake-cortex/*` | `SNOWFLAKE_ACCOUNT`, `SNOWFLAKE_CORTEX_PAT` |
|
|
@@ -180,6 +179,7 @@ List of required environment variables for each model provider and gateway suppo
|
|
|
180
179
|
| [Zhipu AI Coding Plan](https://mastra.ai/models/providers/zhipuai-coding-plan) | `zhipuai-coding-plan/*` | `ZHIPU_API_KEY` |
|
|
181
180
|
| [Azure OpenAI](https://mastra.ai/models/gateways/azure-openai) (Gateway) | `azure-openai/*` | `AZURE_API_KEY`, `AZURE_TENANT_ID`, `AZURE_CLIENT_ID`, `AZURE_CLIENT_SECRET`, `AZURE_SUBSCRIPTION_ID` |
|
|
182
181
|
| [Mastra](https://mastra.ai/models/gateways/mastra) (Gateway) | `mastra/*` | `MASTRA_GATEWAY_API_KEY` |
|
|
182
|
+
| [Merge Gateway](https://mastra.ai/models/gateways/merge-gateway) (Gateway) | `merge-gateway/*` | `MERGE_GATEWAY_API_KEY` |
|
|
183
183
|
| [Neon](https://mastra.ai/models/gateways/neon) (Gateway) | `neon/*` | `NEON_AI_GATEWAY_BASE_URL`, `NEON_AI_GATEWAY_TOKEN` |
|
|
184
184
|
| [Netlify](https://mastra.ai/models/gateways/netlify) (Gateway) | `netlify/*` | `NETLIFY_TOKEN`, `NETLIFY_SITE_ID` |
|
|
185
185
|
| [OpenRouter](https://mastra.ai/models/gateways/openrouter) (Gateway) | `openrouter/*` | `OPENROUTER_API_KEY` |
|