Skip to content

feat(editor): Surface used data tables and bound credentials in Artifacts panel#28762

Closed
aalises wants to merge 12 commits intomasterfrom
ai-2399-artifacts-panel-include-used-but-not-created-tables-and
Closed

feat(editor): Surface used data tables and bound credentials in Artifacts panel#28762
aalises wants to merge 12 commits intomasterfrom
ai-2399-artifacts-panel-include-used-but-not-created-tables-and

Conversation

@aalises
Copy link
Copy Markdown
Contributor

@aalises aalises commented Apr 21, 2026

Summary

The Instance AI Artifacts panel now also surfaces:

  • existing data tables the agent reused inside a produced workflow
  • credentials the agent bound to a produced workflow via setup

References are resolved on the CLI adapter via a new getWorkflowReferences context method and emitted from workflows(action="setup") State 4, build-workflow, and submit-workflow. The frontend registry keys references per workflowId, orders tool calls globally by startedAt, and renders produced ∪ referenced (produced wins on id collisions).

Related Linear tickets, Github issues, and Community forum posts

https://linear.app/n8n/issue/AI-2399

Review / Merge checklist

  • I have seen this code, I have run this code, and I take responsibility for this code.
  • PR title and summary are descriptive.
  • Docs updated or follow-up ticket created.
  • Tests included.

…acts panel

Existing data tables the agent reused inside a produced workflow and
credentials bound via setup now appear in the Instance AI Artifacts
panel alongside created resources.

Tools (workflows setup State 4, build-workflow, submit-workflow) resolve
a workflow's references through a new InstanceAiContext.getWorkflowReferences
method implemented on the adapter, using the workflow's owning project
via OwnershipService and access-aware service calls. The frontend
registry keys references per workflowId so new emits replace prior ones,
ordered globally by startedAt to stay correct across parent/child agent
interleavings.

Linear: https://linear.app/n8n/issue/AI-2399
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 21, 2026

Bundle Report

Changes will increase total bundle size by 2.88kB (0.01%) ⬆️. This is within the configured threshold ✅

Detailed changes
Bundle name Size Change
editor-ui-esm 45.23MB 2.88kB (0.01%) ⬆️

Affected Assets, Files, and Routes:

view changes for bundle: editor-ui-esm

Assets Changed:

Asset Name Size Change Total Size Change (%)
assets/worker-*.js 3.14MB 3.15MB 17517.58% ⚠️
assets/worker-*.js -3.14MB 17.9kB -99.43%
assets/core-*.js 137 bytes 629.86kB 0.02%
assets/InstanceAiView-*.js 2.21kB 388.35kB 0.57%
assets/InstanceAiView-*.css 27 bytes 176.7kB 0.02%
assets/CreditWarningBanner-*.js 503 bytes 60.42kB 0.84%

Files in assets/InstanceAiView-*.js:

  • ./src/features/ai/instanceAi/components/InstanceAiMarkdown.vue → Total Size: 368 bytes

  • ./src/features/ai/instanceAi/components/InstanceAiArtifactsPanel.vue → Total Size: 392 bytes

Files in assets/CreditWarningBanner-*.js:

  • ./src/features/ai/instanceAi/useResourceRegistry.ts → Total Size: 7.38kB

  • ./src/features/ai/instanceAi/instanceAi.store.ts → Total Size: 25.48kB

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 21, 2026

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 21, 2026

Instance AI Workflow Eval Results

9/9 built | 3 run(s) | pass@3: 72% | pass^3: 31% | iterations: 48% / 45% / 55%

Workflow Build pass@3 pass^3
Every hour, fetch all records from an Airtable table. Use the HTTP Req 3/3 100% 100%
Create a workflow that handles contact form submissions via a webhook. 3/3 60% 17%
Get all the Linear issues created in the last 2 weeks. Filter them for 3/3 40% 6%
Every day, get the posts made in the past day on 3 different Slack cha 3/3 60% 12%
Create a form that collects: name, email, company, and interest level 3/3 100% 100%
Every day, fetch all open GitHub issues from repository 'acme-corp/bac 3/3 50% 14%
Create a workflow that receives webhook notifications with a JSON body 3/3 100% 3%
Fetch the latest posts from the JSONPlaceholder API (GET https://jsonp 3/3 100% 53%
Every hour, check the current weather for London, New York, and Tokyo 3/3 100% 64%
Failure details

Create a workflow that handles contact form submissions via a webhook. / happy-path — 2/3 passed

Run [builder_issue]: The workflow crashed at the 'Send Auto-Reply Email' node with 'Cannot read properties of undefined (reading 'split')'. This error occurs in the Gmail node when the 'sendTo' field expression `={{ $json

Create a workflow that handles contact form submissions via a webhook. / missing-fields — 2/3 passed

Run [builder_issue]: The workflow crashed on the 'Send Auto-Reply Email' node with 'Cannot read properties of undefined (reading 'split')'. The pinned webhook data provides name as an empty string (""), but the Gmail node

Create a workflow that handles contact form submissions via a webhook. / partial-action-failure — 0/3 passed

Run [builder_issue]: The workflow crashed at the 'Send Auto-Reply Email' node with 'Cannot read properties of undefined (reading 'split')'. This error occurs because the Gmail node's 'sendTo' field uses '={{ $json.email }
Run [builder_issue]: The Telegram node errored with 'Bad request - please check your parameters' due to the mock returning a 400 error (chat not found). This caused the entire workflow to crash — the error propagated as a
Run [builder_issue]: The workflow crashed when the Telegram node failed. The connections show that Send Auto-Reply Email, Telegram Team Notification, and Log to Google Sheets all run in parallel from Contact Form Webhook

Create a workflow that handles contact form submissions via a webhook. / empty-message — 2/3 passed

Run [builder_issue]: The workflow crashed with 'Cannot read properties of undefined (reading 'split')' in the Send Auto-Reply Email node. The error occurs because the Gmail node's 'sendTo' field uses {{ $json.email }} b

Create a workflow that handles contact form submissions via a webhook. / invalid-email — 0/3 passed

Run [builder_issue]: The workflow crashed at the 'Send Auto-Reply Email' node with the error 'Cannot read properties of undefined (reading 'split')'. This happened because the Gmail node's sendTo parameter is set to `={
Run [builder_issue]: The workflow crashes entirely when the invalid email 'not-an-email' is encountered. The Send Auto-Reply Email (Gmail) node throws 'Invalid email address (item 0)' and terminates execution. Because thi
Run [builder_issue]: The workflow crashed at the 'Send Auto-Reply Email' node with 'Invalid email address (item 0)' because 'not-an-email' is not a valid email. This error halted the entire workflow execution — 'Telegram

Get all the Linear issues created in the last 2 weeks. Filter them for / happy-path — 0/3 passed

Run [mock_issue]: The workflow did not complete the full pipeline. While Fetch Linear Issues and Filter Cross-Team Issues executed, the Filter Cross-Team Issues node produced no output (empty result), causing Count Per
Run [builder_issue]: The workflow failed with 'Invalid or unexpected token' in the 'Filter and Count Cross-Team Issues' Code node. The node did not produce any output and Post to Slack never ran. Inspecting the jsCode par
Run [builder_issue]: The workflow executed without errors and posted to Slack, but the cross-team filtering logic is incorrect. The code node uses item.json.team?.name to get the issue's team, but the Linear API respons

Get all the Linear issues created in the last 2 weeks. Filter them for / multi-team-creator — 0/3 passed

Run [mock_issue]: The workflow failed to complete execution. The 'Filter Cross-Team Issues' node produced no output (empty result), which caused 'Count Per Creator', 'Format Slack Message', and 'Post to Slack' to not r
Run [builder_issue]: The workflow failed with 'Invalid or unexpected token' in the Filter and Count Cross-Team Issues code node. The pre-analysis flags a FRAMEWORK ISSUE: Phase 1 returned empty trigger content, meaning th
Run [builder_issue]: The Filter Cross-Team and Count node output shows [email protected]: 3 and [email protected]: 1, with total: 4. This is incorrect. The scenario requires that Alice's AI issue (LIN-103, 'Integrate new LL

Get all the Linear issues created in the last 2 weeks. Filter them for / no-cross-team-issues — 1/3 passed

Run [builder_issue]: The workflow crashed with 'Invalid or unexpected token' in the 'Filter and Count Cross-Team Issues' code node. The node errored and produced no output, so Post to Slack never ran. The error 'Invalid o
Run [builder_issue]: The workflow executed without errors, which satisfies the 'no crash' requirement. However, the cross-team filter did NOT remove all issues as the scenario requires. The Filter Cross-Team and Count cod

Get all the Linear issues created in the last 2 weeks. Filter them for / unknown-creator — 2/3 passed

Run [builder_issue]: The workflow crashed at the 'Filter and Count Cross-Team Issues' Code node with 'Invalid or unexpected token'. This error is a JavaScript syntax error in the node's code, which prevented any execution

Get all the Linear issues created in the last 2 weeks. Filter them for / api-error — 0/3 passed

Run [builder_issue]: The workflow crashed with an unhandled 'Authentication required' error from the Fetch Linear Issues node. There is no error handling branch (e.g., an error handler node, a try/catch in a Code node, or
Run [builder_issue]: The workflow crashed with an unhandled error when the Linear API returned an authentication error. The 'Fetch Linear Issues' node threw 'Invalid or missing API key. Please check your Linear API creden
Run [builder_issue]: The workflow does not handle the API authentication error gracefully. When the Fetch Linear Issues node receives a 401 authentication error from the Linear API, the workflow crashes with 'Authenticati

Every day, get the posts made in the past day on 3 different Slack cha / happy-path — 2/3 passed

Run [builder_issue]: The workflow executed without errors and reached the final posting node, but the summary sent to the AI contained no actual message data. The Aggregate Messages code node output shows all three channe

Every day, get the posts made in the past day on 3 different Slack cha / empty-channel — 1/3 passed

Run [builder_issue]: The workflow did not complete end-to-end. The Merge Channel Messages node, Aggregate Messages node, Summarize with AI node, and Post to #daily-digest node all DID NOT RUN. The root cause is that Get #
Run [builder_issue]: The workflow completed end-to-end without errors, and the merge step handled the empty #product channel gracefully (it produced a placeholder '(no messages in the past 24 hours)' entry). However, the

Every day, get the posts made in the past day on 3 different Slack cha / high-volume — 2/3 passed

Run [builder_issue]: The workflow has a critical data loss issue in the merge step. The Tag nodes output only channel_id and channel_name fields — they are missing the actual message content (ts, user, text) fro

Every day, get the posts made in the past day on 3 different Slack cha / channel-not-found — 0/3 passed

Run [builder_issue]: The workflow crashed entirely when 'Get #product Messages' returned a channel_not_found error. There is no error handling configured on that node (no 'Continue on Error' setting, no try/catch, no erro
Run [builder_issue]: The workflow has no error handling for the channel_not_found case. When 'Get #product Messages' received the error response, the node threw 'Slack error response: channel_not_found' and the entire wor
Run [builder_issue]: The workflow crashed entirely when 'Get #product Messages' received a channel_not_found error. There is no error handling (e.g., a Continue on Error setting, a try/catch branch, or an IF node to handl

Every day, get the posts made in the past day on 3 different Slack cha / insufficient-permissions — 0/3 passed

Run [builder_issue]: The workflow crashes when 'Get #product Messages' returns a 403 error (the mock returned a not_in_channel error response). The workflow has no error handling configured on that node — no 'Continue on
Run [builder_issue]: The workflow does not handle the permission error gracefully. When 'Get #product Messages' receives the 'not_in_channel' error response from Slack, the node throws an exception ('Slack error response:
Run [builder_issue]: The workflow crashed entirely when 'Get #product Messages' received a 'not_in_channel' error from Slack. No error handling exists — there is no try/catch, no error branch, no continueOnFail setting on

Every day, fetch all open GitHub issues from repository 'acme-corp/bac / happy-path — 0/3 passed

Run [mock_issue]: The workflow errored with 'Cannot read properties of undefined (reading 'type')' in the Create Notion Page node. Examining the execution trace: the first two Notion API calls succeeded (POST for issue
Run [builder_issue]: The workflow failed to execute. The pre-analysis flags a builder issue: the 'Split Issues' node (n8n-nodes-base.splitOut) has its 'fieldToSplitOut' parameter set to an empty string, while the paramete
Run [mock_issue]: The workflow errored at the 'Create Notion Page' node with 'Cannot read properties of undefined (reading 'type')'. Tracing the execution: the first POST to Notion returned a full page response and app

Every day, fetch all open GitHub issues from repository 'acme-corp/bac / no-bugs — 2/3 passed

Run [builder_issue]: The workflow failed to execute cleanly. The 'Split Issues' node has a misconfigured 'fieldToSplitOut' parameter (empty string), which caused the execution to fail entirely with 'The workflow has issue

Create a workflow that receives webhook notifications with a JSON body / high-priority — 1/3 passed

Run [builder_issue]: The Route by Level switch node correctly identified the 'high' level and routed to output index 0 (the 'high' branch), but the connections JSON shows 'Route by Level' has an empty 'main' array — meani
Run [builder_issue]: The Switch node ('Route by Level') correctly matched the 'high' level condition and produced output on its first branch. However, the connections JSON shows 'Route by Level' has an empty 'main' array

Create a workflow that receives webhook notifications with a JSON body / medium-priority — 1/3 passed

Run [builder_issue]: The Switch node correctly routed the medium-priority notification to its 'medium' output (index 1), but the Send Slack Message node never ran. Looking at the connections JSON, 'Route by Level' has `"m
Run [builder_issue]: The Switch node (Route by Level) correctly matched the 'medium' level and produced output on its medium branch. However, the connections JSON shows 'Route by Level' has an empty 'main' array — none of

Create a workflow that receives webhook notifications with a JSON body / low-priority — 1/3 passed

Run [builder_issue]: The Switch node ('Route by Level') correctly routed the low-priority notification to its 'low' output (index 2), but the connections JSON shows that 'Route by Level' has an empty 'main' array — meanin
Run [builder_issue]: The Switch node (Route by Level) correctly identified the 'low' priority and routed the item to its third output (index 2). However, the connections JSON shows 'Route by Level' has "main": [] — mean

Fetch the latest posts from the JSONPlaceholder API (GET https://jsonp / empty-response — 2/3 passed

Run [builder_issue]: The Fetch Posts node received an empty array [] from the mock, which caused it to produce no output items. Because n8n HTTP Request nodes treat an empty array response as zero items, no items passed d

Fetch the latest posts from the JSONPlaceholder API (GET https://jsonp / all-filtered — 2/3 passed

Run [builder_issue]: The checklist requires that when all items are filtered out, the workflow should NOT send an empty message to Slack. However, the execution trace shows that the 'Filter and Summarize' code node return

Every hour, check the current weather for London, New York, and Tokyo / happy-path — 2/3 passed

Run [mock_issue]: Multiple criteria in this checklist item fail:

  1. Not all 3 weather API calls succeeded: The 'Get Weather New York' mock generation failed with _evalMockError, returning an error object instead

Add `get` mock to `dataTableService` test stubs and supply the new
`ownershipService` constructor arg in the adapter service tests so the
suites match the updated interfaces.
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 21, 2026

Performance Comparison

Comparing currentlatest master14-day baseline

docker-stats

Metric Current Latest Master Baseline (avg) vs Master vs Baseline Status
docker-image-size-runners 388.00 MB 388.00 MB 391.58 MB (σ 9.46) +0.0% -0.9%
docker-image-size-n8n 1280.00 MB 1392.64 MB 1297.25 MB (σ 48.76) -8.1% -1.3%

Idle baseline with Instance AI module loaded

Metric Current Latest Master Baseline (avg) vs Master vs Baseline Status
instance-ai-heap-used-baseline 187.02 MB 191.66 MB 187.42 MB (σ 1.77) -2.4% -0.2%
instance-ai-rss-baseline 385.86 MB 352.70 MB 367.22 MB (σ 21.72) +9.4% +5.1%

Memory consumption baseline with starter plan resources

Metric Current Latest Master Baseline (avg) vs Master vs Baseline Status
memory-heap-used-baseline 115.42 MB 118.45 MB 115.30 MB (σ 1.79) -2.6% +0.1%
memory-rss-baseline 352.36 MB 295.84 MB 290.89 MB (σ 29.40) +19.1% +21.1% 🔴
How to read this table
  • Current: This PR's value (or latest master if PR perf tests haven't run)
  • Latest Master: Most recent nightly master measurement
  • Baseline: Rolling 14-day average from master
  • vs Master: PR impact (current vs latest master)
  • vs Baseline: Drift from baseline (current vs rolling avg)
  • Status: ✅ within 1σ | ⚠️ 1-2σ | 🔴 >2σ regression

@n8n-assistant n8n-assistant Bot added core Enhancement outside /nodes-base and /editor-ui n8n team Authored by the n8n team labels Apr 21, 2026
@aalises aalises marked this pull request as ready for review April 21, 2026 11:09
@aalises aalises requested a review from mutdmour April 21, 2026 11:24
aalises added 8 commits April 21, 2026 13:46
Aligns the name-based data-table fallback in resolveWorkflowReferences
with the id-based path so a matched table is only surfaced when the user
has dataTable:read on it, closing a gap where a user with workflow:read
but no dataTable:read could see the table's id and name via the
Artifacts panel.

Adds security tests covering credential and data-table scope denial
(both id and name paths), inaccessible-workflow short-circuit, and
id/name dedup.
…anel-include-used-but-not-created-tables-and
…ter test helper

Aligns createNodeAdapterForTests with the 30-parameter InstanceAiAdapterService
constructor after the ownershipService dependency was added on this branch.
…ot-created-tables-and

# Conflicts:
#	packages/@n8n/api-types/src/schemas/instance-ai.schema.ts
#	packages/@n8n/instance-ai/src/tools/workflows/build-workflow.tool.ts
#	packages/cli/src/modules/instance-ai/__tests__/instance-ai.adapter.service.security.test.ts
#	packages/cli/src/modules/instance-ai/__tests__/instance-ai.adapter.service.test.ts
#	packages/cli/src/modules/instance-ai/instance-ai.adapter.service.ts
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 4 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="packages/cli/src/modules/instance-ai/instance-ai.adapter.service.ts">

<violation number="1" location="packages/cli/src/modules/instance-ai/instance-ai.adapter.service.ts:285">
P2: Name-based data table reference resolution now uses substring search (`LIKE %name%`) with `take: 1`, which can return the wrong table when names overlap.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review, or fix all with cubic.

await Promise.all(
dataTableNameRefs.map(async (name) => {
const { data: matches } = await this.dataTableService.getManyAndCount({
filter: { projectId: project.id, name: name.toLowerCase() },
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot Apr 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Name-based data table reference resolution now uses substring search (LIKE %name%) with take: 1, which can return the wrong table when names overlap.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/cli/src/modules/instance-ai/instance-ai.adapter.service.ts, line 285:

<comment>Name-based data table reference resolution now uses substring search (`LIKE %name%`) with `take: 1`, which can return the wrong table when names overlap.</comment>

<file context>
@@ -279,13 +279,13 @@ export class InstanceAiAdapterService {
 					dataTableNameRefs.map(async (name) => {
-						const match = byName.get(name);
+						const { data: matches } = await this.dataTableService.getManyAndCount({
+							filter: { projectId: project.id, name: name.toLowerCase() },
+							take: 1,
+						});
</file context>
Fix with Cubic

@aalises aalises closed this May 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

core Enhancement outside /nodes-base and /editor-ui n8n team Authored by the n8n team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant