kind: tool-call

agentRole: orchestrator

toolName: build-workflow

Node Execution Test

code:
import { workflow, node, trigger, expr } from '@n8n/workflow-sdk';

const manualTrigger = trigger({
  type: 'n8n-nodes-base.manualTrigger',
  version: 1,
  config: { name: 'Manual Trigger' },
});

const setNode = node({
  type: 'n8n-nodes-base.set',
  version: 3.4,
  config: {
    name: 'node execution test',
    parameters: {
      mode: 'manual',
      assignments: {
        assignments: [
          { name: 'message', type: 'string', value: 'Hello from node execution test' },
        ],
      },
    },
  },
});

export default workflow('id', 'Node Execution Test')
  .add(manualTrigger)
  .to(setNode);

errors: [SET_INVALID_ASSIGNMENT] (node execution test): 'node execution test' [n8n-nodes-base.set] assignment at index 0 is missing a non-empty "id" field.

errors: [INVALID_PARAMETER] (node execution test): Node "node execution test": Field "parameters.assignments.assignments.0.id" has wrong type: expected string, got undefined.


code:
import { workflow, node, trigger } from '@n8n/workflow-sdk';

const manualTrigger = trigger({
  type: 'n8n-nodes-base.manualTrigger',
  version: 1,
  config: { name: 'Manual Trigger' },
});

const setNode = node({
  type: 'n8n-nodes-base.set',
  version: 3.4,
  config: {
    name: 'node execution test',
    parameters: {
      mode: 'manual',
      assignments: {
        assignments: [
          { id: 'field1', name: 'message', type: 'string', value: 'Hello from node execution test' },
        ],
      },
    },
  },
});

export default workflow('id', 'Node Execution Test')
  .add(manualTrigger)
  .to(setNode);

errors: Final action contract missing: include `requiredFinalActions` with one entry for every user-requested terminal effect before saving a new main workflow. Point each entry at the actual enabled action node, not preprocessing or control flow.


code:
import { workflow, node, trigger } from '@n8n/workflow-sdk';

const manualTrigger = trigger({
  type: 'n8n-nodes-base.manualTrigger',
  version: 1,
  config: { name: 'Manual Trigger' },
});

const setNode = node({
  type: 'n8n-nodes-base.set',
  version: 3.4,
  config: {
    name: 'node execution test',
    parameters: {
      mode: 'manual',
      assignments: {
        assignments: [
          { id: 'field1', name: 'message', type: 'string', value: 'Hello from node execution test' },
        ],
      },
    },
  },
});

export default workflow('id', 'Node Execution Test')
  .add(manualTrigger)
  .to(setNode);

errors: Final action contract missing: include `requiredFinalActions` with one entry for every user-requested terminal effect before saving a new main workflow. Point each entry at the actual enabled action node, not preprocessing or control flow.


code:
import { workflow, node, trigger } from '@n8n/workflow-sdk';

const manualTrigger = trigger({
  type: 'n8n-nodes-base.manualTrigger',
  version: 1,
  config: { name: 'Manual Trigger' },
});

const setNode = node({
  type: 'n8n-nodes-base.set',
  version: 3.4,
  config: {
    name: 'node execution test',
    parameters: {
      mode: 'manual',
      assignments: {
        assignments: [
          { id: 'field1', name: 'message', type: 'string', value: 'Hello from node execution test' },
        ],
      },
    },
  },
});

export default workflow('id', 'Node Execution Test')
  .add(manualTrigger)
  .to(setNode);

description: Set fields in the node execution test node

errors: Final action "Set fields in the node execution test node" points to "node execution test" (n8n-nodes-base.set), but that is not a terminal action node. Point to the node that actually sends, posts, responds, creates, updates, notifies, logs, or upserts.


code:
import { workflow, node, trigger } from '@n8n/workflow-sdk';

const manualTrigger = trigger({
  type: 'n8n-nodes-base.manualTrigger',
  version: 1,
  config: { name: 'Manual Trigger' },
});

const setNode = node({
  type: 'n8n-nodes-base.set',
  version: 3.4,
  config: {
    name: 'node execution test',
    parameters: {
      mode: 'manual',
      assignments: {
        assignments: [
          { id: 'field1', name: 'example', type: 'string', value: 'Hello from node execution test' },
        ],
      },
    },
  },
});

export default workflow('id', 'Node Execution Test')
  .add(manualTrigger)
  .to(setNode);

description: Set and output fields via the Set node

errors: Final action "Set and output fields via the Set node" points to "node execution test" (n8n-nodes-base.set), but that is not a terminal action node. Point to the node that actually sends, posts, responds, creates, updates, notifies, logs, or upserts.


toolName: workflows

query: Node Execution Test


kind: tool-suspend

message: Update workflow "undefined" (ID: undefined)?

severity: warning


toolName: nodes

content:
/**
 * Manual Trigger Node - Version 1
 * Runs the flow on clicking a button in n8n
 */

export interface ManualTriggerV1Params {
}

interface ManualTriggerV1NodeBase {
  type: 'n8n-nodes-base.manualTrigger';
  version: 1;
  isTrigger: true;
}

export type ManualTriggerV1ParamsNode = ManualTriggerV1NodeBase & {
  config: NodeConfig<ManualTriggerV1Params>;
};

export type ManualTriggerV1Node = ManualTriggerV1ParamsNode;

builderHint: There can only be one manual trigger node per workflow

error: Node 'n8n-nodes-base.set' requires mode discriminator. Available modes: manual, raw.


content:
/**
 * Edit Fields (Set) Node - Version 3.4
 * Discriminator: mode=manual
 */

// Helper types for special n8n fields
/**
 * Assignment type determines how the value is interpreted.
 * - string: Direct string value or expression evaluating to string
 * - number: Direct number value or expression evaluating to number
 * - boolean: Direct boolean value or expression evaluating to boolean
 * - array: Expression that evaluates to an array, e.g. ={{ [1, 2, 3] }} or ={{ $json.items }}
 * - object: Expression that evaluates to a plain object (not an array — use the array type for arrays), e.g. ={{ { key: 'value' } }} or ={{ $json.data }}
 * - binary: Property name of binary data in the input item, or expression to access binary data from previous nodes, e.g. ={{ $('Node').item.binary.data }}
 */
type AssignmentType = 'string' | 'number' | 'boolean' | 'array' | 'object' | 'binary';
type AssignmentCollectionValue = { assignments: Array<{ id: string; name: string; value: unknown; type: AssignmentType }> };

/** Edit item fields one by one */
export type SetV34ManualParams = {
  mode: 'manual';
/**
 * Whether this item should be duplicated a set number of times
 * @default false
 */
    duplicateItem?: boolean | Expression<boolean>;
/**
 * How many times the item should be duplicated, mainly used for testing and debugging
 * @displayOptions.show { duplicateItem: [true] }
 * @default 0
 */
    duplicateCount?: number | Expression<number>;
/**
 * Fields to Set
 * @default {}
 */
    assignments?: AssignmentCollectionValue;
/**
 * Whether to pass to the output all the input fields (along with the fields set in 'Fields to Set')
 * @default false
 */
    includeOtherFields?: boolean | Expression<boolean>;
/**
 * How to select the fields you want to include in your output items
 * @displayOptions.hide { /includeOtherFields: [false] }
 * @default all
 */
    include?: 'all' | 'selected' | 'except' | Expression<string>;
/**
 * Comma-separated list of the field names you want to include in the output. You can drag the selected fields from the input panel.
 * @displayOptions.show { include: ["selected"], /includeOtherFields: [true] }
 */
    includeFields?: string | Expression<string>;
/**
 * Comma-separated list of the field names you want to exclude from the output. You can drag the selected fields from the input panel.
 * @displayOptions.show { include: ["except"], /includeOtherFields: [true] }
 */
    excludeFields?: string | Expression<string>;
  options?: {
    /** Whether binary data should be included if present in the input item
     * @default true
     */
    includeBinary?: boolean | Expression<boolean>;
    /** Whether binary data should be stripped from the input item. Only applies when "Include Other Input Fields" is enabled.
     * @displayOptions.show { /includeOtherFields: [true] }
     * @default true
     */
    stripBinary?: boolean | Expression<boolean>;
    /** Whether to ignore field type errors and apply a less strict type conversion
     * @default false
     */
    ignoreConversionErrors?: boolean | Expression<boolean>;
    /** By default, dot-notation is used in property names. This means that "a.b" will set the property "b" underneath "a" so { "a": { "b": value} }. If that is not intended this can be deactivated, it will then set { "a.b": value } instead.
     * @default true
     */
    dotNotation?: boolean | Expression<boolean>;
  };
};

export type SetV34ManualNode = {
  type: 'n8n-nodes-base.set';
  version: 3.4;
  config: NodeConfig<SetV34ManualParams>;
};


code:
import { workflow, node, trigger } from '@n8n/workflow-sdk';

const manualTrigger = trigger({
  type: 'n8n-nodes-base.manualTrigger',
  version: 1,
  config: { name: 'Manual Trigger' },
});

const setNode = node({
  type: 'n8n-nodes-base.set',
  version: 3.4,
  config: {
    name: 'node execution test',
    parameters: {
      mode: 'manual',
      assignments: {
        assignments: [
          { id: 'a1b2c3d4', name: 'example', type: 'string', value: 'Hello from node execution test' },
        ],
      },
    },
  },
});

export default workflow('id', 'Node Execution Test')
  .add(manualTrigger)
  .to(setNode);

errors: Final action contract missing: include `requiredFinalActions` with one entry for every user-requested terminal effect before saving a new main workflow. Point each entry at the actual enabled action node, not preprocessing or control flow.


code:
import { workflow, node, trigger } from '@n8n/workflow-sdk';

const manualTrigger = trigger({
  type: 'n8n-nodes-base.manualTrigger',
  version: 1,
  config: { name: 'Manual Trigger' },
});

const setNode = node({
  type: 'n8n-nodes-base.set',
  version: 3.4,
  config: {
    name: 'node execution test',
    parameters: {
      mode: 'manual',
      assignments: {
        assignments: [
          { id: 'a1b2c3d4', name: 'example', type: 'string', value: 'Hello from node execution test' },
        ],
      },
    },
  },
});

export default workflow('id', 'Node Execution Test')
  .add(manualTrigger)
  .to(setNode);

guidance: The workflow does not have a trigger the post-build verifier can exercise.