All skills
wilkomarketing avatar

/n8n-node-configuration

@0d187d8

Operation-aware node configuration guidance. Use when configuring nodes, understanding property dependencies, determining required fields, choosing between get_node detail levels, or learning common configuration patterns by node type. Always use this skill when setting up node parameters — it explains which fields are required for each operation, how displayOptions control field visibility, and when to use patchNodeField for surgical edits vs full node updates.

Use this Skill: https://skilld.dev/gh/wilkomarketing/antigravity-n8n-skills/n8n-node-configuration

This session only. Nothing lands on disk.

OPERATION_PATTERNS.md

≈6.7k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Operation Patterns Guide

Common node configuration patterns organized by node type and operation.


Overview

Purpose: Quick reference for common node configurations

Coverage: Top 20 most-used nodes from 525 available

Pattern format:

  • Minimal valid configuration
  • Common options
  • Real-world examples
  • Gotchas and tips

HTTP & API Nodes

HTTP Request (nodes-base.httpRequest)

Most versatile node for HTTP operations

GET Request

Minimal:

{
  "method": "GET",
  "url": "https://api.example.com/users",
  "authentication": "none"
}

With query parameters:

{
  "method": "GET",
  "url": "https://api.example.com/users",
  "authentication": "none",
  "sendQuery": true,
  "queryParameters": {
    "parameters": [
      {
        "name": "limit",
        "value": "100"
      },
      {
        "name": "offset",
        "value": "={{$json.offset}}"
      }
    ]
  }
}

With authentication:

{
  "method": "GET",
  "url": "https://api.example.com/users",
  "authentication": "predefinedCredentialType",
  "nodeCredentialType": "httpHeaderAuth"
}
POST with JSON

Minimal:

{
  "method": "POST",
  "url": "https://api.example.com/users",
  "authentication": "none",
  "sendBody": true,
  "body": {
    "contentType": "json",
    "content": {
      "name": "John Doe",
      "email": "john@example.com"
    }
  }
}

With expressions:

{
  "method": "POST",
  "url": "https://api.example.com/users",
  "authentication": "none",
  "sendBody": true,
  "body": {
    "contentType": "json",
    "content": {
      "name": "={{$json.name}}",
      "email": "={{$json.email}}",
      "metadata": {
        "source": "n8n",
        "timestamp": "={{$now.toISO()}}"
      }
    }
  }
}

Gotcha: Remember sendBody: true for POST/PUT/PATCH!

PUT/PATCH Request

Pattern: Same as POST, but method changes

{
  "method": "PUT",  // or "PATCH"
  "url": "https://api.example.com/users/123",
  "authentication": "none",
  "sendBody": true,
  "body": {
    "contentType": "json",
    "content": {
      "name": "Updated Name"
    }
  }
}
DELETE Request

Minimal (no body):

{
  "method": "DELETE",
  "url": "https://api.example.com/users/123",
  "authentication": "none"
}

With body (some APIs allow):

{
  "method": "DELETE",
  "url": "https://api.example.com/users",
  "authentication": "none",
  "sendBody": true,
  "body": {
    "contentType": "json",
    "content": {
      "ids": ["123", "456"]
    }
  }
}

Webhook (nodes-base.webhook)

Most common trigger - 813 searches!

Basic Webhook

Minimal:

{
  "path": "my-webhook",
  "httpMethod": "POST",
  "responseMode": "onReceived"
}

Gotcha: Webhook data is under $json.body, not $json!

// ❌ Wrong
{
  "text": "={{$json.email}}"
}

// ✅ Correct
{
  "text": "={{$json.body.email}}"
}
Webhook with Authentication

Header auth:

{
  "path": "secure-webhook",
  "httpMethod": "POST",
  "responseMode": "onReceived",
  "authentication": "headerAuth",
  "options": {
    "responseCode": 200,
    "responseData": "{\n  \"success\": true\n}"
  }
}
Webhook Returning Data

Custom response:

{
  "path": "my-webhook",
  "httpMethod": "POST",
  "responseMode": "lastNode",  // Return data from last node
  "options": {
    "responseCode": 201,
    "responseHeaders": {
      "entries": [
        {
          "name": "Content-Type",
          "value": "application/json"
        }
      ]
    }
  }
}

Communication Nodes

Slack (nodes-base.slack)

Popular choice for AI agent workflows

Post Message

Minimal:

{
  "resource": "message",
  "operation": "post",
  "channel": "#general",
  "text": "Hello from n8n!"
}

With dynamic content:

{
  "resource": "message",
  "operation": "post",
  "channel": "={{$json.channel}}",
  "text": "New user: {{$json.name}} ({{$json.email}})"
}

With attachments:

{
  "resource": "message",
  "operation": "post",
  "channel": "#alerts",
  "text": "Error Alert",
  "attachments": [
    {
      "color": "#ff0000",
      "fields": [
        {
          "title": "Error Type",
          "value": "={{$json.errorType}}"
        },
        {
          "title": "Timestamp",
          "value": "={{$now.toLocaleString()}}"
        }
      ]
    }
  ]
}

Gotcha: Channel must start with # for public channels or be a channel ID!

Update Message

Minimal:

{
  "resource": "message",
  "operation": "update",
  "messageId": "1234567890.123456",  // From previous message post
  "text": "Updated message content"
}

Note: messageId required, channel optional (can be inferred)

Create Channel

Minimal:

{
  "resource": "channel",
  "operation": "create",
  "name": "new-project-channel",  // Lowercase, no spaces
  "isPrivate": false
}

Gotcha: Channel name must be lowercase, no spaces, 1-80 chars!


Gmail (nodes-base.gmail)

Popular for email automation

Send Email

Minimal:

{
  "resource": "message",
  "operation": "send",
  "to": "user@example.com",
  "subject": "Hello from n8n",
  "message": "This is the email body"
}

With dynamic content:

{
  "resource": "message",
  "operation": "send",
  "to": "={{$json.email}}",
  "subject": "Order Confirmation #{{$json.orderId}}",
  "message": "Dear {{$json.name}},\n\nYour order has been confirmed.\n\nThank you!",
  "options": {
    "ccList": "admin@example.com",
    "replyTo": "support@example.com"
  }
}
Get Email

Minimal:

{
  "resource": "message",
  "operation": "getAll",
  "returnAll": false,
  "limit": 10
}

With filters:

{
  "resource": "message",
  "operation": "getAll",
  "returnAll": false,
  "limit": 50,
  "filters": {
    "q": "is:unread from:important@example.com",
    "labelIds": ["INBOX"]
  }
}

Database Nodes

Postgres (nodes-base.postgres)

Database operations - 456 templates

Execute Query

Minimal (SELECT):

{
  "operation": "executeQuery",
  "query": "SELECT * FROM users WHERE active = true LIMIT 100"
}

With parameters (SQL injection prevention):

{
  "operation": "executeQuery",
  "query": "SELECT * FROM users WHERE email = $1 AND active = $2",
  "additionalFields": {
    "mode": "list",
    "queryParameters": "user@example.com,true"
  }
}

Gotcha: ALWAYS use parameterized queries for user input!

// ❌ BAD - SQL injection risk!
{
  "query": "SELECT * FROM users WHERE email = '{{$json.email}}'"
}

// ✅ GOOD - Parameterized
{
  "query": "SELECT * FROM users WHERE email = $1",
  "additionalFields": {
    "mode": "list",
    "queryParameters": "={{$json.email}}"
  }
}
Insert

Minimal:

{
  "operation": "insert",
  "table": "users",
  "columns": "name,email,created_at",
  "additionalFields": {
    "mode": "list",
    "queryParameters": "John Doe,john@example.com,NOW()"
  }
}

With expressions:

{
  "operation": "insert",
  "table": "users",
  "columns": "name,email,metadata",
  "additionalFields": {
    "mode": "list",
    "queryParameters": "={{$json.name}},={{$json.email}},{{JSON.stringify($json)}}"
  }
}
Update

Minimal:

{
  "operation": "update",
  "table": "users",
  "updateKey": "id",
  "columns": "name,email",
  "additionalFields": {
    "mode": "list",
    "queryParameters": "={{$json.id}},Updated Name,newemail@example.com"
  }
}

Storage Nodes

Data Table (nodes-base.dataTable)

Persistent, structured per-project key-value storage — an in-n8n alternative to external SQL for small state like buffers, de-dup sets, counters, or lookup caches. Do not confuse with the MCP tool n8n_manage_datatable — that tool manages tables from outside n8n (create/list/delete tables and rows from Claude). The nodes-base.dataTable node below is what you drop into a workflow to read/write rows during execution.

Verified end-to-end against live n8n on 2026-04-08 with a 15-node assertion harness exercising every claim below: insert returning rows with system id, like operator, returnAll, allConditions AND-of-multiple-filters, isTrue unary boolean condition, upsert with matchingColumns (no duplicates), defineBelow resourceMapper writing values, deleteRows (the reserved-word workaround) returning affected rows, and dataTableId resourceLocator in mode: "name". All 6 assertions passed.

Node shape:

  • type: n8n-nodes-base.dataTable
  • typeVersion: 1.1 (also 1)
  • resource: "row" or "table"
  • Row operation values — note the reserved-word workaround on delete:
    • "insert" — Insert row
    • "get" — Get row(s)
    • "update" — Update row(s) matching conditions
    • "upsert" — Update if match, else insert
    • "deleteRows" — Delete row(s) matching conditions (not "delete" — delete is a JS reserved word, the node uses deleteRows)
    • "rowExists" — Pass through input if at least one match
    • "rowNotExists" — Pass through input if zero matches

Table selection — always a resourceLocator parameter named dataTableId:

"dataTableId": {
  "__rl": true,
  "mode": "list",      // or "name" or "id"
  "value": "dt_xyz123" // or the name when mode=name
}

Row mapping (insert/update/upsert) — resourceMapper parameter named columns:

"columns": {
  "mappingMode": "defineBelow",    // or "autoMapInputData"
  "value": {
    "user_email": "={{ $json.email }}",
    "score": "={{ $json.score }}",
    "active": true
  },
  "matchingColumns": [],           // filled for update/upsert match keys
  "schema": [],                    // n8n re-loads at runtime; safe to leave empty
  "attemptToConvertTypes": false,
  "convertFieldsToString": false
}

In autoMapInputData mode, incoming item field names must match column names exactly and value is ignored.

Filtering (get/update/upsert/deleteRows/rowExists/rowNotExists):

"matchType": "anyCondition",   // or "allConditions"
"filters": {
  "conditions": [
    { "keyName": "user_email", "condition": "eq",        "keyValue": "a@b.com" },
    { "keyName": "score",      "condition": "gte",       "keyValue": 10 },
    { "keyName": "archived",   "condition": "isNotEmpty"  }
  ]
}

Supported condition values: eq, neq, like, ilike, gt, gte, lt, lte, isEmpty, isNotEmpty, isTrue, isFalse. The last four are unary — omit keyValue.

Get options: returnAll: true bypasses the default 50-row limit. options can include ordering.

Insert option: options.optimizeBulk: true skips returning inserted rows for ~5x bulk throughput. Do not use when downstream nodes need the inserted row ids.

Mutating ops (update/upsert/deleteRows) accept options.dryRun: true — returns the rows that would be affected with before/after states, without writing.

Minimal Insert
{
  "resource": "row",
  "operation": "insert",
  "dataTableId": { "__rl": true, "mode": "name", "value": "email_buffer" },
  "columns": {
    "mappingMode": "defineBelow",
    "value": {
      "from_name": "={{ $json.from_name }}",
      "subject":   "={{ $json.subject }}"
    },
    "matchingColumns": [],
    "schema": []
  },
  "options": {}
}
Get All Rows

Get requires at least one condition — a bare "return everything" isn't allowed. Trick: filter on the always-populated system id column with isNotEmpty.

{
  "resource": "row",
  "operation": "get",
  "dataTableId": { "__rl": true, "mode": "name", "value": "email_buffer" },
  "matchType": "anyCondition",
  "filters": {
    "conditions": [ { "keyName": "id", "condition": "isNotEmpty" } ]
  },
  "returnAll": true,
  "options": {}
}
Delete All Rows

Same id isNotEmpty trick — a delete without conditions throws At least one condition is required.

{
  "resource": "row",
  "operation": "deleteRows",
  "dataTableId": { "__rl": true, "mode": "name", "value": "email_buffer" },
  "matchType": "anyCondition",
  "filters": {
    "conditions": [ { "keyName": "id", "condition": "isNotEmpty" } ]
  },
  "options": {}
}
Upsert by Natural Key
{
  "resource": "row",
  "operation": "upsert",
  "dataTableId": { "__rl": true, "mode": "name", "value": "user_scores" },
  "matchType": "allConditions",
  "filters": {
    "conditions": [ { "keyName": "user_email", "condition": "eq", "keyValue": "={{ $json.email }}" } ]
  },
  "columns": {
    "mappingMode": "defineBelow",
    "value": {
      "user_email": "={{ $json.email }}",
      "score":      "={{ $json.score }}"
    },
    "matchingColumns": ["user_email"],
    "schema": []
  },
  "options": {}
}

System columns: every table auto-has id plus created/updated timestamps — you don't declare these and can't write to them. They're usable in filters.

When to reach for Data Table vs alternatives:

Need Use
Small per-workflow scratch state, single workflow, not durable across workflow edits $getWorkflowStaticData('global') inside a Code node
Persistent structured state, queryable by column, survives workflow rename/edit/deactivation, shared across multiple workflows in the same project Data Table node
Large datasets (>>10k rows), complex joins, transactions, FKs, indexes External Postgres/MySQL
Unstructured key-value cache with TTL Redis

Gotchas:

  • Scope is per project — Data Tables are not shared across n8n projects. Move a workflow to another project and its Data Table references break.
  • Filter operator eq on a column that doesn't exist in the table returns a validation error at execution, not at import — always verify column names match the live table.
  • Expression values in columns.value are evaluated per input item. If the upstream node emits N items, Insert runs N times unless you explicitly use optimizeBulk.
  • deleteRows is the operation value, not delete. Using delete will import but fail at execution with "unknown operation".
  • Race condition in buffer/flush patterns: rows added between Get and deleteRows will be wiped without being read. For at-least-once semantics, delete by specific row ids returned from Get instead of by a broad filter.
  • Zero-match halts the chain. When get, deleteRows, update, or upsert matches 0 rows, the node emits 0 output items and n8n stops the downstream branch silently — no error, just nothing happens. This bites cleanup steps in idempotent test/setup workflows where the table starts empty. Fix: set node-level "alwaysOutputData": true (sibling of parameters/type, NOT inside parameters) on any DT node that may legitimately match nothing. The node will then emit a single empty item and the chain continues.
  • DT operations execute once per input item. A Get node fed 3 input items will run 3 separate queries and concatenate the results — usually not what you want. Insert a "collapse" Code node (return [{ json: {} }];) between any multi-item-emitting node and a downstream DT op that should run exactly once.
  • DT nodes do not natively offer a "run once for all items" mode like the Code node — the collapse-node pattern is currently the only clean workaround.

Data Transformation Nodes

Set (nodes-base.set)

Most used transformation - 68% of workflows!

Set Fixed Values

Minimal:

{
  "mode": "manual",
  "duplicateItem": false,
  "assignments": {
    "assignments": [
      {
        "name": "status",
        "value": "active",
        "type": "string"
      },
      {
        "name": "count",
        "value": 100,
        "type": "number"
      }
    ]
  }
}
Set from Input Data

Mapping data:

{
  "mode": "manual",
  "duplicateItem": false,
  "assignments": {
    "assignments": [
      {
        "name": "fullName",
        "value": "={{$json.firstName}} {{$json.lastName}}",
        "type": "string"
      },
      {
        "name": "email",
        "value": "={{$json.email.toLowerCase()}}",
        "type": "string"
      },
      {
        "name": "timestamp",
        "value": "={{$now.toISO()}}",
        "type": "string"
      }
    ]
  }
}

Gotcha: Use correct type for each field!

// ❌ Wrong type
{
  "name": "age",
  "value": "25",      // String
  "type": "string"    // Will be string "25"
}

// ✅ Correct type
{
  "name": "age",
  "value": 25,        // Number
  "type": "number"    // Will be number 25
}

Code (nodes-base.code)

JavaScript execution - 42% of workflows

Simple Transformation

Minimal:

{
  "mode": "runOnceForAllItems",
  "jsCode": "return $input.all().map(item => ({\n  json: {\n    name: item.json.name.toUpperCase(),\n    email: item.json.email\n  }\n}));"
}

Per-item processing:

{
  "mode": "runOnceForEachItem",
  "jsCode": "// Process each item\nconst data = $input.item.json;\n\nreturn {\n  json: {\n    fullName: `${data.firstName} ${data.lastName}`,\n    email: data.email.toLowerCase(),\n    timestamp: new Date().toISOString()\n  }\n};"
}

Gotcha: In Code nodes, use $input.item.json or $input.all(), NOT {{...}}!

// ❌ Wrong - expressions don't work in Code nodes
{
  "jsCode": "const name = '={{$json.name}}';"
}

// ✅ Correct - direct access
{
  "jsCode": "const name = $input.item.json.name;"
}

Conditional Nodes

IF (nodes-base.if)

Conditional logic - 38% of workflows

String Comparison

Equals (binary):

{
  "conditions": {
    "string": [
      {
        "value1": "={{$json.status}}",
        "operation": "equals",
        "value2": "active"
      }
    ]
  }
}

Contains (binary):

{
  "conditions": {
    "string": [
      {
        "value1": "={{$json.email}}",
        "operation": "contains",
        "value2": "@example.com"
      }
    ]
  }
}

isEmpty (unary):

{
  "conditions": {
    "string": [
      {
        "value1": "={{$json.email}}",
        "operation": "isEmpty"
        // No value2 - unary operator
        // singleValue: true added by auto-sanitization
      }
    ]
  }
}

Gotcha: Unary operators (isEmpty, isNotEmpty) don't need value2!

Number Comparison

Greater than:

{
  "conditions": {
    "number": [
      {
        "value1": "={{$json.age}}",
        "operation": "larger",
        "value2": 18
      }
    ]
  }
}
Boolean Comparison

Is true:

{
  "conditions": {
    "boolean": [
      {
        "value1": "={{$json.isActive}}",
        "operation": "true"
        // Unary - no value2
      }
    ]
  }
}
Multiple Conditions (AND)

All must match:

{
  "conditions": {
    "string": [
      {
        "value1": "={{$json.status}}",
        "operation": "equals",
        "value2": "active"
      }
    ],
    "number": [
      {
        "value1": "={{$json.age}}",
        "operation": "larger",
        "value2": 18
      }
    ]
  },
  "combineOperation": "all"  // AND logic
}
Multiple Conditions (OR)

Any can match:

{
  "conditions": {
    "string": [
      {
        "value1": "={{$json.status}}",
        "operation": "equals",
        "value2": "active"
      },
      {
        "value1": "={{$json.status}}",
        "operation": "equals",
        "value2": "pending"
      }
    ]
  },
  "combineOperation": "any"  // OR logic
}

Switch (nodes-base.switch)

Multi-way routing - 18% of workflows

Basic Switch

Minimal:

{
  "mode": "rules",
  "rules": {
    "rules": [
      {
        "conditions": {
          "string": [
            {
              "value1": "={{$json.status}}",
              "operation": "equals",
              "value2": "active"
            }
          ]
        }
      },
      {
        "conditions": {
          "string": [
            {
              "value1": "={{$json.status}}",
              "operation": "equals",
              "value2": "pending"
            }
          ]
        }
      }
    ]
  },
  "fallbackOutput": "extra"  // Catch-all for non-matching
}

Gotcha: Number of rules must match number of outputs!


AI Nodes

OpenAI (nodes-langchain.openAi)

AI operations - 234 templates

Chat Completion

Minimal:

{
  "resource": "chat",
  "operation": "complete",
  "messages": {
    "values": [
      {
        "role": "user",
        "content": "={{$json.prompt}}"
      }
    ]
  }
}

With system prompt:

{
  "resource": "chat",
  "operation": "complete",
  "messages": {
    "values": [
      {
        "role": "system",
        "content": "You are a helpful assistant specialized in customer support."
      },
      {
        "role": "user",
        "content": "={{$json.userMessage}}"
      }
    ]
  },
  "options": {
    "temperature": 0.7,
    "maxTokens": 500
  }
}

Schedule Nodes

Schedule Trigger (nodes-base.scheduleTrigger)

Time-based workflows - 28% have schedule triggers

Daily at Specific Time

Minimal:

{
  "rule": {
    "interval": [
      {
        "field": "hours",
        "hoursInterval": 24
      }
    ],
    "hour": 9,
    "minute": 0,
    "timezone": "America/New_York"
  }
}

Gotcha: Always set timezone explicitly!

// ❌ Bad - uses server timezone
{
  "rule": {
    "interval": [...]
  }
}

// ✅ Good - explicit timezone
{
  "rule": {
    "interval": [...],
    "timezone": "America/New_York"
  }
}
Every N Minutes

Minimal:

{
  "rule": {
    "interval": [
      {
        "field": "minutes",
        "minutesInterval": 15
      }
    ]
  }
}
Cron Expression

Advanced scheduling:

{
  "mode": "cron",
  "cronExpression": "0 */2 * * *",  // Every 2 hours
  "timezone": "America/New_York"
}

Summary

Key Patterns by Category:

Category Most Common Key Gotcha
HTTP/API GET, POST JSON Remember sendBody: true
Webhooks POST receiver Data under $json.body
Communication Slack post Channel format (#name)
Database SELECT with params Use parameterized queries
Transform Set assignments Correct type per field
Conditional IF string equals Unary vs binary operators
AI OpenAI chat System + user messages
Schedule Daily at time Set timezone explicitly

Configuration Approach:

  1. Use patterns as starting point
  2. Adapt to your use case
  3. Validate configuration
  4. Iterate based on errors
  5. Deploy when valid

Related Files:


Worked Example: Configuring HTTP Request Step by Step

A full validate-driven walkthrough of building a POST JSON request from minimal config, letting validation surface each required field.

Step 1: Identify what you need

// Goal: POST JSON to API

Step 2: Get node info

const info = get_node({
  nodeType: "nodes-base.httpRequest"
});

// Returns: method, url, sendBody, body, authentication required/optional

Step 3: Minimal config

{
  "method": "POST",
  "url": "https://api.example.com/create",
  "authentication": "none"
}

Step 4: Validate

validate_node({
  nodeType: "nodes-base.httpRequest",
  config,
  profile: "runtime"
});
// → Error: "sendBody required for POST"

Step 5: Add required field

{
  "method": "POST",
  "url": "https://api.example.com/create",
  "authentication": "none",
  "sendBody": true
}

Step 6: Validate again

validate_node({...});
// → Error: "body required when sendBody=true"

Step 7: Complete configuration

{
  "method": "POST",
  "url": "https://api.example.com/create",
  "authentication": "none",
  "sendBody": true,
  "body": {
    "contentType": "json",
    "content": {
      "name": "={{$json.name}}",
      "email": "={{$json.email}}"
    }
  }
}

Step 8: Final validation

validate_node({...});
// → Valid! ✅

Operation-Specific Configuration Examples

Concrete minimal configs showing how required fields differ by resource + operation.

Slack Node Examples

Post Message
{
  "resource": "message",
  "operation": "post",
  "channel": "#general",      // Required
  "text": "Hello!",           // Required
  "attachments": [],          // Optional
  "blocks": []                // Optional
}
Update Message
{
  "resource": "message",
  "operation": "update",
  "messageId": "1234567890",  // Required (different from post!)
  "text": "Updated!",         // Required
  "channel": "#general"       // Optional (can be inferred)
}
Create Channel
{
  "resource": "channel",
  "operation": "create",
  "name": "new-channel",      // Required
  "isPrivate": false          // Optional
  // Note: text NOT required for this operation
}

HTTP Request Node Examples

GET Request
{
  "method": "GET",
  "url": "https://api.example.com/users",
  "authentication": "predefinedCredentialType",
  "nodeCredentialType": "httpHeaderAuth",
  "sendQuery": true,                    // Optional
  "queryParameters": {                  // Shows when sendQuery=true
    "parameters": [
      {
        "name": "limit",
        "value": "100"
      }
    ]
  }
}
POST with JSON
{
  "method": "POST",
  "url": "https://api.example.com/users",
  "authentication": "none",
  "sendBody": true,                     // Required for POST
  "body": {                             // Required when sendBody=true
    "contentType": "json",
    "content": {
      "name": "John Doe",
      "email": "john@example.com"
    }
  }
}

IF Node Examples

String Comparison (Binary)
{
  "conditions": {
    "string": [
      {
        "value1": "={{$json.status}}",
        "operation": "equals",
        "value2": "active"              // Binary: needs value2
      }
    ]
  }
}
Empty Check (Unary)
{
  "conditions": {
    "string": [
      {
        "value1": "={{$json.email}}",
        "operation": "isEmpty",
        // No value2 - unary operator
        "singleValue": true             // Auto-added by sanitization
      }
    ]
  }
}

Source: SKILL.md on GitHub

No alerts11d4 checks · Risk SAFE
  • Gen Agent Trust Hub11d

    No security issues detected. The skill provides legitimate documentation and guidance for an AI agent to configure n8n nodes according to best practices. It correctly emphasizes security measures like using parameterized SQL queries to prevent injection attacks.

  • Socket11d

    No alerts

  • Snyk11d

    Risk: LOW · No issues

  • Runlayer6mo

    4 files scanned · No issues

Signed by skilld at 0d187d8. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub last month.

Steadyupdated 3 months ago

README badge

README badge for wilkomarketing/antigravity-n8n-skills/n8n-node-configuration