Skip to content

Conversation

burivuhster
Copy link
Contributor

@burivuhster burivuhster commented Oct 21, 2025

Summary

This PR adds programmatic workflow validation capabilities to the AI workflow builder agent. The validation system runs automated checks against workflows to detect critical issues and provide feedback to the AI agent.

Key Changes

  1. New validate_workflow tool - Allows the AI agent to validate workflows programmatically during the building process
  2. Programmatic evaluation - Extracted and modularized evaluation logic:
  • Checks providing list of violations, now used both in validate_workflow tool and as part of evaluation process (moved to src/)
  • Calculating scores (left in evaluations/)
  1. Expression context refactoring - Refactored expression evaluation context initialization
  2. Connections resolution - Now uses expression evaluation instead of temporary Function constructor approach used before
  3. Prompt changes - Instruct main agent to run validation after making changes to the workflow

How it works

The agent can now call validate_workflow() after making changes to ensure the workflow is valid. The tool:

  • Runs all programmatic checks against the current workflow
  • Returns errors for critical or major violations
  • This helps the agent to self-correct issues before finalizing workflows

Related Linear tickets, Github issues, and Community forum posts

Review / Merge checklist

  • PR title and summary are descriptive
  • Docs updated or follow-up ticket created
  • Tests included
  • PR Labeled with release/backport (if urgent fix)

@n8n-assistant n8n-assistant bot added the n8n team Authored by the n8n team label Oct 21, 2025
@burivuhster burivuhster force-pushed the ai-1493-feature-add-programmatic-workflow-checks-in-the-builder branch from 68308bb to c8e0e9b Compare October 21, 2025 13:59
@burivuhster burivuhster marked this pull request as ready for review October 21, 2025 16:42
@burivuhster burivuhster requested review from a team and mike12345567 and removed request for a team October 21, 2025 16:42
Copy link
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.

3 issues found across 41 files

Prompt for AI agents (all 3 issues)

Understand the root cause of the following 3 issues and fix them.


<file name="packages/@n8n/ai-workflow-builder.ee/src/validation/checks/connections.ts">

<violation number="1" location="packages/@n8n/ai-workflow-builder.ee/src/validation/checks/connections.ts:27">
Rule violated: **Prefer Typeguards over Type casting**

`Object.entries` returns string keys, so casting `connectionType` to `NodeConnectionType` sidesteps the guard this rule expects. Please introduce a proper `NodeConnectionType` type guard (or adjust typings so the key is already constrained) instead of relying on `as` for narrowing.</violation>
</file>

<file name="packages/@n8n/ai-workflow-builder.ee/src/validation/utils/resolve-connections.ts">

<violation number="1" location="packages/@n8n/ai-workflow-builder.ee/src/validation/utils/resolve-connections.ts:43">
Rule violated: **Prefer Typeguards over Type casting**

Please avoid using `as` to narrow `result` here. Instead, tighten the typing by introducing a proper type guard (or refining the return type of `Expression.resolveWithoutWorkflow`) so that `result` is proven to be `Array&lt;NodeConnectionType | T&gt;` without relying on a cast.</violation>
</file>

<file name="packages/@n8n/ai-workflow-builder.ee/src/validation/checks/from-ai.ts">

<violation number="1" location="packages/@n8n/ai-workflow-builder.ee/src/validation/checks/from-ai.ts:23">
Rule violated: **Prefer Typeguards over Type casting**

The recursion relies on `as Record&lt;string, unknown&gt;` to narrow `value`/`item` after runtime checks, which breaks the “Prefer Typeguards over Type casting” rule. Please replace these assertions with a dedicated type guard (e.g., `isRecord`) so TypeScript narrows without casting. This applies both to the object branch and the array branch.</violation>
</file>

React with 👍 or 👎 to teach cubic. Mention @cubic-dev-ai to give feedback, ask questions, or re-run the review.

totalConnections += connectionSet.length;
}
if (totalConnections > 0) {
providedInputTypes.set(connectionType as NodeConnectionType, totalConnections);
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Oct 21, 2025

Choose a reason for hiding this comment

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

Rule violated: Prefer Typeguards over Type casting

Object.entries returns string keys, so casting connectionType to NodeConnectionType sidesteps the guard this rule expects. Please introduce a proper NodeConnectionType type guard (or adjust typings so the key is already constrained) instead of relying on as for narrowing.

Prompt for AI agents
Address the following comment on packages/@n8n/ai-workflow-builder.ee/src/validation/checks/connections.ts at line 27:

<comment>`Object.entries` returns string keys, so casting `connectionType` to `NodeConnectionType` sidesteps the guard this rule expects. Please introduce a proper `NodeConnectionType` type guard (or adjust typings so the key is already constrained) instead of relying on `as` for narrowing.</comment>

<file context>
@@ -0,0 +1,184 @@
+			totalConnections += connectionSet.length;
+		}
+		if (totalConnections &gt; 0) {
+			providedInputTypes.set(connectionType as NodeConnectionType, totalConnections);
+		}
+	}
</file context>
Fix with Cubic

throw new Error('Expression did not resolve to an array');
}

return result as Array<NodeConnectionType | T>;
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Oct 21, 2025

Choose a reason for hiding this comment

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

Rule violated: Prefer Typeguards over Type casting

Please avoid using as to narrow result here. Instead, tighten the typing by introducing a proper type guard (or refining the return type of Expression.resolveWithoutWorkflow) so that result is proven to be Array<NodeConnectionType | T> without relying on a cast.

Prompt for AI agents
Address the following comment on packages/@n8n/ai-workflow-builder.ee/src/validation/utils/resolve-connections.ts at line 43:

<comment>Please avoid using `as` to narrow `result` here. Instead, tighten the typing by introducing a proper type guard (or refining the return type of `Expression.resolveWithoutWorkflow`) so that `result` is proven to be `Array&lt;NodeConnectionType | T&gt;` without relying on a cast.</comment>

<file context>
@@ -0,0 +1,102 @@
+			throw new Error(&#39;Expression did not resolve to an array&#39;);
+		}
+
+		return result as Array&lt;NodeConnectionType | T&gt;;
+	}
+
</file context>
Fix with Cubic

}

if (value && typeof value === 'object' && !Array.isArray(value)) {
if (parametersContainFromAi(value as Record<string, unknown>)) {
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Oct 21, 2025

Choose a reason for hiding this comment

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

Rule violated: Prefer Typeguards over Type casting

The recursion relies on as Record<string, unknown> to narrow value/item after runtime checks, which breaks the “Prefer Typeguards over Type casting” rule. Please replace these assertions with a dedicated type guard (e.g., isRecord) so TypeScript narrows without casting. This applies both to the object branch and the array branch.

Prompt for AI agents
Address the following comment on packages/@n8n/ai-workflow-builder.ee/src/validation/checks/from-ai.ts at line 23:

<comment>The recursion relies on `as Record&lt;string, unknown&gt;` to narrow `value`/`item` after runtime checks, which breaks the “Prefer Typeguards over Type casting” rule. Please replace these assertions with a dedicated type guard (e.g., `isRecord`) so TypeScript narrows without casting. This applies both to the object branch and the array branch.</comment>

<file context>
@@ -0,0 +1,76 @@
+		}
+
+		if (value &amp;&amp; typeof value === &#39;object&#39; &amp;&amp; !Array.isArray(value)) {
+			if (parametersContainFromAi(value as Record&lt;string, unknown&gt;)) {
+				return true;
+			}
</file context>
Fix with Cubic

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

n8n team Authored by the n8n team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant