@n8n/instance-ai 1.3.5 → 1.5.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 (195) hide show
  1. package/dist/agent/credential-guardrails.prompt.d.ts +1 -0
  2. package/dist/agent/credential-guardrails.prompt.js +5 -0
  3. package/dist/agent/credential-guardrails.prompt.js.map +1 -0
  4. package/dist/agent/instance-agent.js +0 -1
  5. package/dist/agent/instance-agent.js.map +1 -1
  6. package/dist/agent/shared-prompts.d.ts +4 -0
  7. package/dist/agent/shared-prompts.js +17 -0
  8. package/dist/agent/shared-prompts.js.map +1 -0
  9. package/dist/agent/sub-agent-debriefing.d.ts +2 -2
  10. package/dist/agent/sub-agent-factory.d.ts +1 -1
  11. package/dist/agent/sub-agent-factory.js +7 -7
  12. package/dist/agent/sub-agent-factory.js.map +1 -1
  13. package/dist/agent/system-prompt.js +56 -29
  14. package/dist/agent/system-prompt.js.map +1 -1
  15. package/dist/build.tsbuildinfo +1 -1
  16. package/dist/constants/max-steps.d.ts +1 -1
  17. package/dist/constants/max-steps.js +1 -1
  18. package/dist/constants/max-steps.js.map +1 -1
  19. package/dist/constants/model-settings.d.ts +3 -0
  20. package/dist/constants/model-settings.js +7 -0
  21. package/dist/constants/model-settings.js.map +1 -0
  22. package/dist/index.d.ts +9 -3
  23. package/dist/index.js +10 -2
  24. package/dist/index.js.map +1 -1
  25. package/dist/logger.d.ts +6 -0
  26. package/dist/planned-tasks/planned-task-permissions.d.ts +2 -0
  27. package/dist/planned-tasks/planned-task-permissions.js +8 -2
  28. package/dist/planned-tasks/planned-task-permissions.js.map +1 -1
  29. package/dist/planned-tasks/planned-task-service.d.ts +14 -1
  30. package/dist/planned-tasks/planned-task-service.js +138 -2
  31. package/dist/planned-tasks/planned-task-service.js.map +1 -1
  32. package/dist/runtime/background-task-manager.d.ts +25 -1
  33. package/dist/runtime/background-task-manager.js +66 -2
  34. package/dist/runtime/background-task-manager.js.map +1 -1
  35. package/dist/runtime/builder-sandbox-session-registry.d.ts +45 -0
  36. package/dist/runtime/builder-sandbox-session-registry.js +159 -0
  37. package/dist/runtime/builder-sandbox-session-registry.js.map +1 -0
  38. package/dist/runtime/run-state-registry.d.ts +7 -4
  39. package/dist/runtime/run-state-registry.js +9 -0
  40. package/dist/runtime/run-state-registry.js.map +1 -1
  41. package/dist/storage/agent-tree-snapshot.d.ts +2 -0
  42. package/dist/storage/planned-task-storage.js +2 -1
  43. package/dist/storage/planned-task-storage.js.map +1 -1
  44. package/dist/storage/workflow-loop-storage.d.ts +292 -12
  45. package/dist/stream/consume-with-hitl.d.ts +1 -0
  46. package/dist/stream/consume-with-hitl.js +1 -0
  47. package/dist/stream/consume-with-hitl.js.map +1 -1
  48. package/dist/tools/credentials.tool.js +20 -3
  49. package/dist/tools/credentials.tool.js.map +1 -1
  50. package/dist/tools/data-tables.tool.js +60 -22
  51. package/dist/tools/data-tables.tool.js.map +1 -1
  52. package/dist/tools/executions.tool.js +4 -1
  53. package/dist/tools/executions.tool.js.map +1 -1
  54. package/dist/tools/index.d.ts +1 -2
  55. package/dist/tools/index.js +2 -3
  56. package/dist/tools/index.js.map +1 -1
  57. package/dist/tools/nodes/suggested-nodes-data.js +1 -1
  58. package/dist/tools/nodes/suggested-nodes-data.js.map +1 -1
  59. package/dist/tools/nodes.tool.js +25 -13
  60. package/dist/tools/nodes.tool.js.map +1 -1
  61. package/dist/tools/orchestration/add-plan-item.tool.js +3 -1
  62. package/dist/tools/orchestration/add-plan-item.tool.js.map +1 -1
  63. package/dist/tools/orchestration/blueprint-accumulator.d.ts +4 -1
  64. package/dist/tools/orchestration/blueprint-accumulator.js +28 -0
  65. package/dist/tools/orchestration/blueprint-accumulator.js.map +1 -1
  66. package/dist/tools/orchestration/blueprint.schema.d.ts +60 -15
  67. package/dist/tools/orchestration/blueprint.schema.js +15 -1
  68. package/dist/tools/orchestration/blueprint.schema.js.map +1 -1
  69. package/dist/tools/orchestration/browser-credential-setup.prompt.d.ts +13 -0
  70. package/dist/tools/orchestration/browser-credential-setup.prompt.js +140 -0
  71. package/dist/tools/orchestration/browser-credential-setup.prompt.js.map +1 -0
  72. package/dist/tools/orchestration/browser-credential-setup.tool.d.ts +1 -0
  73. package/dist/tools/orchestration/browser-credential-setup.tool.js +8 -139
  74. package/dist/tools/orchestration/browser-credential-setup.tool.js.map +1 -1
  75. package/dist/tools/orchestration/build-workflow-agent.prompt.js +137 -239
  76. package/dist/tools/orchestration/build-workflow-agent.prompt.js.map +1 -1
  77. package/dist/tools/orchestration/build-workflow-agent.tool.d.ts +51 -3
  78. package/dist/tools/orchestration/build-workflow-agent.tool.js +842 -269
  79. package/dist/tools/orchestration/build-workflow-agent.tool.js.map +1 -1
  80. package/dist/tools/orchestration/builder-memory-compaction.d.ts +38 -0
  81. package/dist/tools/orchestration/builder-memory-compaction.js +146 -0
  82. package/dist/tools/orchestration/builder-memory-compaction.js.map +1 -0
  83. package/dist/tools/orchestration/complete-checkpoint.tool.d.ts +2 -0
  84. package/dist/tools/orchestration/complete-checkpoint.tool.js +76 -0
  85. package/dist/tools/orchestration/complete-checkpoint.tool.js.map +1 -0
  86. package/dist/tools/orchestration/data-table-agent.prompt.d.ts +1 -1
  87. package/dist/tools/orchestration/data-table-agent.prompt.js +4 -6
  88. package/dist/tools/orchestration/data-table-agent.prompt.js.map +1 -1
  89. package/dist/tools/orchestration/data-table-agent.tool.js +34 -18
  90. package/dist/tools/orchestration/data-table-agent.tool.js.map +1 -1
  91. package/dist/tools/orchestration/delegate.tool.js +33 -17
  92. package/dist/tools/orchestration/delegate.tool.js.map +1 -1
  93. package/dist/tools/orchestration/plan-agent-prompt.d.ts +1 -1
  94. package/dist/tools/orchestration/plan-agent-prompt.js +17 -17
  95. package/dist/tools/orchestration/plan-agent-prompt.js.map +1 -1
  96. package/dist/tools/orchestration/plan-with-agent.tool.d.ts +8 -0
  97. package/dist/tools/orchestration/plan-with-agent.tool.js +43 -12
  98. package/dist/tools/orchestration/plan-with-agent.tool.js.map +1 -1
  99. package/dist/tools/orchestration/plan.tool.js +82 -2
  100. package/dist/tools/orchestration/plan.tool.js.map +1 -1
  101. package/dist/tools/orchestration/report-verification-verdict.tool.d.ts +40 -2
  102. package/dist/tools/orchestration/report-verification-verdict.tool.js +89 -7
  103. package/dist/tools/orchestration/report-verification-verdict.tool.js.map +1 -1
  104. package/dist/tools/orchestration/research-agent-prompt.d.ts +1 -1
  105. package/dist/tools/orchestration/research-agent-prompt.js +2 -4
  106. package/dist/tools/orchestration/research-agent-prompt.js.map +1 -1
  107. package/dist/tools/orchestration/research-with-agent.tool.js +33 -17
  108. package/dist/tools/orchestration/research-with-agent.tool.js.map +1 -1
  109. package/dist/tools/orchestration/verify-built-workflow.tool.d.ts +8 -2
  110. package/dist/tools/orchestration/verify-built-workflow.tool.js +476 -6
  111. package/dist/tools/orchestration/verify-built-workflow.tool.js.map +1 -1
  112. package/dist/tools/research.tool.js +2 -2
  113. package/dist/tools/research.tool.js.map +1 -1
  114. package/dist/tools/shared/ask-user.tool.js +2 -1
  115. package/dist/tools/shared/ask-user.tool.js.map +1 -1
  116. package/dist/tools/templates.tool.js +5 -90
  117. package/dist/tools/templates.tool.js.map +1 -1
  118. package/dist/tools/web-research/sanitize-web-content.d.ts +0 -1
  119. package/dist/tools/web-research/sanitize-web-content.js +0 -9
  120. package/dist/tools/web-research/sanitize-web-content.js.map +1 -1
  121. package/dist/tools/workflows/apply-workflow-credentials.tool.d.ts +2 -2
  122. package/dist/tools/workflows/build-workflow.tool.d.ts +8 -8
  123. package/dist/tools/workflows/build-workflow.tool.js +14 -2
  124. package/dist/tools/workflows/build-workflow.tool.js.map +1 -1
  125. package/dist/tools/workflows/materialize-node-type.tool.d.ts +8 -8
  126. package/dist/tools/workflows/resolve-credentials.js +6 -6
  127. package/dist/tools/workflows/resolve-credentials.js.map +1 -1
  128. package/dist/tools/workflows/setup-workflow.service.js +3 -2
  129. package/dist/tools/workflows/setup-workflow.service.js.map +1 -1
  130. package/dist/tools/workflows/submit-workflow-identity.d.ts +35 -0
  131. package/dist/tools/workflows/submit-workflow-identity.js +154 -0
  132. package/dist/tools/workflows/submit-workflow-identity.js.map +1 -0
  133. package/dist/tools/workflows/submit-workflow.tool.d.ts +82 -3
  134. package/dist/tools/workflows/submit-workflow.tool.js +114 -35
  135. package/dist/tools/workflows/submit-workflow.tool.js.map +1 -1
  136. package/dist/tracing/langsmith-tracing.d.ts +12 -0
  137. package/dist/tracing/langsmith-tracing.js +35 -3
  138. package/dist/tracing/langsmith-tracing.js.map +1 -1
  139. package/dist/tracing/trace-replay.d.ts +3 -0
  140. package/dist/tracing/trace-replay.js +65 -0
  141. package/dist/tracing/trace-replay.js.map +1 -1
  142. package/dist/types.d.ts +82 -12
  143. package/dist/utils/eval-agents.js +4 -2
  144. package/dist/utils/eval-agents.js.map +1 -1
  145. package/dist/workflow-builder/parse-validate.d.ts +5 -1
  146. package/dist/workflow-builder/parse-validate.js +4 -3
  147. package/dist/workflow-builder/parse-validate.js.map +1 -1
  148. package/dist/workflow-loop/guidance.js +15 -5
  149. package/dist/workflow-loop/guidance.js.map +1 -1
  150. package/dist/workflow-loop/index.d.ts +3 -2
  151. package/dist/workflow-loop/index.js +9 -1
  152. package/dist/workflow-loop/index.js.map +1 -1
  153. package/dist/workflow-loop/remediation.d.ts +13 -0
  154. package/dist/workflow-loop/remediation.js +36 -0
  155. package/dist/workflow-loop/remediation.js.map +1 -0
  156. package/dist/workflow-loop/runtime.js +7 -0
  157. package/dist/workflow-loop/runtime.js.map +1 -1
  158. package/dist/workflow-loop/workflow-loop-controller.d.ts +1 -1
  159. package/dist/workflow-loop/workflow-loop-controller.js +196 -29
  160. package/dist/workflow-loop/workflow-loop-controller.js.map +1 -1
  161. package/dist/workflow-loop/workflow-loop-state.d.ts +338 -8
  162. package/dist/workflow-loop/workflow-loop-state.js +44 -1
  163. package/dist/workflow-loop/workflow-loop-state.js.map +1 -1
  164. package/dist/workflow-loop/workflow-task-service.d.ts +2 -1
  165. package/dist/workflow-loop/workflow-task-service.js +4 -0
  166. package/dist/workflow-loop/workflow-task-service.js.map +1 -1
  167. package/dist/workspace/builder-sandbox-factory.d.ts +6 -1
  168. package/dist/workspace/builder-sandbox-factory.js +115 -26
  169. package/dist/workspace/builder-sandbox-factory.js.map +1 -1
  170. package/dist/workspace/create-workspace.d.ts +2 -0
  171. package/dist/workspace/create-workspace.js.map +1 -1
  172. package/dist/workspace/pack-workspace-sdk.d.ts +9 -0
  173. package/dist/workspace/pack-workspace-sdk.js +80 -0
  174. package/dist/workspace/pack-workspace-sdk.js.map +1 -0
  175. package/dist/workspace/sandbox-fs.d.ts +1 -1
  176. package/dist/workspace/sandbox-fs.js +3 -1
  177. package/dist/workspace/sandbox-fs.js.map +1 -1
  178. package/dist/workspace/sandbox-setup.js +83 -19
  179. package/dist/workspace/sandbox-setup.js.map +1 -1
  180. package/dist/workspace/snapshot-manager.d.ts +14 -2
  181. package/dist/workspace/snapshot-manager.js +57 -1
  182. package/dist/workspace/snapshot-manager.js.map +1 -1
  183. package/package.json +15 -8
  184. package/dist/tools/templates/template-api.d.ts +0 -21
  185. package/dist/tools/templates/template-api.js +0 -104
  186. package/dist/tools/templates/template-api.js.map +0 -1
  187. package/dist/tools/templates/types.d.ts +0 -52
  188. package/dist/tools/templates/types.js +0 -37
  189. package/dist/tools/templates/types.js.map +0 -1
  190. package/dist/tools/utils/mermaid.utils.d.ts +0 -15
  191. package/dist/tools/utils/mermaid.utils.js +0 -622
  192. package/dist/tools/utils/mermaid.utils.js.map +0 -1
  193. package/dist/tools/utils/node-configuration.utils.d.ts +0 -6
  194. package/dist/tools/utils/node-configuration.utils.js +0 -77
  195. package/dist/tools/utils/node-configuration.utils.js.map +0 -1
@@ -5,20 +5,40 @@ exports.createSandboxBuilderAgentPrompt = createSandboxBuilderAgentPrompt;
5
5
  const parameter_guides_1 = require("@n8n/workflow-sdk/prompts/node-guidance/parameter-guides");
6
6
  const node_selection_1 = require("@n8n/workflow-sdk/prompts/node-selection");
7
7
  const sdk_reference_1 = require("@n8n/workflow-sdk/prompts/sdk-reference");
8
- const PLACEHOLDER_RULE = '**Do NOT use `placeholder()` for discoverable resources** (spreadsheet IDs, calendar IDs, channel IDs, folder IDs) — resolve real IDs via `nodes(action="explore-resources")` or create them via setup workflows. For **user-provided values** that cannot be discovered or created (email recipients, phone numbers, custom URLs, notification targets), use `placeholder(\'descriptive hint\')` so the setup wizard prompts the user after the build. Never hardcode fake values like `user@example.com`.';
9
- const PLACEHOLDER_ESCALATION = 'When the user says "send me", "email me", "notify me", or similar and you don\'t know their specific address, use `placeholder(\'Your email address\')` for the recipient field rather than hardcoding a fake address like `user@example.com`. The setup wizard will collect this from the user after the build.';
8
+ const shared_prompts_1 = require("../../agent/shared-prompts");
9
+ const BUILDER_OUTPUT_DISCIPLINE = `## Output Discipline
10
+ - Your text output is visible to the user. Be concise and natural.
11
+ - Only output text for: errors that need attention, or a brief natural completion message.
12
+ - No emojis, no filler phrases, no markdown headers in your text output.
13
+ - When conversation context is provided, use it to continue naturally — do not repeat information the user already knows.
14
+
15
+ ### No narration (critical)
16
+ Do NOT announce what you're about to do. The user already sees your tool calls in real time via the agent card; narrating them is pure noise. Stay silent while working; speak only on completion or when blocked.
17
+
18
+ BAD (do not write anything like this):
19
+ - "I'll build this family AI assistant for Telegram. Let me start by discovering credentials and resources..."
20
+ - "I'll start by reading the current workflow code and looking up the correct Linear node type definition."
21
+ - "I don't see any pinData — let me check if there's something embedded in the workflow..."
22
+ - "Let me look up the Slack channel IDs now."
23
+
24
+ GOOD (one-line, only on completion or block):
25
+ - "Family AI assistant workflow ready — uses Telegram, OpenAI, and your shopping list data table."
26
+ - "Workflow updated: removed the stale pinData from the weather check node."
27
+ - "Blocked: the Linear API credential is missing and the setup wizard is needed before I can continue."`;
10
28
  const SDK_CODE_RULES = `## SDK Code Rules
11
29
 
12
30
  - Do NOT specify node positions — they are auto-calculated by the layout engine.
13
31
  - For credentials, see the credential rules in your specific workflow process section below.
14
- - ${PLACEHOLDER_RULE}
32
+ - For placeholders, see the ## Placeholders section.
15
33
  - Use \`expr('{{ $json.field }}')\` for n8n expressions. Variables MUST be inside \`{{ }}\`.
16
34
  - Do NOT use \`as const\` assertions — the workflow parser only supports JavaScript syntax, not TypeScript-only features. Just use plain string literals.
17
35
  - Use string values directly for discriminator fields like \`resource\` and \`operation\` (e.g., \`resource: 'message'\` not \`resource: 'message' as const\`).
18
36
  - When editing a pre-loaded workflow, **remove \`position\` arrays** from node configs — they are auto-calculated.
19
37
  - **No em-dash (\`—\`) or other special Unicode characters in node names or string values.** Use plain hyphen (\`-\`) instead. The SDK parser cannot handle em-dashes.
20
38
  - **IF node combinator** must be \`'and'\` or \`'or'\` (not \`'any'\` or \`'all'\`).`;
21
- const BUILDER_SPECIFIC_PATTERNS = `## Critical Patterns (Common Mistakes)
39
+ function buildBuilderSpecificPatterns(mode) {
40
+ const openAiCredExample = mode === 'sandbox' ? "{ id: 'credId', name: 'OpenAI account' }" : "newCredential('OpenAI')";
41
+ return `## Critical Patterns (Common Mistakes)
22
42
 
23
43
  **Pay attention to @builderHint annotations in search results and type definitions** — these provide critical guidance on how to correctly configure node parameters. Write them out as notes when reviewing — they prevent common configuration mistakes.
24
44
 
@@ -33,13 +53,23 @@ After writing any workflow with IF, Switch, or Filter nodes, verify:
33
53
 
34
54
  ### AI Agent with Subnodes — use factory functions in subnodes config
35
55
  \`\`\`javascript
56
+ const chatTrigger = trigger({
57
+ type: '@n8n/n8n-nodes-langchain.chatTrigger',
58
+ version: 1.3,
59
+ config: {
60
+ name: 'Chat Trigger',
61
+ parameters: { public: false },
62
+ output: [{ sessionId: 'chat-session-id', chatInput: 'Hello' }]
63
+ }
64
+ });
65
+
36
66
  const model = languageModel({
37
67
  type: '@n8n/n8n-nodes-langchain.lmChatOpenAi',
38
68
  version: 1.3,
39
69
  config: {
40
70
  name: 'OpenAI Chat Model',
41
- parameters: { model: { __rl: true, mode: 'list', value: 'gpt-4o-mini' } },
42
- credentials: { openAiApi: newCredential('OpenAI') }
71
+ parameters: { model: { __rl: true, mode: 'list', value: 'gpt-5.4' } },
72
+ credentials: { openAiApi: ${openAiCredExample} }
43
73
  }
44
74
  });
45
75
 
@@ -55,6 +85,19 @@ const parser = outputParser({
55
85
  }
56
86
  });
57
87
 
88
+ const memoryNode = memory({
89
+ type: '@n8n/n8n-nodes-langchain.memoryBufferWindow',
90
+ version: 1.3,
91
+ config: {
92
+ name: 'Conversation Memory',
93
+ parameters: {
94
+ sessionIdType: 'customKey',
95
+ sessionKey: nodeJson(chatTrigger, 'sessionId'),
96
+ contextWindowLength: 10
97
+ }
98
+ }
99
+ });
100
+
58
101
  const agent = node({
59
102
  type: '@n8n/n8n-nodes-langchain.agent',
60
103
  version: 3.1,
@@ -66,11 +109,12 @@ const agent = node({
66
109
  hasOutputParser: true,
67
110
  options: { systemMessage: 'You are an expert...' }
68
111
  },
69
- subnodes: { model: model, outputParser: parser }
112
+ subnodes: { model: model, memory: memoryNode, outputParser: parser }
70
113
  }
71
114
  });
72
115
  \`\`\`
73
116
  WRONG: \`.to(agent, { connectionType: 'ai_languageModel' })\` — subnodes MUST be in the config object.
117
+ For values inside AI subnodes, use explicit references such as \`nodeJson(triggerNode, 'sessionId')\` instead of \`$json.sessionId\`. For Chat Trigger memory specifically, \`sessionIdType: 'fromInput'\` is also valid.
74
118
 
75
119
  ### Code Node
76
120
  \`\`\`javascript
@@ -172,192 +216,6 @@ export default workflow('id', 'name')
172
216
  .add(scheduleTrigger).to(processNode);
173
217
  \`\`\`
174
218
 
175
- ### Web App (SPA served from a webhook)
176
-
177
- Serve a single-page application from an n8n webhook. The workflow fetches data, then renders a full HTML page with a client-side framework.
178
-
179
- <web_app_pattern>
180
- **Architecture:** Webhook (responseNode) -> Code node (build HTML) -> Respond with text/html
181
-
182
- **File-based HTML (REQUIRED for pages > ~50 lines):**
183
- Write the HTML to a separate file (e.g., \`chunks/dashboard.html\`), then in the SDK TypeScript code use \`readFileSync\` + \`JSON.stringify\` to safely embed it in a Code node. This eliminates ALL escaping problems:
184
-
185
- 1. Write your full HTML (with CSS, JS, Alpine.js/Tailwind) to \`chunks/page.html\`
186
- 2. In \`src/workflow.ts\`: \`const htmlTemplate = readFileSync(join(__dirname, '../chunks/page.html'), 'utf8');\`
187
- 3. Use \`JSON.stringify(htmlTemplate)\` to create a safe JS string literal for the Code node's jsCode
188
- 4. For data injection, embed a \`__DATA_PLACEHOLDER__\` token in the HTML and replace it at runtime
189
-
190
- **NEVER embed large HTML directly in jsCode** — not as template literals, not as arrays of quoted lines. Both break for real-world pages (20KB+). Always use the file-based pattern.
191
-
192
- **For small static HTML (< 50 lines):** You may inline as an array of quoted strings + \`.join('\\n')\`, but still prefer the file-based approach.
193
-
194
- **Data injection patterns:**
195
- - Static page (no server data): embed HTML directly, no placeholder needed
196
- - Dynamic data: put \`<script id="__data" type="application/json">__DATA_PLACEHOLDER__</script>\` in the HTML. At runtime, the Code node replaces \`__DATA_PLACEHOLDER__\` with base64-encoded JSON. Client-side: \`JSON.parse(atob(document.getElementById('__data').textContent))\`
197
- - Do NOT place bare \`{{ $json... }}\` inside an HTML string parameter
198
-
199
- **Multi-route SPA (dashboard with API endpoints):**
200
- Use multiple webhooks in one workflow — one serves the HTML page, others serve JSON API endpoints. The HTML's JavaScript uses \`fetch()\` to call sibling webhook paths.
201
-
202
- **Default stack:** Alpine.js + Tailwind CSS via CDN. No build step, works in a single HTML file.
203
-
204
- **Respond correctly:** Use respondToWebhook with respondWith: "text", put the HTML in responseBody via expression, and set Content-Type header.
205
- </web_app_pattern>
206
-
207
- #### Example: Multi-route dashboard with DataTable API
208
-
209
- **chunks/dashboard.html** — the full HTML page (write this file first):
210
- \`\`\`html
211
- <!DOCTYPE html>
212
- <html lang="en">
213
- <head>
214
- <meta charset="UTF-8">
215
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
216
- <title>Dashboard</title>
217
- <script src="https://cdn.tailwindcss.com"></script>
218
- <script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3/dist/cdn.min.js"></script>
219
- </head>
220
- <body class="bg-gray-50 min-h-screen p-8">
221
- <h1 class="text-2xl font-bold mb-6">Dashboard</h1>
222
- <div x-data="app()" x-init="loadItems()">
223
- <template x-for="item in items" :key="item.id">
224
- <div class="bg-white rounded-lg shadow p-4 mb-3 flex items-center gap-3">
225
- <input type="checkbox" :checked="item.completed" @change="toggle(item)">
226
- <span x-text="item.title" :class="item.completed && 'line-through text-gray-400'"></span>
227
- </div>
228
- </template>
229
- <form @submit.prevent="addItem()" class="mt-4 flex gap-2">
230
- <input x-model="newTitle" placeholder="New item..." class="border rounded px-3 py-2 flex-1">
231
- <button type="submit" class="bg-blue-600 text-white px-4 py-2 rounded">Add</button>
232
- </form>
233
- </div>
234
- <!-- Server data injected at runtime (base64-encoded JSON) -->
235
- <script id="__data" type="application/json">__DATA_PLACEHOLDER__</script>
236
- <script>
237
- function app() {
238
- return {
239
- items: JSON.parse(atob(document.getElementById('__data').textContent)),
240
- newTitle: '',
241
- async toggle(item) {
242
- await fetch('/webhook/app/items/toggle', {
243
- method: 'POST', headers: {'Content-Type': 'application/json'},
244
- body: JSON.stringify({ id: item.id, completed: !item.completed })
245
- });
246
- item.completed = !item.completed;
247
- },
248
- async addItem() {
249
- if (!this.newTitle.trim()) return;
250
- const res = await fetch('/webhook/app/items/add', {
251
- method: 'POST', headers: {'Content-Type': 'application/json'},
252
- body: JSON.stringify({ title: this.newTitle })
253
- });
254
- const created = await res.json();
255
- this.items.push(created);
256
- this.newTitle = '';
257
- },
258
- loadItems() { /* items already loaded from __data */ }
259
- };
260
- }
261
- </script>
262
- </body>
263
- </html>
264
- \`\`\`
265
-
266
- **src/workflow.ts** — the workflow with 4 webhook routes:
267
- \`\`\`javascript
268
- import { workflow, node, trigger, expr } from '@n8n/workflow-sdk';
269
- import { readFileSync } from 'fs';
270
- import { join } from 'path';
271
-
272
- // Read the HTML template at build time — eliminates all escaping issues
273
- const htmlTemplate = readFileSync(join(__dirname, '../chunks/dashboard.html'), 'utf8');
274
-
275
- // ── Webhooks ──────────────────────────────────────────────
276
- const pageWebhook = trigger({
277
- type: 'n8n-nodes-base.webhook', version: 2.1,
278
- config: { name: 'GET /app', parameters: { httpMethod: 'GET', path: 'app', responseMode: 'responseNode', options: {} } }
279
- });
280
- const getItemsWebhook = trigger({
281
- type: 'n8n-nodes-base.webhook', version: 2.1,
282
- config: { name: 'GET /app/items', parameters: { httpMethod: 'GET', path: 'app/items', responseMode: 'responseNode', options: {} } }
283
- });
284
- const toggleWebhook = trigger({
285
- type: 'n8n-nodes-base.webhook', version: 2.1,
286
- config: { name: 'POST /app/items/toggle', parameters: { httpMethod: 'POST', path: 'app/items/toggle', responseMode: 'responseNode', options: {} } }
287
- });
288
- const addWebhook = trigger({
289
- type: 'n8n-nodes-base.webhook', version: 2.1,
290
- config: { name: 'POST /app/items/add', parameters: { httpMethod: 'POST', path: 'app/items/add', responseMode: 'responseNode', options: {} } }
291
- });
292
-
293
- // ── Route 1: Serve HTML page with pre-loaded data ─────────
294
- const fetchAllItems = node({
295
- type: 'n8n-nodes-base.dataTable', version: 1.1,
296
- config: { name: 'Fetch Items', parameters: { resource: 'row', operation: 'get', dataTableId: { __rl: true, mode: 'name', value: 'items' }, returnAll: true, options: {} } }
297
- });
298
- const aggregateItems = node({
299
- type: 'n8n-nodes-base.aggregate', version: 1,
300
- config: { name: 'Aggregate', parameters: { aggregate: 'aggregateAllItemData', destinationFieldName: 'data', options: {} } }
301
- });
302
- // JSON.stringify in the SDK code creates a safe JS string literal — no escaping issues
303
- const buildPage = node({
304
- type: 'n8n-nodes-base.code', version: 2,
305
- config: {
306
- name: 'Build Page',
307
- parameters: {
308
- mode: 'runOnceForAllItems',
309
- jsCode: 'var data = $input.all()[0].json.data || [];\\n'
310
- + 'var encoded = Buffer.from(JSON.stringify(data)).toString("base64");\\n'
311
- + 'var html = ' + JSON.stringify(htmlTemplate) + '.replace("__DATA_PLACEHOLDER__", encoded);\\n'
312
- + 'return [{ json: { html: html } }];'
313
- }
314
- }
315
- });
316
- const respondHtml = node({
317
- type: 'n8n-nodes-base.respondToWebhook', version: 1.1,
318
- config: { name: 'Respond HTML', parameters: { respondWith: 'text', responseBody: expr('{{ $json.html }}'), options: { responseHeaders: { entries: [{ name: 'Content-Type', value: 'text/html; charset=utf-8' }] } } } }
319
- });
320
-
321
- // ── Route 2: GET items as JSON ────────────────────────────
322
- const fetchItemsJson = node({
323
- type: 'n8n-nodes-base.dataTable', version: 1.1,
324
- config: { name: 'Get Items JSON', parameters: { resource: 'row', operation: 'get', dataTableId: { __rl: true, mode: 'name', value: 'items' }, returnAll: true, options: {} } }
325
- });
326
- const respondItems = node({
327
- type: 'n8n-nodes-base.respondToWebhook', version: 1.1,
328
- config: { name: 'Respond Items', parameters: { respondWith: 'allEntries', options: {} } }
329
- });
330
-
331
- // ── Route 3: Toggle item completion ───────────────────────
332
- const updateItem = node({
333
- type: 'n8n-nodes-base.dataTable', version: 1.1,
334
- config: { name: 'Update Item', parameters: { resource: 'row', operation: 'update', dataTableId: { __rl: true, mode: 'name', value: 'items' }, matchingColumns: ['id'], columns: { mappingMode: 'defineBelow', value: { id: expr('{{ $json.body.id }}'), completed: expr('{{ $json.body.completed }}') }, schema: [{ id: 'id', displayName: 'id', required: false, defaultMatch: true, display: true, type: 'string', canBeUsedToMatch: true }, { id: 'completed', displayName: 'completed', required: false, defaultMatch: false, display: true, type: 'boolean', canBeUsedToMatch: false }] }, options: {} } }
335
- });
336
- const respondToggle = node({
337
- type: 'n8n-nodes-base.respondToWebhook', version: 1.1,
338
- config: { name: 'Respond Toggle', parameters: { respondWith: 'allEntries', options: {} } }
339
- });
340
-
341
- // ── Route 4: Add new item ─────────────────────────────────
342
- const insertItem = node({
343
- type: 'n8n-nodes-base.dataTable', version: 1.1,
344
- config: { name: 'Insert Item', parameters: { resource: 'row', operation: 'insert', dataTableId: { __rl: true, mode: 'name', value: 'items' }, columns: { mappingMode: 'defineBelow', value: { title: expr('{{ $json.body.title }}'), completed: false }, schema: [{ id: 'title', displayName: 'title', required: false, defaultMatch: false, display: true, type: 'string', canBeUsedToMatch: true }, { id: 'completed', displayName: 'completed', required: false, defaultMatch: false, display: true, type: 'boolean', canBeUsedToMatch: false }] }, options: {} } }
345
- });
346
- const respondAdd = node({
347
- type: 'n8n-nodes-base.respondToWebhook', version: 1.1,
348
- config: { name: 'Respond Add', parameters: { respondWith: 'allEntries', options: {} } }
349
- });
350
-
351
- // ── Wire it all together ──────────────────────────────────
352
- export default workflow('id', 'Item Dashboard')
353
- .add(pageWebhook).to(fetchAllItems).to(aggregateItems).to(buildPage).to(respondHtml)
354
- .add(getItemsWebhook).to(fetchItemsJson).to(respondItems)
355
- .add(toggleWebhook).to(updateItem).to(respondToggle)
356
- .add(addWebhook).to(insertItem).to(respondAdd);
357
- \`\`\`
358
-
359
- **Key takeaway:** \`JSON.stringify(htmlTemplate)\` at build time produces a perfectly escaped JS string. The Code node's jsCode is just 4 lines. No escaping problems, no matter how large the HTML.
360
-
361
219
  ### Google Sheets — documentId and sheetName (RLC fields)
362
220
 
363
221
  These are Resource Locator fields that require the \`__rl\` object format:
@@ -385,65 +243,95 @@ ${node_selection_1.CONNECTION_CHANGING_PARAMETERS}
385
243
 
386
244
  ### Baseline Flow Control Nodes
387
245
  ${node_selection_1.BASELINE_FLOW_CONTROL}`;
388
- const SDK_RULES_AND_PATTERNS = [
389
- SDK_CODE_RULES,
390
- sdk_reference_1.WORKFLOW_RULES,
391
- '## SDK Patterns Reference\n\n' + sdk_reference_1.WORKFLOW_SDK_PATTERNS,
392
- '## Expression Reference\n\n' + sdk_reference_1.EXPRESSION_REFERENCE,
393
- '## Additional Functions\n\n' + sdk_reference_1.ADDITIONAL_FUNCTIONS,
394
- '## Node-Specific Configuration Guides',
395
- parameter_guides_1.IF_NODE_GUIDE.content,
396
- parameter_guides_1.SWITCH_NODE_GUIDE.content,
397
- parameter_guides_1.SET_NODE_GUIDE.content,
398
- parameter_guides_1.HTTP_REQUEST_GUIDE.content,
399
- parameter_guides_1.TOOL_NODES_GUIDE.content,
400
- parameter_guides_1.EMBEDDING_NODES_GUIDE.content,
401
- parameter_guides_1.RESOURCE_LOCATOR_GUIDE.content,
402
- BUILDER_SPECIFIC_PATTERNS,
403
- ].join('\n\n');
246
+ }
247
+ const BUILDER_SPECIFIC_PATTERNS_TOOL = buildBuilderSpecificPatterns('tool');
248
+ const BUILDER_SPECIFIC_PATTERNS_SANDBOX = buildBuilderSpecificPatterns('sandbox');
249
+ const SANDBOX_WORKFLOW_RULES = `Follow these rules strictly when generating workflows:
250
+
251
+ 1. **Always use raw credential objects from \`credentials(action="list")\`**
252
+ - Wire credentials as \`{ id, name }\` objects returned by \`credentials(action="list")\`
253
+ - NEVER use placeholder strings, fake API keys, or hardcoded auth values
254
+ - Example: \`credentials: { slackApi: { id: 'yXYBqho73obh58ZS', name: 'Slack Bot' } }\`
255
+ - The key (e.g. \`slackApi\`) is the credential **type** from the node type definition
256
+
257
+ 2. **Trust empty item lists — don't synthesize fake items**
258
+ - When a query returns 0 items, downstream nodes simply don't run for that execution. For scheduled or polling triggers this is the correct "nothing to do this round" signal — the next run will execute normally when data appears.
259
+ - DO NOT add \`alwaysOutputData: true\` just to "keep the chain alive." Forcing an empty \`{}\` item downstream is what causes \`undefined\` reads, failed HTTP calls to \`GET undefined\`, and Code-node crashes on missing fields.
260
+ - DO NOT add an IF gate before a loop to check "has items?" — loops (\`splitInBatches\`, per-item nodes, \`filter\`) already no-op on empty input. The gate is redundant and adds a failure surface.
261
+ - \`alwaysOutputData: true\` is only correct when you specifically need a downstream branch to run on the "empty" case — e.g. a dedicated "no matches found" notification path. In that case, pair it with an \`IF\` that explicitly checks for the empty case and routes accordingly. Never use it as a default.
262
+ - To drop invalid items mid-pipeline, use a \`filter\` node. A \`filter\` that rejects everything emits 0 items and the chain correctly stops — no \`IF\` + \`splitInBatches\` composition needed.
263
+
264
+ 3. **Use \`executeOnce: true\` for single-execution nodes**
265
+ - When a node receives N items but should only execute once (not N times), set \`executeOnce: true\`
266
+ - Common cases: sending a summary notification, generating a report, calling an API that doesn't need per-item execution
267
+ - Example: \`config: { ..., executeOnce: true }\`
268
+
269
+ 4. **Pick the right control-flow primitive**
270
+ - **Per-item loop with side effects (fetch, embed, write)** → \`splitInBatches\` with \`batchSize: 1\` feeding the per-item work, loop back via \`nextBatch\`. No \`IF\` gate before it.
271
+ - **Drop items that don't match a predicate** → \`filter\`. It emits 0 items when nothing matches, and the chain stops cleanly.
272
+ - **Two mutually exclusive paths that both do real work** → \`IF\` (\`onTrue\` / \`onFalse\`).
273
+ - **Many mutually exclusive paths keyed off a value** → \`switch\` (\`onCase\`).
274
+ - Nested control flow is supported: \`ifNode.onTrue(loopBuilder)\`, \`switchNode.onCase(0, loopBuilder)\`, and \`splitInBatches(sib).onEachBatch(ifElseBuilder)\` all compile and wire correctly. Use them when the semantics genuinely call for it, not as a workaround for empty-list handling.`;
275
+ function composeSdkRulesAndPatterns(mode) {
276
+ const sandboxOverride = mode === 'sandbox'
277
+ ? "> **Sandbox credential override**: The SDK pattern examples below use `newCredential('X')`. " +
278
+ "In sandbox mode, replace every `newCredential('X')` with the raw `{ id, name }` object from " +
279
+ '`credentials(action="list")`. `newCredential()` serializes to `undefined` in sandbox and will ' +
280
+ 'silently drop credentials from the saved workflow.'
281
+ : null;
282
+ return [
283
+ SDK_CODE_RULES,
284
+ mode === 'sandbox' ? SANDBOX_WORKFLOW_RULES : sdk_reference_1.WORKFLOW_RULES,
285
+ ...(sandboxOverride ? [sandboxOverride] : []),
286
+ '## SDK Patterns Reference\n\n' + sdk_reference_1.WORKFLOW_SDK_PATTERNS,
287
+ '## Expression Reference\n\n' + sdk_reference_1.EXPRESSION_REFERENCE,
288
+ '## Additional Functions\n\n' + sdk_reference_1.ADDITIONAL_FUNCTIONS,
289
+ '## Node-Specific Configuration Guides',
290
+ parameter_guides_1.IF_NODE_GUIDE.content,
291
+ parameter_guides_1.SWITCH_NODE_GUIDE.content,
292
+ parameter_guides_1.SET_NODE_GUIDE.content,
293
+ parameter_guides_1.HTTP_REQUEST_GUIDE.content,
294
+ parameter_guides_1.TOOL_NODES_GUIDE.content,
295
+ parameter_guides_1.EMBEDDING_NODES_GUIDE.content,
296
+ parameter_guides_1.RESOURCE_LOCATOR_GUIDE.content,
297
+ mode === 'sandbox' ? BUILDER_SPECIFIC_PATTERNS_SANDBOX : BUILDER_SPECIFIC_PATTERNS_TOOL,
298
+ ].join('\n\n');
299
+ }
300
+ const SDK_RULES_AND_PATTERNS_TOOL = composeSdkRulesAndPatterns('tool');
301
+ const SDK_RULES_AND_PATTERNS_SANDBOX = composeSdkRulesAndPatterns('sandbox');
404
302
  exports.BUILDER_AGENT_PROMPT = `You are an expert n8n workflow builder. You generate complete, valid TypeScript code using the @n8n/workflow-sdk.
405
303
 
406
- ## Output Discipline
407
- - Your text output is visible to the user. Be concise but natural.
408
- - Do NOT narrate your process ("I'll build this step by step", "Let me start by"). Just do the work.
409
- - No emojis, no filler phrases, no markdown headers in your text output.
410
- - When conversation context is provided, use it to continue naturally — do not repeat information the user already knows.
411
- - Only output text for: errors that need attention, or a brief natural completion message.
304
+ ${BUILDER_OUTPUT_DISCIPLINE}
412
305
 
413
306
  ## Repair Strategy
414
307
  When called with failure details for an existing workflow, start from the pre-loaded code — do not re-discover node types already present.
415
308
 
416
309
  ## Escalation
417
- - If you are stuck or need information only a human can provide (e.g., a chat ID, API key, external resource name), use the \`ask-user\` tool to ask a clear question.
418
- - Do NOT retry the same failing approach more than twice — ask the user instead.
419
- - ${PLACEHOLDER_ESCALATION}
310
+ ${shared_prompts_1.ASK_USER_FALLBACK}
311
+
312
+ ${shared_prompts_1.PLACEHOLDERS_RULE}
420
313
 
421
314
  ## Mandatory Process
422
315
  1. **Research**: If the workflow fits a known category (notification, chatbot, scheduling, data_transformation, etc.), call \`nodes(action="suggested")\` first for curated recommendations. Then use \`nodes(action="search")\` for service-specific nodes (use short service names: "Gmail", "Slack", not "send email SMTP"). The results include \`discriminators\` (available resources and operations) for nodes that need them. Then call \`nodes(action="type-definition")\` with the appropriate resource/operation to get the TypeScript schema with exact parameter names and types. **Pay attention to @builderHint annotations** in search results and type definitions — they prevent common configuration mistakes.
423
316
  2. **Build**: Write TypeScript SDK code and call \`build-workflow\`. Follow the SDK patterns below exactly.
424
317
  3. **Fix errors**: If \`build-workflow\` returns errors, use **patch mode**: call \`build-workflow\` with \`patches\` (array of \`{old_str, new_str}\` replacements). Patches apply to your last submitted code, or auto-fetch from the saved workflow if \`workflowId\` is given. Much faster than resending full code.
425
318
  4. **Modify existing workflows**: When updating a workflow, call \`build-workflow\` with \`workflowId\` + \`patches\`. The tool fetches the current code and applies your patches. Use \`workflows(action="get-as-code")\` first to see the current code if you need to identify what to replace.
426
- 4. **Done**: When \`build-workflow\` succeeds, output a brief, natural completion message.
319
+ 5. **Done**: When \`build-workflow\` succeeds, output a brief, natural completion message.
427
320
 
428
- Do NOT produce visible output until step 4. All reasoning happens internally.
321
+ Do NOT produce visible output until step 5. All reasoning happens internally.
429
322
 
430
- ## Credential Rules
323
+ ## Credential Rules (tool mode)
431
324
  - Always use \`newCredential('Credential Name')\` for credentials, never fake keys or placeholders.
432
- - NEVER use raw credential objects like \`{ id: '...', name: '...' }\`.
325
+ - NEVER use raw credential objects like \`{ id: '...', name: '...' }\` — that form is for sandbox mode only.
433
326
  - When editing a pre-loaded workflow, the roundtripped code may have credentials as raw objects — replace them with \`newCredential()\` calls.
434
327
  - Unresolved credentials (where the user chose mock data or no credential is available) will be automatically mocked via pinned data at submit time. Always declare \`output\` on nodes that use credentials so mock data is available. The workflow will be testable via manual/test runs but not production-ready until real credentials are added.
435
328
 
436
- ${SDK_RULES_AND_PATTERNS}
329
+ ${SDK_RULES_AND_PATTERNS_TOOL}
437
330
  `;
438
331
  function createSandboxBuilderAgentPrompt(workspaceRoot) {
439
332
  return `You are an expert n8n workflow builder working inside a sandbox with real TypeScript tooling. You write workflow code as files and use \`tsc\` for validation.
440
333
 
441
- ## Output Discipline
442
- - Your text output is visible to the user. Be concise but natural.
443
- - Do NOT narrate your process ("I'll build this step by step", "Let me start by"). Just do the work.
444
- - No emojis, no filler phrases, no markdown headers in your text output.
445
- - When conversation context is provided, use it to continue naturally — do not repeat information the user already knows.
446
- - Only output text for: errors that need attention, or a brief natural completion message.
334
+ ${BUILDER_OUTPUT_DISCIPLINE}
447
335
 
448
336
  ## Workspace Layout
449
337
 
@@ -598,9 +486,9 @@ Replace \`CHUNK_WORKFLOW_ID\` with the actual ID returned by \`submit-workflow\`
598
486
  - **Complex workflows** (5+ nodes, multiple integrations): Decompose into chunks.
599
487
  Build, test, and compose. Each chunk is reusable across workflows.
600
488
 
601
- ## Setup Workflows (Create Missing Resources)
489
+ ${shared_prompts_1.PLACEHOLDERS_RULE}
602
490
 
603
- ${PLACEHOLDER_RULE}
491
+ ## Setup Workflows (Create Missing Resources)
604
492
 
605
493
  When \`nodes(action="explore-resources")\` returns no results for a required resource:
606
494
 
@@ -615,9 +503,7 @@ When \`nodes(action="explore-resources")\` returns no results for a required res
615
503
  When called with failure details for an existing workflow, start from the pre-loaded code — do not re-discover node types already present.
616
504
 
617
505
  ## Escalation
618
- - If you are stuck or need information only a human can provide (e.g., a chat ID, API key, external resource name), use the \`ask-user\` tool to ask a clear question.
619
- - Do NOT retry the same failing approach more than twice — ask the user instead.
620
- - ${PLACEHOLDER_ESCALATION}
506
+ ${shared_prompts_1.ASK_USER_FALLBACK}
621
507
 
622
508
  ## Sandbox Isolation
623
509
 
@@ -635,9 +521,9 @@ When called with failure details for an existing workflow, start from the pre-lo
635
521
  - **For large HTML, use the file-based pattern.** Write HTML to \`chunks/page.html\`, then \`readFileSync\` + \`JSON.stringify\` in your SDK code. NEVER embed large HTML directly in jsCode — it will break. See the web_app_pattern section.
636
522
  - **Em-dash and Unicode**: the sandbox executes real JS so these technically work, but prefer plain hyphens for consistency with the shared SDK rules.
637
523
 
638
- ## Credentials
524
+ ## Credentials (sandbox mode)
639
525
 
640
- Call \`credentials(action="list")\` early. Each credential has an \`id\`, \`name\`, and \`type\`. Wire them into nodes like this:
526
+ Sandbox mode uses **raw credential objects** (not \`newCredential()\`). Call \`credentials(action="list")\` early. Each credential has an \`id\`, \`name\`, and \`type\`. Wire them into nodes like this:
641
527
 
642
528
  \`\`\`typescript
643
529
  credentials: {
@@ -649,6 +535,8 @@ The key (\`openWeatherMapApi\`) is the credential **type** from the node type de
649
535
 
650
536
  If the required credential type is not in \`credentials(action="list")\` results, call \`credentials(action="search-types")\` with the service name (e.g. "linear", "notion") to discover available dedicated credential types. Always prefer dedicated types over generic auth (\`httpHeaderAuth\`, \`httpBearerAuth\`, etc.). When generic auth is truly needed (no dedicated type exists), prefer \`httpBearerAuth\` over \`httpHeaderAuth\`.
651
537
 
538
+ The credential-selection guidance above applies to outbound service calls. For inbound trigger nodes such as Webhook, Form Trigger, Chat Trigger, and MCP Trigger, keep authentication at its default \`none\` unless the user explicitly asks to authenticate inbound traffic.
539
+
652
540
  ## Data Tables
653
541
 
654
542
  n8n normalizes column names to snake_case (e.g., \`dayName\` → \`day_name\`). Always call \`data-tables(action="schema")\` before using a data table in workflow code to get the real column names.
@@ -683,8 +571,10 @@ n8n normalizes column names to snake_case (e.g., \`dayName\` → \`day_name\`).
683
571
 
684
572
  4. **Resolve real resource IDs**: Check the node schemas from step 3 for parameters with \`searchListMethod\` or \`loadOptionsMethod\`. For EACH one, call \`nodes(action="explore-resources")\` with the node type, method name, and the matching credential from step 1 to discover real resource IDs.
685
573
  - **This is mandatory for: calendars, spreadsheets, channels, folders, models, databases, and any other list-based parameter.** Do NOT assume values like "primary", "default", or "General" — always look up the real ID.
574
+ - **LLM models in particular** (OpenAI, Anthropic, Groq, etc.): always call \`explore-resources\` with the node's \`@searchListMethod\` when a credential for that provider is attached. The live list reflects what the credential can actually access — free/cheap tiers are often limited (e.g. an OpenAI free-tier key may only return \`gpt-5-mini\`). Picking a model ID that the credential can't access produces a broken workflow. The list is sorted newest-first; use the \`@builderHint\` as selection guidance (e.g. "prefer the GPT-5.4 family") over the live results, not as a hard-coded pick.
686
575
  - Example: Google Calendar's \`calendar\` parameter uses \`searchListMethod: getCalendars\`. Call \`nodes(action="explore-resources")\` with \`methodName: "getCalendars"\` to get the actual calendar ID (e.g., "user@example.com"), not "primary".
687
576
  - **Never use \`placeholder()\` or fake IDs for discoverable resources.** Create them via a setup workflow instead (see "Setup Workflows" section). For user-provided values, follow the placeholder rules in "SDK Code Rules".
577
+ - **If \`explore-resources\` returns more than one match and the user did not name a specific one, use \`placeholder('Select <resource>')\` for that parameter** (e.g. \`placeholder('Select a calendar')\`, \`placeholder('Select a Slack channel')\`). Picking one silently is a guess; the setup wizard surfaces placeholders so the user can choose after the build. Only pick a single match without prompting.
688
578
  - If the resource can't be created via n8n (e.g., Slack channels), explain clearly in your summary what the user needs to set up.
689
579
 
690
580
  5. **Write workflow code** to \`${workspaceRoot}/src/workflow.ts\`.
@@ -722,13 +612,21 @@ Follow the **Compositional Workflow Pattern** above. The process becomes:
722
612
  Do NOT produce visible output until the final step. All reasoning happens internally.
723
613
 
724
614
  ## Modifying Existing Workflows
725
- When modifying an existing workflow, the current code is **already pre-loaded** into \`${workspaceRoot}/src/workflow.ts\` with SDK imports. You can:
726
- - Read it with \`read_file\` to see the current code
615
+ When modifying an existing workflow, the current code is **already pre-loaded** into \`${workspaceRoot}/src/workflow.ts\` with SDK imports.
616
+
617
+ **Pre-flight check before any edit**: If the change introduces a node type not already in the file, or touches parameter values you haven't just looked up (model IDs, RLC values, enum selections, credential types, versions, etc.), call \`nodes(action="type-definition")\` first. Read \`@builderHint\`, \`@default\`, \`@searchListMethod\`, and \`@loadOptionsMethod\` from the output.
618
+
619
+ **Live credential-backed lookups are the source of truth for RLC/list parameters.** When a node exposes \`@searchListMethod\` or \`@loadOptionsMethod\` and a credential for its type is attached, call \`nodes(action="explore-resources")\` to query what the credential can actually access — don't rely on \`@default\` or memory. Treat \`@builderHint\` as *selection guidance over the live list* ("prefer the GPT-5.4 family", "prefer the most recent Sonnet") rather than as the source of the value itself. When no credential is attached, fall back to \`@default\`. If the hint and \`@default\` disagree on the fallback, prefer the hint — it's curated more actively.
620
+
621
+ Do not guess method names for \`explore-resources\`, and do not fill parameter values in from memory, even when the node or parameter feels familiar. This applies to swaps (Anthropic → OpenAI), model changes, trigger changes, and any parameter whose allowed values are unclear.
622
+
623
+ Steps:
624
+ - Read the current code with \`read_file\`
727
625
  - Edit using \`edit_file\` for targeted changes or \`write_file\` for full rewrites (always use absolute paths)
728
626
  - Run tsc → submit-workflow with the \`workflowId\`
729
627
  - Do NOT call \`workflows(action="get-as-code")\` — the file is already populated
730
628
 
731
- ${SDK_RULES_AND_PATTERNS}
629
+ ${SDK_RULES_AND_PATTERNS_SANDBOX}
732
630
  `;
733
631
  }
734
632
  //# sourceMappingURL=build-workflow-agent.prompt.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"build-workflow-agent.prompt.js","sourceRoot":"","sources":["../../../src/tools/orchestration/build-workflow-agent.prompt.ts"],"names":[],"mappings":";;;AA+dA,0EAuSC;AA9vBD,+FAQkE;AAClE,6EAIkD;AAClD,2EAKiD;AAKjD,MAAM,gBAAgB,GACrB,6eAA6e,CAAC;AAG/e,MAAM,sBAAsB,GAC3B,kTAAkT,CAAC;AAIpT,MAAM,cAAc,GAAG;;;;IAInB,gBAAgB;;;;;;qFAMiE,CAAC;AAEtF,MAAM,yBAAyB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAwWhC,iCAAgB;;;EAGhB,+CAA8B;;;EAG9B,sCAAqB,EAAE,CAAC;AAI1B,MAAM,sBAAsB,GAAG;IAC9B,cAAc;IACd,8BAAc;IACd,+BAA+B,GAAG,qCAAqB;IACvD,6BAA6B,GAAG,oCAAoB;IACpD,6BAA6B,GAAG,oCAAoB;IACpD,uCAAuC;IACvC,gCAAa,CAAC,OAAO;IACrB,oCAAiB,CAAC,OAAO;IACzB,iCAAc,CAAC,OAAO;IACtB,qCAAkB,CAAC,OAAO;IAC1B,mCAAgB,CAAC,OAAO;IACxB,wCAAqB,CAAC,OAAO;IAC7B,yCAAsB,CAAC,OAAO;IAC9B,yBAAyB;CACzB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAIF,QAAA,oBAAoB,GAAG;;;;;;;;;;;;;;;IAehC,sBAAsB;;;;;;;;;;;;;;;;;EAiBxB,sBAAsB;CACvB,CAAC;AAIF,SAAgB,+BAA+B,CAAC,aAAqB;IACpE,OAAO;;;;;;;;;;;0BAWkB,aAAa,6DAA6D,aAAa;;;EAG/G,aAAa;;;;;;;;;;;;;;;;;;KAkBV,aAAa;;;;;;;;;;;;;;;KAeb,aAAa;;;;;;;;;;;;;;;;;;;;;KAqBb,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAsDb,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA0ChB,gBAAgB;;;;;;;;;;;;;;;;;IAiBd,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;sCA0DY,aAAa;;;;;;;;;;;;kCAYjB,aAAa;;;;;;;;;;;;;;;;;;;;;;;;6BAwBlB,aAAa;;;;sCAIJ,aAAa;;;;;;;yFAOsC,aAAa;;;;;;EAMpG,sBAAsB;CACvB,CAAC;AACF,CAAC"}
1
+ {"version":3,"file":"build-workflow-agent.prompt.js","sourceRoot":"","sources":["../../../src/tools/orchestration/build-workflow-agent.prompt.ts"],"names":[],"mappings":";;;AAgYA,0EA4SC;AApqBD,+FAQkE;AAClE,6EAIkD;AAClD,2EAKiD;AAEjD,+DAAkF;AAIlF,MAAM,yBAAyB,GAAG;;;;;;;;;;;;;;;;;;0GAkBwE,CAAC;AAI3G,MAAM,cAAc,GAAG;;;;;;;;;;qFAU8D,CAAC;AAKtF,SAAS,4BAA4B,CAAC,IAAwB;IAC7D,MAAM,iBAAiB,GACtB,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,0CAA0C,CAAC,CAAC,CAAC,yBAAyB,CAAC;IAC7F,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gCA+BwB,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAuK/C,iCAAgB;;;EAGhB,+CAA8B;;;EAG9B,sCAAqB,EAAE,CAAC;AAC1B,CAAC;AAED,MAAM,8BAA8B,GAAG,4BAA4B,CAAC,MAAM,CAAC,CAAC;AAC5E,MAAM,iCAAiC,GAAG,4BAA4B,CAAC,SAAS,CAAC,CAAC;AAOlF,MAAM,sBAAsB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;qSAyBsQ,CAAC;AAEtS,SAAS,0BAA0B,CAAC,IAAwB;IAM3D,MAAM,eAAe,GACpB,IAAI,KAAK,SAAS;QACjB,CAAC,CAAC,8FAA8F;YAC/F,8FAA8F;YAC9F,gGAAgG;YAChG,oDAAoD;QACrD,CAAC,CAAC,IAAI,CAAC;IACT,OAAO;QACN,cAAc;QACd,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,8BAAc;QAC5D,GAAG,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7C,+BAA+B,GAAG,qCAAqB;QACvD,6BAA6B,GAAG,oCAAoB;QACpD,6BAA6B,GAAG,oCAAoB;QACpD,uCAAuC;QACvC,gCAAa,CAAC,OAAO;QACrB,oCAAiB,CAAC,OAAO;QACzB,iCAAc,CAAC,OAAO;QACtB,qCAAkB,CAAC,OAAO;QAC1B,mCAAgB,CAAC,OAAO;QACxB,wCAAqB,CAAC,OAAO;QAC7B,yCAAsB,CAAC,OAAO;QAC9B,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,iCAAiC,CAAC,CAAC,CAAC,8BAA8B;KACvF,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAChB,CAAC;AAED,MAAM,2BAA2B,GAAG,0BAA0B,CAAC,MAAM,CAAC,CAAC;AACvE,MAAM,8BAA8B,GAAG,0BAA0B,CAAC,SAAS,CAAC,CAAC;AAIhE,QAAA,oBAAoB,GAAG;;EAElC,yBAAyB;;;;;;EAMzB,kCAAiB;;EAEjB,kCAAiB;;;;;;;;;;;;;;;;;EAiBjB,2BAA2B;CAC5B,CAAC;AAIF,SAAgB,+BAA+B,CAAC,aAAqB;IACpE,OAAO;;EAEN,yBAAyB;;;;0BAID,aAAa,6DAA6D,aAAa;;;EAG/G,aAAa;;;;;;;;;;;;;;;;;;KAkBV,aAAa;;;;;;;;;;;;;;;KAeb,aAAa;;;;;;;;;;;;;;;;;;;;;KAqBb,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAsDb,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAwChB,kCAAiB;;;;;;;;;;;;;;;;;EAiBjB,kCAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;sCA4DmB,aAAa;;;;;;;;;;;;;;kCAcjB,aAAa;;;;;;;;;;;;;;;;;;;;;;;;6BAwBlB,aAAa;;;;sCAIJ,aAAa;;;;;;;yFAOsC,aAAa;;;;;;;;;;;;;;EAcpG,8BAA8B;CAC/B,CAAC;AACF,CAAC"}
@@ -1,18 +1,57 @@
1
1
  import { z } from 'zod';
2
- import type { BackgroundTaskResult, OrchestrationContext } from '../../types';
3
- import { type SubmitWorkflowAttempt } from '../workflows/submit-workflow.tool';
2
+ import type { OrchestrationContext } from '../../types';
3
+ import { type WorkflowBuildOutcome, type WorkflowLoopState } from '../../workflow-loop';
4
+ import { type SubmitWorkflowAttempt, type SubmitWorkflowOutput } from '../workflows/submit-workflow.tool';
5
+ export declare function buildWarmBuilderFollowUp(input: {
6
+ task: string;
7
+ conversationContext?: string;
8
+ workflowId: string;
9
+ workItemId: string;
10
+ }): string;
4
11
  export declare function recordSuccessfulWorkflowBuilds(tool: unknown, onWorkflowId: (workflowId: string) => void): void;
12
+ export declare function mergeLatestVerificationIntoOutcome(outcome: WorkflowBuildOutcome, latestOutcome: WorkflowBuildOutcome | undefined): WorkflowBuildOutcome;
13
+ export declare function withTerminalLoopState(outcome: WorkflowBuildOutcome, state: WorkflowLoopState | undefined): WorkflowBuildOutcome;
14
+ export declare function finalizeBuildResult(context: OrchestrationContext, workItemId: string, result: {
15
+ text: string;
16
+ outcome: WorkflowBuildOutcome;
17
+ }): Promise<{
18
+ text: string;
19
+ outcome: WorkflowBuildOutcome;
20
+ }>;
5
21
  export declare function resultFromPostStreamError(input: {
6
22
  error: unknown;
7
23
  submitAttempts: SubmitWorkflowAttempt[];
8
24
  mainWorkflowPath: string;
9
25
  workItemId: string;
26
+ runId: string;
27
+ taskId: string;
28
+ }): {
29
+ text: string;
30
+ outcome: WorkflowBuildOutcome;
31
+ } | undefined;
32
+ export declare function resultFromLaterFailedMainSubmit(input: {
33
+ failedAttempt: SubmitWorkflowAttempt;
34
+ submitAttempts: SubmitWorkflowAttempt[];
35
+ mainWorkflowPath: string;
36
+ workItemId: string;
37
+ runId: string;
10
38
  taskId: string;
11
- }): BackgroundTaskResult | undefined;
39
+ }): {
40
+ text: string;
41
+ outcome: WorkflowBuildOutcome;
42
+ } | undefined;
43
+ export declare function attemptFromAutoResubmit(input: {
44
+ latestAttempt: SubmitWorkflowAttempt | undefined;
45
+ resubmit: SubmitWorkflowOutput;
46
+ filePath: string;
47
+ sourceHash: string;
48
+ }): SubmitWorkflowAttempt | undefined;
49
+ export declare function shouldRecoverSavedWorkflowAfterFailedSubmit(attempt: SubmitWorkflowAttempt): boolean;
12
50
  export interface StartBuildWorkflowAgentInput {
13
51
  task: string;
14
52
  workflowId?: string;
15
53
  conversationContext?: string;
54
+ workItemId?: string;
16
55
  taskId?: string;
17
56
  agentId?: string;
18
57
  plannedTaskId?: string;
@@ -27,13 +66,22 @@ export declare const buildWorkflowAgentInputSchema: z.ZodObject<{
27
66
  task: z.ZodString;
28
67
  workflowId: z.ZodOptional<z.ZodString>;
29
68
  conversationContext: z.ZodOptional<z.ZodString>;
69
+ workItemId: z.ZodOptional<z.ZodString>;
70
+ bypassPlan: z.ZodOptional<z.ZodBoolean>;
71
+ reason: z.ZodOptional<z.ZodString>;
30
72
  }, "strip", z.ZodTypeAny, {
31
73
  task: string;
32
74
  workflowId?: string | undefined;
75
+ reason?: string | undefined;
76
+ workItemId?: string | undefined;
33
77
  conversationContext?: string | undefined;
78
+ bypassPlan?: boolean | undefined;
34
79
  }, {
35
80
  task: string;
36
81
  workflowId?: string | undefined;
82
+ reason?: string | undefined;
83
+ workItemId?: string | undefined;
37
84
  conversationContext?: string | undefined;
85
+ bypassPlan?: boolean | undefined;
38
86
  }>;
39
87
  export declare function createBuildWorkflowAgentTool(context: OrchestrationContext): import("@mastra/core/tools").Tool<InferPublicSchema<T>, InferPublicSchema<T>, InferPublicSchema<T>, InferPublicSchema<T>, import("@mastra/core/tools").ToolExecutionContext<InferPublicSchema<T>, InferPublicSchema<T>, unknown>, "build-workflow-with-agent", unknown>;