Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/czlonkowski/n8n-skills/llms.txt

Use this file to discover all available pages before exploring further.

Node Configuration

Expert guidance for operation-aware node configuration with property dependencies.
Progressive disclosure principle: Start minimal, add complexity as needed. Use get_node({detail: "standard"}) first — it covers 95% of configuration needs with a ~1–2K token response. Only escalate to detail: "full" when standard detail is insufficient.

Core Concept: Operation-Aware Configuration

Not all fields are always required. Which fields are required depends on the operation selected.
// Slack: operation = "post" requires channel + text
{
  resource: "message",
  operation: "post",
  channel: "#general",   // Required for post
  text: "Hello!"         // Required for post
}

// Slack: operation = "update" requires messageId, NOT channel
{
  resource: "message",
  operation: "update",
  messageId: "123",      // Required for update (different!)
  text: "Updated!"
  // channel NOT required for update
}

// Slack: operation = "create" (channel) requires name, NOT text
{
  resource: "channel",
  operation: "create",
  name: "new-channel",   // Required for channel create
  isPrivate: false
  // text NOT required at all for this operation
}
Key insight: Always re-check get_node when changing the resource or operation. Fields change.

Property Dependencies (displayOptions)

Fields appear and disappear based on the values of other fields. This is controlled by displayOptions rules.
// Example: body field in HTTP Request
{
  name: "body",
  displayOptions: {
    show: {
      sendBody: [true],
      method: ["POST", "PUT", "PATCH"]
    }
  }
}
// Translation: "body" only appears when sendBody=true AND method is POST/PUT/PATCH

Common Dependency Chains

// Full dependency chain:
// method="POST" → sendBody available
// sendBody=true → body required
// body.contentType="json" → body.content expected as JSON

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

{
  method: "GET",
  url: "https://api.example.com/users",
  authentication: "predefinedCredentialType",
  nodeCredentialType: "httpHeaderAuth",
  sendQuery: true,
  queryParameters: {
    parameters: [
      {name: "limit", value: "100"},
      {name: "offset", value: "0"}
    ]
  }
}
// Binary operator (equals, contains, etc.) → needs value1 + value2
// Auto-sanitization removes singleValue from binary operators

{
  conditions: {
    string: [
      {
        value1: "={{$json.status}}",
        operation: "equals",
        value2: "active"    // Binary: needs both value1 AND value2
      }
    ]
  }
}
// Unary operator (isEmpty, isNotEmpty) → needs only value1
// Auto-sanitization adds singleValue: true automatically

{
  conditions: {
    string: [
      {
        value1: "={{$json.email}}",
        operation: "isEmpty"
        // singleValue: true  ← added automatically by auto-sanitization
        // No value2 — unary operator checks single value
      }
    ]
  }
}
// executeQuery → query required
{
  operation: "executeQuery",
  query: "SELECT * FROM users WHERE id = $1",
  additionalFields: {queryParams: "={{$json.userId}}"}
}

// insert → table + columns required
{
  operation: "insert",
  table: "users",
  columns: "id,name,email"
}

// update → table + updateKey required
{
  operation: "update",
  table: "users",
  updateKey: "id"
}

get_node Detail Level Decision Tree

Starting a new node configuration?
  └→ get_node({detail: "standard"})          ← Always start here
        |
        Does standard detail have what you need?
        ├ YES → Configure with it
        └ NO  → Looking for a specific field name?
                  ├ YES → get_node({mode: "search_properties", propertyQuery: "auth"})
                  └ NO  → get_node({detail: "full"})           ← Last resort only
Detail LevelTokensUse When
minimal~200Quick metadata only
standard~1–2KDefault — covers 95% of needs
full~3–8KComplex debugging; complete schema

Configuration Workflow

1

Identify node type and operation

What service are you integrating? What action do you want to perform?
// Goal: Post a message to Slack
// Node: nodes-base.slack
// Resource: message
// Operation: post
2

Get node info (standard detail)

get_node({
  nodeType: "nodes-base.slack",
  includeExamples: true  // Get real template configs
})
// Returns: operations, required fields, example configurations
3

Build minimal configuration

Start with only the required fields:
{
  resource: "message",
  operation: "post",
  channel: "#general",
  text: "Hello!"
}
4

Validate

validate_node({
  nodeType: "nodes-base.slack",
  config,
  profile: "runtime"
})
// Follow validation loop: fix errors, validate again (2–3 cycles is normal)
5

Search for specific properties if stuck

get_node({
  nodeType: "nodes-base.httpRequest",
  mode: "search_properties",
  propertyQuery: "auth"  // Finds authentication-related properties
})
6

Add optional fields and validate again

Only add fields you actually need. Avoid over-configuring upfront.

AI Connection Types

When building AI workflows, connections use special sourceOutput types:
Connection TypesourceOutput ValueExample Node
Language Modelai_languageModelOpenAI Chat Model
Toolai_toolHTTP Request Tool, Code Tool
Memoryai_memoryWindow Buffer Memory
Output Parserai_outputParserStructured Output Parser
Embeddingai_embeddingOpenAI Embeddings
Vector Storeai_vectorStorePinecone, Qdrant
Documentai_documentDefault Data Loader
Text Splitterai_textSplitterRecursive Character Splitter
// Connect a language model to the AI Agent
{
  type: "addConnection",
  source: "OpenAI Chat Model",
  target: "AI Agent",
  sourceOutput: "ai_languageModel"
}

// Connect multiple tools
{
  type: "addConnection",
  source: "HTTP Request Tool",
  target: "AI Agent",
  sourceOutput: "ai_tool"
}

Common Node Configuration Patterns

Examples: Slack, Google Sheets, Airtable, NotionStructure: resource + operation determines all required fields.
// Pattern
{
  resource: "<entity>",    // What thing (message, channel, row...)
  operation: "<action>",   // What to do (post, create, update...)
  // ... operation-specific fields
}

// Always re-check get_node when changing resource or operation!

Configuration Anti-Patterns

Over-configuring upfront

// ❌ Don't add every optional field
{
  method: "GET",
  url: "...",
  sendQuery: false,
  sendHeaders: false,
  sendBody: false,
  timeout: 10000,
  // ... 20 more optional fields
}

Start minimal instead

// ✅ Start with only required fields
{
  method: "GET",
  url: "...",
  authentication: "none"
}
// Add more only when validation asks for it

Copy configs without checking

// ❌ Copy Slack post config for update
{
  resource: "message",
  operation: "update",  // Changed
  channel: "#general",  // Wrong field for update!
  text: "Updated"
}

Check requirements when switching

// ✅ Check get_node after changing operation
get_node({nodeType: "nodes-base.slack"})
// See that update needs messageId, not channel
{
  resource: "message",
  operation: "update",
  messageId: "12345678",  // Correct!
  text: "Updated"
}

Best Practices

PracticeWhy
Start with get_node({detail: "standard"})Covers 95% of needs at 1–2K tokens
Validate iteratively (2–3 cycles is normal)Validation reveals missing dependencies
Use search_properties mode when stuckFinds fields by name efficiently
Respect operation contextDifferent operations ← different requirements
Trust auto-sanitizationDon’t manually manage singleValue
Never jump straight to detail: "full"Try standard and search_properties first

Build docs developers (and LLMs) love