decocms 0.16.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 (111) hide show
  1. package/README.md +95 -0
  2. package/dist/cli.d.ts +3 -0
  3. package/dist/cli.d.ts.map +1 -0
  4. package/dist/cli.js +373 -0
  5. package/dist/cli.js.map +1 -0
  6. package/dist/commands/add/add.d.ts +7 -0
  7. package/dist/commands/add/add.d.ts.map +1 -0
  8. package/dist/commands/add/add.js +90 -0
  9. package/dist/commands/add/add.js.map +1 -0
  10. package/dist/commands/auth/login.d.ts +2 -0
  11. package/dist/commands/auth/login.d.ts.map +1 -0
  12. package/dist/commands/auth/login.js +125 -0
  13. package/dist/commands/auth/login.js.map +1 -0
  14. package/dist/commands/auth/whoami.d.ts +2 -0
  15. package/dist/commands/auth/whoami.d.ts.map +1 -0
  16. package/dist/commands/auth/whoami.js +51 -0
  17. package/dist/commands/auth/whoami.js.map +1 -0
  18. package/dist/commands/config/configure.d.ts +2 -0
  19. package/dist/commands/config/configure.d.ts.map +1 -0
  20. package/dist/commands/config/configure.js +51 -0
  21. package/dist/commands/config/configure.js.map +1 -0
  22. package/dist/commands/create/create.d.ts +3 -0
  23. package/dist/commands/create/create.d.ts.map +1 -0
  24. package/dist/commands/create/create.js +238 -0
  25. package/dist/commands/create/create.js.map +1 -0
  26. package/dist/commands/dev/dev.d.ts +8 -0
  27. package/dist/commands/dev/dev.d.ts.map +1 -0
  28. package/dist/commands/dev/dev.js +64 -0
  29. package/dist/commands/dev/dev.js.map +1 -0
  30. package/dist/commands/dev/link.d.ts +8 -0
  31. package/dist/commands/dev/link.d.ts.map +1 -0
  32. package/dist/commands/dev/link.js +124 -0
  33. package/dist/commands/dev/link.js.map +1 -0
  34. package/dist/commands/gen/gen.d.ts +11 -0
  35. package/dist/commands/gen/gen.d.ts.map +1 -0
  36. package/dist/commands/gen/gen.js +341 -0
  37. package/dist/commands/gen/gen.js.map +1 -0
  38. package/dist/commands/hosting/deploy.d.ts +19 -0
  39. package/dist/commands/hosting/deploy.d.ts.map +1 -0
  40. package/dist/commands/hosting/deploy.js +194 -0
  41. package/dist/commands/hosting/deploy.js.map +1 -0
  42. package/dist/commands/hosting/list.d.ts +6 -0
  43. package/dist/commands/hosting/list.d.ts.map +1 -0
  44. package/dist/commands/hosting/list.js +26 -0
  45. package/dist/commands/hosting/list.js.map +1 -0
  46. package/dist/commands/hosting/promote.d.ts +11 -0
  47. package/dist/commands/hosting/promote.d.ts.map +1 -0
  48. package/dist/commands/hosting/promote.js +153 -0
  49. package/dist/commands/hosting/promote.js.map +1 -0
  50. package/dist/commands/update/update.d.ts +4 -0
  51. package/dist/commands/update/update.d.ts.map +1 -0
  52. package/dist/commands/update/update.js +242 -0
  53. package/dist/commands/update/update.js.map +1 -0
  54. package/dist/commands/update/upgrade.d.ts +4 -0
  55. package/dist/commands/update/upgrade.d.ts.map +1 -0
  56. package/dist/commands/update/upgrade.js +157 -0
  57. package/dist/commands/update/upgrade.js.map +1 -0
  58. package/dist/lib/config.d.ts +309 -0
  59. package/dist/lib/config.d.ts.map +1 -0
  60. package/dist/lib/config.js +262 -0
  61. package/dist/lib/config.js.map +1 -0
  62. package/dist/lib/constants.d.ts +10 -0
  63. package/dist/lib/constants.d.ts.map +1 -0
  64. package/dist/lib/constants.js +16 -0
  65. package/dist/lib/constants.js.map +1 -0
  66. package/dist/lib/fs.d.ts +40 -0
  67. package/dist/lib/fs.d.ts.map +1 -0
  68. package/dist/lib/fs.js +162 -0
  69. package/dist/lib/fs.js.map +1 -0
  70. package/dist/lib/mcp.d.ts +34 -0
  71. package/dist/lib/mcp.d.ts.map +1 -0
  72. package/dist/lib/mcp.js +19 -0
  73. package/dist/lib/mcp.js.map +1 -0
  74. package/dist/lib/parse-binding-tool.d.ts +12 -0
  75. package/dist/lib/parse-binding-tool.d.ts.map +1 -0
  76. package/dist/lib/parse-binding-tool.js +15 -0
  77. package/dist/lib/parse-binding-tool.js.map +1 -0
  78. package/dist/lib/prompt-ide-setup.d.ts +27 -0
  79. package/dist/lib/prompt-ide-setup.d.ts.map +1 -0
  80. package/dist/lib/prompt-ide-setup.js +158 -0
  81. package/dist/lib/prompt-ide-setup.js.map +1 -0
  82. package/dist/lib/prompt-integrations.d.ts +7 -0
  83. package/dist/lib/prompt-integrations.d.ts.map +1 -0
  84. package/dist/lib/prompt-integrations.js +84 -0
  85. package/dist/lib/prompt-integrations.js.map +1 -0
  86. package/dist/lib/prompt-workspace.d.ts +2 -0
  87. package/dist/lib/prompt-workspace.d.ts.map +1 -0
  88. package/dist/lib/prompt-workspace.js +93 -0
  89. package/dist/lib/prompt-workspace.js.map +1 -0
  90. package/dist/lib/runtime.d.ts +5 -0
  91. package/dist/lib/runtime.d.ts.map +1 -0
  92. package/dist/lib/runtime.js +15 -0
  93. package/dist/lib/runtime.js.map +1 -0
  94. package/dist/lib/session.d.ts +39 -0
  95. package/dist/lib/session.d.ts.map +1 -0
  96. package/dist/lib/session.js +124 -0
  97. package/dist/lib/session.js.map +1 -0
  98. package/dist/lib/slugify.d.ts +13 -0
  99. package/dist/lib/slugify.d.ts.map +1 -0
  100. package/dist/lib/slugify.js +27 -0
  101. package/dist/lib/slugify.js.map +1 -0
  102. package/dist/lib/supabase.d.ts +5 -0
  103. package/dist/lib/supabase.d.ts.map +1 -0
  104. package/dist/lib/supabase.js +19 -0
  105. package/dist/lib/supabase.js.map +1 -0
  106. package/dist/lib/wrangler.d.ts +9 -0
  107. package/dist/lib/wrangler.d.ts.map +1 -0
  108. package/dist/lib/wrangler.js +118 -0
  109. package/dist/lib/wrangler.js.map +1 -0
  110. package/dist/rules/deco-chat.mdc +902 -0
  111. package/package.json +79 -0
@@ -0,0 +1,902 @@
1
+ ---
2
+ description: Comprehensive guide for developing applications on the deco.chat platform, covering tools, workflows, and best practices
3
+ globs: ["**/*.ts", "**/*.tsx"]
4
+ alwaysApply: true
5
+ ---
6
+
7
+ # deco.chat Platform Development Rules
8
+
9
+ ## 🎯 Overview
10
+
11
+ deco.chat is a powerful platform for creating MCP (Model Context Protocol) tools and workflows that can automate any kind of workload. This rule file provides comprehensive guidance for developing applications on the deco.chat platform.
12
+
13
+ ## 🚀 Getting Started
14
+
15
+ ### Prerequisites
16
+ - **Deno** installed on your system
17
+ - Access to deco.chat platform
18
+ - Basic TypeScript knowledge
19
+
20
+ ### Initial Setup Commands
21
+ ```bash
22
+ # Install CLI
23
+ deno run -A jsr:@deco/cli
24
+
25
+ # Configure project
26
+ deno run -A jsr:@deco/cli config
27
+
28
+ # Development
29
+ npm run dev
30
+
31
+ # Deploy
32
+ npm run deploy
33
+ ```
34
+
35
+ ### Project Structure
36
+ ```
37
+ project/
38
+ ├── main.ts # Main application
39
+ ├── deco.gen.ts # Auto-generated types
40
+ ├── package.json # Dependencies
41
+ ├── wrangler.toml # Cloudflare config
42
+ └── README.md
43
+ ```
44
+
45
+ ## 🔧 Core Concepts
46
+
47
+ ### 1. Environment (Env) Object
48
+ The `env` object contains all available integrations and tools. Each integration is namespaced:
49
+ ```typescript
50
+ interface Env {
51
+ INTEGRATION_NAME: {
52
+ TOOL_NAME: (input: ToolInput) => Promise<ToolOutput>;
53
+ };
54
+ DECO_CHAT_WORKSPACE_API: {
55
+ // Workspace-specific tools
56
+ };
57
+ DECO_CHAT_API: {
58
+ // Global API tools
59
+ };
60
+ }
61
+ ```
62
+
63
+ ### 2. Tools
64
+ Tools are individual functions that perform specific tasks. They can:
65
+ - Call external APIs
66
+ - Process data
67
+ - Interact with databases
68
+ - Generate content using AI
69
+
70
+ ### 3. Workflows
71
+ Workflows orchestrate multiple tools using Mastra's control flow patterns. They should:
72
+ - **Split I/O operations** into separate steps
73
+ - **Use control flow** for data processing and logic
74
+ - **Keep each step focused** on a single tool invocation
75
+
76
+ ## 📝 Creating Tools
77
+
78
+ ### Core Imports
79
+ ```typescript
80
+ import { withRuntime } from "@deco/workers-runtime";
81
+ import {
82
+ createStepFromTool,
83
+ createTool,
84
+ createWorkflow,
85
+ } from "@deco/workers-runtime/mastra";
86
+ import { z } from "zod";
87
+ import { Env } from "./deco.gen";
88
+ ```
89
+
90
+ ### Basic Tool Pattern
91
+ ```typescript
92
+ const createMyTool = (env: Env) =>
93
+ createTool({
94
+ id: "TOOL_ID",
95
+ description: "Tool description",
96
+ inputSchema: z.object({
97
+ param1: z.string(),
98
+ param2: z.number().optional(),
99
+ }),
100
+ outputSchema: z.object({
101
+ result: z.string(),
102
+ }),
103
+ execute: async ({ context }) => {
104
+ // ONE tool call only
105
+ const response = await env.INTEGRATION.TOOL({
106
+ // parameters
107
+ });
108
+
109
+ return { result: response.data };
110
+ },
111
+ });
112
+ ```
113
+
114
+ ### Tool Best Practices
115
+ 1. **Single Responsibility**: Each tool should do one thing well
116
+ 2. **Input Validation**: Use Zod schemas to validate inputs
117
+ 3. **Error Handling**: Always handle potential errors gracefully
118
+ 4. **Type Safety**: Leverage TypeScript for type safety
119
+
120
+ ## 🔄 Creating Workflows
121
+
122
+ ### Workflow Philosophy - GOLDEN RULE
123
+ **IMPORTANT**: Follow this principle for optimal workflow design:
124
+ - **Each step should invoke only ONE tool** from `env.INTEGRATION_NAME.TOOL_NAME`
125
+ - **All data processing, logic, and control flow** should be handled by Mastra workflow operators
126
+ - **Split complex operations** into multiple steps rather than combining them
127
+
128
+ ### Basic Workflow Pattern
129
+ ```typescript
130
+ const createMyWorkflow = (env: Env) => {
131
+ const step1 = createStepFromTool(createTool1(env));
132
+ const step2 = createStepFromTool(createTool2(env));
133
+
134
+ return createWorkflow({
135
+ id: "WORKFLOW_ID",
136
+ inputSchema: z.object({ input: z.string() }),
137
+ outputSchema: z.object({ output: z.string() }),
138
+ })
139
+ .then(step1)
140
+ .map((context) => ({
141
+ ...context,
142
+ // Data processing here
143
+ }))
144
+ .then(step2)
145
+ .commit();
146
+ };
147
+ ```
148
+
149
+ ### Control Flow Operators
150
+
151
+ #### 1. Sequential (.then)
152
+ ```typescript
153
+ .then(step1)
154
+ .then(step2)
155
+ .then(step3)
156
+ ```
157
+
158
+ #### 2. Parallel (.parallel)
159
+ ```typescript
160
+ .parallel([
161
+ step1,
162
+ step2,
163
+ step3
164
+ ])
165
+ ```
166
+
167
+ #### 3. Conditional (.branch)
168
+ ```typescript
169
+ .branch(
170
+ (context) => condition,
171
+ (workflow) => workflow.then(stepIfTrue),
172
+ (workflow) => workflow.then(stepIfFalse)
173
+ )
174
+ ```
175
+
176
+ #### 4. Data Transformation (.map)
177
+ ```typescript
178
+ .map((context) => ({
179
+ ...context,
180
+ processedData: context.rawData.toUpperCase(),
181
+ isValid: context.rawData.length > 0
182
+ }))
183
+ ```
184
+
185
+ #### 5. Looping (.repeat)
186
+ ```typescript
187
+ .repeat(
188
+ (context) => context.items,
189
+ processItem
190
+ )
191
+ ```
192
+
193
+ ## 🔁 Looping with `.dountil`
194
+
195
+ ### What is `.dountil`?
196
+
197
+ The `.dountil` operator allows you to **repeat a workflow step** (typically a polling or status-checking tool) until a specified condition is met. This is especially useful for workflows that need to wait for an asynchronous task to complete, such as polling an external API or a long-running browser automation.
198
+
199
+ ### How does it work?
200
+
201
+ - You provide a step (created with `createStepFromTool`) that will be executed repeatedly.
202
+ - You provide a predicate function that receives the **output of the repeated step** (as `inputData`) and returns `true` when the loop should stop.
203
+
204
+ ### Usage Pattern
205
+
206
+ ```typescript
207
+ .then(scrapeStep)
208
+ .dountil(
209
+ pollTaskStep,
210
+ async ({ inputData }) => {
211
+ // inputData is the output of pollTaskStep
212
+ return inputData.status === "finished";
213
+ }
214
+ )
215
+ .map(async ({ getStepResult }) => ({
216
+ // Use getStepResult(pollTaskStep) to access the final output
217
+ output: getStepResult(pollTaskStep).output,
218
+ prompt: getStepResult(pollTaskStep).prompt,
219
+ taskId: getStepResult(pollTaskStep).taskId,
220
+ }))
221
+ ```
222
+
223
+ #### Key Points
224
+
225
+ - The **first argument** to `.dountil` is the step to repeat.
226
+ - The **second argument** is an async predicate function that receives an object with `inputData`, which is the output of the repeated step.
227
+ - The loop continues until the predicate returns `true`.
228
+ - After `.dountil`, you can use `.map` and `getStepResult(pollTaskStep)` to access the final output.
229
+
230
+ ### Real-World Example
231
+
232
+ Suppose you want to scrape a website, poll for the scraping task to finish, and then process the result:
233
+
234
+ ```typescript
235
+ const pollTaskStep = createStepFromTool(pollTaskTool);
236
+
237
+ return createWorkflow({
238
+ // ...
239
+ })
240
+ .then(scrapeStep)
241
+ .dountil(
242
+ pollTaskStep,
243
+ async ({ inputData }) => {
244
+ // inputData is the output of pollTaskStep
245
+ return inputData.status === "finished";
246
+ }
247
+ )
248
+ .map(async ({ getStepResult }) => ({
249
+ // getStepResult(pollTaskStep) gives you the final poll result
250
+ output: getStepResult(pollTaskStep).output,
251
+ prompt: getStepResult(pollTaskStep).prompt,
252
+ taskId: getStepResult(pollTaskStep).taskId,
253
+ }))
254
+ // ... continue workflow
255
+ ```
256
+
257
+ ### Best Practices
258
+
259
+ - Use `.dountil` for polling or waiting scenarios.
260
+ - Always check the output (`inputData`) of your polling step for the completion condition.
261
+ - Use `.map` and `getStepResult` after `.dountil` to extract the final result for downstream steps.
262
+
263
+ ---
264
+
265
+ **Summary Table for `.dountil`:**
266
+
267
+ | Parameter | Description |
268
+ |-------------------|------------------------------------------------------------------|
269
+ | Step | The step to repeat (e.g., polling tool) |
270
+ | Predicate | Function receiving `{ inputData }` (output of the step) |
271
+ | Loop Exit | Predicate returns `true` when loop should stop |
272
+ | Access Result | Use `.map` and `getStepResult(step)` after `.dountil` |
273
+
274
+ ---
275
+
276
+ **In short:**
277
+ `.dountil(step, predicate)` repeats `step` until `predicate({ inputData })` returns `true`. Afterward, use `.map` and `getStepResult(step)` to access the final output.
278
+
279
+ ## 🗺️ Data Transformation with `.map` and Accessing Previous Step Results
280
+
281
+ The `.map` operator allows you to transform, enrich, or combine data between tool steps. Use `.map` to:
282
+
283
+ - Prepare or reformat data for the next tool
284
+ - Combine results from multiple previous steps
285
+ - Add custom logic or computed fields
286
+
287
+ ### Basic Usage of `.map`
288
+
289
+ ```typescript
290
+ .then(fetchUserData)
291
+ .map(({ inputData }) => ({
292
+ // Add a computed field
293
+ ...inputData,
294
+ isActive: inputData.status === "active",
295
+ }))
296
+ .then(processUser)
297
+ ```
298
+
299
+ ### Accessing Previous Step Results with `getStepResult`
300
+
301
+ When you need to access the output of a specific previous step (not just the immediate last one), use the `getStepResult` function provided in the `.map` context.
302
+
303
+ ```typescript
304
+ const stepA = createStepFromTool(toolA(env));
305
+ const stepB = createStepFromTool(toolB(env));
306
+
307
+ return createWorkflow({
308
+ // ...
309
+ })
310
+ .then(stepA)
311
+ .then(stepB)
312
+ .map(({ inputData, getStepResult }) => {
313
+ const resultA = getStepResult(stepA);
314
+ const resultB = getStepResult(stepB);
315
+ return {
316
+ combined: `${resultA.value} + ${resultB.value}`,
317
+ };
318
+ })
319
+ ```
320
+
321
+ - `getStepResult(step)` retrieves the output of any previous step.
322
+ - This is especially useful when you need to merge or reference data from multiple steps.
323
+
324
+ ### Real-World Example
325
+
326
+ In a workflow that summarizes a YouTube video, you might want to combine the video search result, transcript, and summary into a single output. Here’s how you can do it:
327
+
328
+ ```typescript
329
+ const searchStep = createStepFromTool(createYouTubeSearchTool(env));
330
+ const transcriptStep = createStepFromTool(createYouTubeTranscriptTool(env));
331
+ const summarizeStep = createStepFromTool(createSummarizeTextTool(env));
332
+
333
+ return createWorkflow({
334
+ id: "YOUTUBE_VIDEO_SUMMARY",
335
+ inputSchema: z.object({ query: z.string() }),
336
+ outputSchema: z.object({
337
+ videoId: z.string(),
338
+ title: z.string(),
339
+ description: z.string(),
340
+ transcript: z.string(),
341
+ summary: z.string(),
342
+ }),
343
+ })
344
+ .then(searchStep)
345
+ .map(async ({ inputData }) => ({ videoId: inputData.videoId }))
346
+ .then(transcriptStep)
347
+ .map(async ({ inputData, getStepResult }) => {
348
+ const searchResult = getStepResult(searchStep);
349
+ return {
350
+ videoId: searchResult.videoId,
351
+ title: searchResult.title,
352
+ description: searchResult.description,
353
+ transcript: inputData.transcript,
354
+ };
355
+ })
356
+ .then(summarizeStep)
357
+ .map(async ({ inputData, getStepResult }) => {
358
+ const searchResult = getStepResult(searchStep);
359
+ const transcriptResult = getStepResult(transcriptStep);
360
+ return {
361
+ videoId: searchResult.videoId,
362
+ title: searchResult.title,
363
+ description: searchResult.description,
364
+ transcript: transcriptResult.transcript,
365
+ summary: inputData.summary,
366
+ };
367
+ })
368
+ .commit();
369
+ ```
370
+
371
+ ### Best Practices
372
+
373
+ - Use `.map` for all data processing, not inside tool `execute` functions.
374
+ - Use `getStepResult` to keep your workflow logic clear and maintainable.
375
+ - Keep each step focused on a single responsibility and use `.map` to orchestrate data flow between steps.
376
+
377
+ ## 🔌 Integration Usage Patterns
378
+
379
+ ### AI Generation
380
+ ```typescript
381
+ const aiResponse = await env.GIMENES.AGENT_GENERATE_TEXT({
382
+ message: "Your prompt",
383
+ options: { model: "gpt-4" }
384
+ });
385
+ ```
386
+
387
+ ### Database Operations
388
+ ```typescript
389
+ const dbResult = await env.DECO_CHAT_WORKSPACE_API.DATABASES_RUN_SQL({
390
+ sql: "SELECT * FROM table",
391
+ params: [param1, param2]
392
+ });
393
+ ```
394
+
395
+ ### File System Operations
396
+ ```typescript
397
+ const fileContent = await env.DECO_CHAT_WORKSPACE_API.FS_READ({
398
+ path: "/path/to/file",
399
+ expiresIn: 3600
400
+ });
401
+ ```
402
+
403
+ ## 📋 Configuration Files
404
+
405
+ ### wrangler.toml
406
+ ```toml
407
+ main = "main.ts"
408
+ compatibility_date = "2025-06-17"
409
+ compatibility_flags = [ "nodejs_compat" ]
410
+
411
+ [deco]
412
+ app = "your-app"
413
+ workspace = "your-workspace"
414
+ enable_workflows = true
415
+
416
+ [[deco.bindings]]
417
+ name = "INTEGRATION_NAME"
418
+ type = "mcp"
419
+ integration_id = "your-id"
420
+
421
+ [[migrations]]
422
+ tag = "v1"
423
+ new_classes = [ "Workflow" ]
424
+
425
+ [durable_objects]
426
+ [[durable_objects.bindings]]
427
+ name = "DECO_CHAT_WORKFLOW_DO"
428
+ class_name = "Workflow"
429
+ ```
430
+
431
+ ### package.json
432
+ ```json
433
+ {
434
+ "scripts": {
435
+ "dev": "deco dev",
436
+ "deploy": "wrangler deploy --dry-run --outdir dist && cd dist && deco deploy"
437
+ },
438
+ "dependencies": {
439
+ "@deco/workers-runtime": "npm:@jsr/deco__workers-runtime@^0.2.20",
440
+ "zod": "^3.24.2"
441
+ },
442
+ "devDependencies": {
443
+ "@deco/cli": "npm:@jsr/deco__cli@^0.5.12"
444
+ }
445
+ }
446
+ ```
447
+
448
+ ## 🎯 Golden Rules
449
+
450
+ 1. **One Tool Per Step**: Each workflow step should call only ONE `env.INTEGRATION.TOOL()`
451
+ 2. **Control Flow for Logic**: Use `.map()`, `.branch()`, `.parallel()` for data processing
452
+ 3. **Split Complex Operations**: Break down into multiple focused steps
453
+ 4. **Validate Inputs**: Always use Zod schemas
454
+ 5. **Handle Errors**: Use branching for error scenarios
455
+ 6. **Type Safety**: Leverage TypeScript and generated types
456
+
457
+ ## 🔍 Common Patterns
458
+
459
+ ### Data Validation
460
+ ```typescript
461
+ .map((context) => ({
462
+ ...context,
463
+ isValid: context.data && context.data.length > 0,
464
+ dataCount: context.data?.length || 0
465
+ }))
466
+ ```
467
+
468
+ ### Error Handling
469
+ ```typescript
470
+ .branch(
471
+ (context) => context.isValid,
472
+ (workflow) => workflow.then(processData),
473
+ (workflow) => workflow.map((context) => ({
474
+ ...context,
475
+ success: false,
476
+ error: "Invalid data"
477
+ }))
478
+ )
479
+ ```
480
+
481
+ ### Parallel Processing
482
+ ```typescript
483
+ .parallel([
484
+ fetchUserProfile,
485
+ fetchUserPreferences,
486
+ fetchUserActivity
487
+ ])
488
+ .map((context) => ({
489
+ ...context,
490
+ hasCompleteData: context.profile && context.preferences && context.activity
491
+ }))
492
+ ```
493
+
494
+ ### Conditional Processing
495
+ ```typescript
496
+ .branch(
497
+ (context) => context.dataType === "users",
498
+ (workflow) => workflow.then(processUsers),
499
+ (workflow) => workflow.then(processProducts)
500
+ )
501
+ ```
502
+
503
+ ## 🚨 Anti-Patterns to Avoid
504
+
505
+ ### ❌ Multiple Tool Calls in One Step
506
+ ```typescript
507
+ // DON'T DO THIS
508
+ execute: async ({ context }) => {
509
+ const data1 = await env.API1.TOOL1({...});
510
+ const data2 = await env.API2.TOOL2({...});
511
+ const data3 = await env.API3.TOOL3({...});
512
+ return { result: "combined" };
513
+ }
514
+ ```
515
+
516
+ ### ❌ Complex Logic in Tools
517
+ ```typescript
518
+ // DON'T DO THIS
519
+ execute: async ({ context }) => {
520
+ const data = await env.API.TOOL({...});
521
+
522
+ // Complex processing logic here
523
+ const processed = data.map(item => ({
524
+ ...item,
525
+ calculated: item.value * 2,
526
+ formatted: item.name.toUpperCase(),
527
+ validated: item.id > 0
528
+ })).filter(item => item.validated);
529
+
530
+ return { result: processed };
531
+ }
532
+ ```
533
+
534
+ ### ✅ Do This Instead
535
+ ```typescript
536
+ // Step 1: Fetch data
537
+ const fetchData = createStepFromTool(createFetchTool(env));
538
+
539
+ // Step 2: Process data (in workflow)
540
+ .then(fetchData)
541
+ .map((context) => ({
542
+ ...context,
543
+ processed: context.data.map(item => ({
544
+ ...item,
545
+ calculated: item.value * 2,
546
+ formatted: item.name.toUpperCase(),
547
+ validated: item.id > 0
548
+ })).filter(item => item.validated)
549
+ }))
550
+ ```
551
+
552
+ ## 📚 Practical Examples
553
+
554
+ ### Example 1: User Data Processing Pipeline
555
+
556
+ #### ❌ Bad Approach (Don't Do This)
557
+ ```typescript
558
+ // DON'T: Combining multiple tool calls in one step
559
+ const createBadUserProcessor = (env: Env) =>
560
+ createTool({
561
+ id: "BAD_USER_PROCESSOR",
562
+ description: "Process user data - BAD EXAMPLE",
563
+ inputSchema: z.object({ userId: z.string() }),
564
+ outputSchema: z.object({ result: z.string() }),
565
+ execute: async ({ context }) => {
566
+ // Multiple tool calls in one step - AVOID THIS
567
+ const userData = await env.DECO_CHAT_WORKSPACE_API.DATABASES_RUN_SQL({
568
+ sql: "SELECT * FROM users WHERE id = ?",
569
+ params: [context.userId]
570
+ });
571
+
572
+ const aiAnalysis = await env.GIMENES.AGENT_GENERATE_TEXT({
573
+ message: `Analyze user data: ${JSON.stringify(userData)}`
574
+ });
575
+
576
+ const savedResult = await env.DECO_CHAT_WORKSPACE_API.FS_WRITE({
577
+ path: `/users/${context.userId}/analysis.json`,
578
+ content: aiAnalysis.text,
579
+ contentType: "application/json"
580
+ });
581
+
582
+ return { result: "processed" };
583
+ },
584
+ });
585
+ ```
586
+
587
+ #### ✅ Good Approach (Do This)
588
+ ```typescript
589
+ // DO: Split into separate steps, use control flow for processing
590
+ const createUserDataWorkflow = (env: Env) => {
591
+ // Step 1: Fetch user data (ONE tool call)
592
+ const fetchUserData = createStepFromTool(
593
+ createTool({
594
+ id: "FETCH_USER_DATA",
595
+ description: "Fetch user data from database",
596
+ inputSchema: z.object({ userId: z.string() }),
597
+ outputSchema: z.object({ userData: z.any() }),
598
+ execute: async ({ context }) => {
599
+ const result = await env.DECO_CHAT_WORKSPACE_API.DATABASES_RUN_SQL({
600
+ sql: "SELECT * FROM users WHERE id = ?",
601
+ params: [context.userId]
602
+ });
603
+ return { userData: result };
604
+ },
605
+ })(env)
606
+ );
607
+
608
+ // Step 2: Analyze with AI (ONE tool call)
609
+ const analyzeUserData = createStepFromTool(
610
+ createTool({
611
+ id: "ANALYZE_USER_DATA",
612
+ description: "Analyze user data with AI",
613
+ inputSchema: z.object({ userData: z.any() }),
614
+ outputSchema: z.object({ analysis: z.string() }),
615
+ execute: async ({ context }) => {
616
+ const result = await env.GIMENES.AGENT_GENERATE_TEXT({
617
+ message: `Analyze this user data: ${JSON.stringify(context.userData)}`
618
+ });
619
+ return { analysis: result.text || "" };
620
+ },
621
+ })(env)
622
+ );
623
+
624
+ // Step 3: Save results (ONE tool call)
625
+ const saveAnalysis = createStepFromTool(
626
+ createTool({
627
+ id: "SAVE_ANALYSIS",
628
+ description: "Save analysis to file system",
629
+ inputSchema: z.object({
630
+ userId: z.string(),
631
+ analysis: z.string()
632
+ }),
633
+ outputSchema: z.object({ saved: z.boolean() }),
634
+ execute: async ({ context }) => {
635
+ await env.DECO_CHAT_WORKSPACE_API.FS_WRITE({
636
+ path: `/users/${context.userId}/analysis.json`,
637
+ content: context.analysis,
638
+ contentType: "application/json"
639
+ });
640
+ return { saved: true };
641
+ },
642
+ })(env)
643
+ );
644
+
645
+ return createWorkflow({
646
+ id: "USER_DATA_WORKFLOW",
647
+ inputSchema: z.object({ userId: z.string() }),
648
+ outputSchema: z.object({
649
+ success: z.boolean(),
650
+ analysis: z.string(),
651
+ saved: z.boolean()
652
+ }),
653
+ })
654
+ .then(fetchUserData)
655
+ .map((context) => ({
656
+ ...context,
657
+ // Data processing logic here (not in tools)
658
+ processedUserData: context.userData.results?.[0] || null,
659
+ hasValidData: context.userData.results?.length > 0
660
+ }))
661
+ .branch(
662
+ (context) => context.hasValidData,
663
+ (workflow) => workflow
664
+ .then(analyzeUserData)
665
+ .map((context) => ({
666
+ ...context,
667
+ // More data processing
668
+ analysisLength: context.analysis.length,
669
+ isLongAnalysis: context.analysis.length > 500
670
+ }))
671
+ .then(saveAnalysis)
672
+ .map((context) => ({
673
+ ...context,
674
+ success: true
675
+ })),
676
+ (workflow) => workflow
677
+ .map((context) => ({
678
+ ...context,
679
+ success: false,
680
+ analysis: "No user data found",
681
+ saved: false
682
+ }))
683
+ )
684
+ .commit();
685
+ };
686
+ ```
687
+
688
+ ### Example 2: Multi-Service Integration
689
+ ```typescript
690
+ const createMultiServiceWorkflow = (env: Env) => {
691
+ // Step 1: Fetch data from external API
692
+ const fetchExternalData = createStepFromTool(
693
+ createTool({
694
+ id: "FETCH_EXTERNAL_DATA",
695
+ description: "Fetch data from external service",
696
+ inputSchema: z.object({ query: z.string() }),
697
+ outputSchema: z.object({ externalData: z.any() }),
698
+ execute: async ({ context }) => {
699
+ const result = await env.EXTERNAL_API.GET_DATA({
700
+ query: context.query
701
+ });
702
+ return { externalData: result };
703
+ },
704
+ })(env)
705
+ );
706
+
707
+ // Step 2: Process with AI
708
+ const processWithAI = createStepFromTool(
709
+ createTool({
710
+ id: "PROCESS_WITH_AI",
711
+ description: "Process data with AI",
712
+ inputSchema: z.object({ data: z.any() }),
713
+ outputSchema: z.object({ processedData: z.string() }),
714
+ execute: async ({ context }) => {
715
+ const result = await env.GIMENES.AGENT_GENERATE_TEXT({
716
+ message: `Process this data: ${JSON.stringify(context.data)}`
717
+ });
718
+ return { processedData: result.text || "" };
719
+ },
720
+ })(env)
721
+ );
722
+
723
+ return createWorkflow({
724
+ id: "MULTI_SERVICE_WORKFLOW",
725
+ inputSchema: z.object({
726
+ query: z.string(),
727
+ userId: z.string()
728
+ }),
729
+ outputSchema: z.object({
730
+ success: z.boolean(),
731
+ processedData: z.string()
732
+ }),
733
+ })
734
+ .then(fetchExternalData)
735
+ .map((context) => ({
736
+ ...context,
737
+ // Data validation and processing
738
+ isValidData: context.externalData && context.externalData.length > 0,
739
+ dataCount: context.externalData?.length || 0
740
+ }))
741
+ .branch(
742
+ (context) => context.isValidData,
743
+ (workflow) => workflow
744
+ .then(processWithAI)
745
+ .map((context) => ({
746
+ ...context,
747
+ success: true
748
+ })),
749
+ (workflow) => workflow
750
+ .map((context) => ({
751
+ ...context,
752
+ success: false,
753
+ processedData: "No valid data found"
754
+ }))
755
+ )
756
+ .commit();
757
+ };
758
+ ```
759
+
760
+ ### Example 3: Parallel Processing
761
+ ```typescript
762
+ const createParallelProcessingWorkflow = (env: Env) => {
763
+ // Step 1: Fetch user profile
764
+ const fetchUserProfile = createStepFromTool(
765
+ createTool({
766
+ id: "FETCH_USER_PROFILE",
767
+ description: "Fetch user profile data",
768
+ inputSchema: z.object({ userId: z.string() }),
769
+ outputSchema: z.object({ profile: z.any() }),
770
+ execute: async ({ context }) => {
771
+ const result = await env.DECO_CHAT_WORKSPACE_API.DATABASES_RUN_SQL({
772
+ sql: "SELECT * FROM user_profiles WHERE user_id = ?",
773
+ params: [context.userId]
774
+ });
775
+ return { profile: result.results?.[0] };
776
+ },
777
+ })(env)
778
+ );
779
+
780
+ // Step 2: Fetch user preferences
781
+ const fetchUserPreferences = createStepFromTool(
782
+ createTool({
783
+ id: "FETCH_USER_PREFERENCES",
784
+ description: "Fetch user preferences",
785
+ inputSchema: z.object({ userId: z.string() }),
786
+ outputSchema: z.object({ preferences: z.any() }),
787
+ execute: async ({ context }) => {
788
+ const result = await env.DECO_CHAT_WORKSPACE_API.DATABASES_RUN_SQL({
789
+ sql: "SELECT * FROM user_preferences WHERE user_id = ?",
790
+ params: [context.userId]
791
+ });
792
+ return { preferences: result.results?.[0] };
793
+ },
794
+ })(env)
795
+ );
796
+
797
+ return createWorkflow({
798
+ id: "PARALLEL_PROCESSING_WORKFLOW",
799
+ inputSchema: z.object({ userId: z.string() }),
800
+ outputSchema: z.object({
801
+ success: z.boolean(),
802
+ dataSummary: z.any()
803
+ }),
804
+ })
805
+ .parallel([
806
+ fetchUserProfile,
807
+ fetchUserPreferences
808
+ ])
809
+ .map((context) => ({
810
+ ...context,
811
+ // Combine and validate parallel results
812
+ hasCompleteData: context.profile && context.preferences,
813
+ dataSummary: {
814
+ profileComplete: !!context.profile,
815
+ preferencesComplete: !!context.preferences
816
+ }
817
+ }))
818
+ .branch(
819
+ (context) => context.hasCompleteData,
820
+ (workflow) => workflow
821
+ .map((context) => ({
822
+ ...context,
823
+ success: true
824
+ })),
825
+ (workflow) => workflow
826
+ .map((context) => ({
827
+ ...context,
828
+ success: false
829
+ }))
830
+ )
831
+ .commit();
832
+ };
833
+ ```
834
+
835
+ ## 🔍 Debugging and Testing
836
+
837
+ ### Local Development
838
+ ```bash
839
+ # Start with debugging
840
+ deco dev --debug
841
+
842
+ # Check logs
843
+ deco logs
844
+
845
+ # Test specific workflow
846
+ deco test workflow-name
847
+ ```
848
+
849
+ ### Common Issues
850
+ 1. **Type Errors**: Check your Zod schemas and TypeScript types
851
+ 2. **Integration Errors**: Verify integration configuration and credentials
852
+ 3. **Workflow Errors**: Check step dependencies and data flow
853
+ 4. **Deployment Errors**: Verify wrangler.toml configuration
854
+
855
+ ## 📚 Best Practices Summary
856
+
857
+ ### 1. Workflow Design
858
+ - **Keep steps atomic**: Each step should do one thing
859
+ - **Use control flow for logic**: Leverage `.map`, `.branch`, `.parallel`
860
+ - **Separate concerns**: I/O operations vs data processing
861
+ - **Handle errors gracefully**: Use try-catch and proper error schemas
862
+
863
+ ### 2. Tool Design
864
+ - **Validate inputs**: Always use Zod schemas
865
+ - **Provide clear descriptions**: Help users understand what your tool does
866
+ - **Return consistent outputs**: Use predictable data structures
867
+ - **Handle edge cases**: Consider what happens when things go wrong
868
+
869
+ ### 3. Integration Usage
870
+ - **Check documentation**: Each integration has specific parameters
871
+ - **Use TypeScript**: Leverage the generated types for type safety
872
+ - **Handle rate limits**: Be mindful of API limitations
873
+ - **Cache when appropriate**: Avoid unnecessary repeated calls
874
+
875
+ ### 4. Performance
876
+ - **Parallelize when possible**: Use `.parallel` for independent operations
877
+ - **Batch operations**: Group related operations together
878
+ - **Optimize data flow**: Minimize data transformation overhead
879
+
880
+ ## 📖 Additional Resources
881
+
882
+ - **Mastra Workflows**: https://mastra.ai/en/docs/workflows/control-flow
883
+ - **Data Mapping**: https://mastra.ai/en/docs/workflows/input-data-mapping
884
+ - **deco.chat Documentation**: Platform-specific guides and examples
885
+ - **TypeScript Documentation**: For advanced type usage
886
+ - **Zod Documentation**: For schema validation patterns
887
+
888
+ ## 🎯 Key Takeaways
889
+
890
+ Remember the core principle: **Each workflow step should invoke only ONE tool, and all other processing should use Mastra's control flow operators**. This approach ensures:
891
+
892
+ - **Maintainability**: Clear separation of concerns
893
+ - **Testability**: Each step can be tested independently
894
+ - **Scalability**: Easy to modify and extend workflows
895
+ - **Performance**: Optimal execution patterns
896
+
897
+ Start simple, build incrementally, and leverage the power of deco.chat's integration ecosystem to create powerful automation workflows!
898
+
899
+ - **Scalability**: Easy to modify and extend workflows
900
+ - **Performance**: Optimal execution patterns
901
+
902
+ Start simple, build incrementally, and leverage the power of deco.chat's integration ecosystem to create powerful automation workflows!