Chapter 9: n8n — Workflow Development
Chapter 9: n8n — Workflow Development
Last Updated: 2026-04-16
9.2 Key Concepts
| Concept | Description |
|---|---|
| Workflow | A directed graph of nodes that executes in response to a trigger |
| Trigger node | The first node; starts execution (webhook, schedule, manual) |
| Regular node | Processes data and passes it to the next node |
| Expression | JavaScript-like syntax for referencing data from previous nodes: {{ $json.field }} |
| Credential | Encrypted API key or auth token stored in n8n’s credential vault |
| Webhook | An HTTP endpoint hosted by n8n that triggers a workflow |
| Execution | A single run of a workflow, with input data and output data recorded |
9.3 The Workflow SDK Lifecycle
When creating or modifying workflows programmatically (via Cursor and the n8n MCP server), follow this exact lifecycle. Do not skip steps.
1. get_sdk_reference → Read SDK patterns and syntax
2. search_nodes → Find relevant node types by name/service
3. get_node_types → Get exact parameter definitions for selected nodes
4. validate_workflow → Check the workflow code for errors
5. create_workflow_from_code → Save the workflow to n8n
6. publish_workflow → Activate the workflow (make it live)
Warning: Skipping
get_node_typesbefore writing node parameters is the leading cause of invalid workflows. Parameter names are exact — guessing creates silent failures.
Step 1: Get SDK reference
Use the MCP tool get_sdk_reference to load current SDK patterns and syntax before writing any workflow code.
Step 2: Search for nodes
// Example: find nodes for Gmail and Slack
search_nodes(["gmail", "slack", "schedule trigger"])
// Also search for utility nodes
search_nodes(["set", "if", "merge", "code", "http request"])
Note the discriminator values returned (resource, operation, mode) — these are required in Step 3.
Step 3: Get node type definitions
// Use ALL node IDs from search, including discriminators
get_node_types(["n8n-nodes-base.gmail", "n8n-nodes-base.slack"])
This returns exact TypeScript parameter definitions. Use these verbatim — do not guess parameter names.
Step 4: Write and validate
Write the workflow code using SDK patterns, then validate:
validate_workflow(workflowCode)
Fix all errors reported. Re-validate until clean.
Step 5: Create
create_workflow_from_code(workflowCode, {
description: "One to two sentence description of what this workflow does."
})
Step 6: Publish (activate)
publish_workflow(workflowId)
Until a workflow is published, it exists in n8n but does not execute in response to triggers.
9.4 n8n Expression Syntax
Expressions reference data from the current execution context.
Reference data from a previous node
// Access a field from the previous node's output
{{ $json.fieldName }}
// Access a specific node's output by name
{{ $node["Node Name"].json.fieldName }}
// Access the current item's index
{{ $itemIndex }}
String operations
// Concatenate
{{ "Hello, " + $json.name }}
// Template literal style
{{ `Hello, ${$json.name}` }}
Conditional logic in expressions
// Ternary operator
{{ $json.status === "active" ? "Yes" : "No" }}
Access HTTP response data
// In an HTTP Request node's output
{{ $json.data.items[0].id }}
Tip: Use the Expression Editor in the n8n UI to test expressions against real execution data before embedding them in production workflows.
9.5 Credential Management
Credentials (API keys, OAuth tokens, database passwords) are stored encrypted in n8n’s credential vault, protected by N8N_ENCRYPTION_KEY.
Adding a new credential
- Open n8n UI at
http://localhost:5678. - Navigate to Credentials in the left sidebar.
- Click Add Credential.
- Select the credential type (e.g., “HTTP Header Auth”, “OpenAI API”).
- Enter the values and save.
The credential is now available to select in any node of the matching type.
Referencing credentials in SDK workflows
Credentials are referenced by name, not by value:
nodes: [{
type: "n8n-nodes-base.httpRequest",
credentials: {
httpHeaderAuth: { id: "credential-id", name: "My API Key" }
}
}]
Warning: API keys must never appear in workflow code, node parameters, or expressions. Always use the credential vault.
9.6 Webhook Design
n8n workflows triggered by HTTP webhooks follow these design principles:
Webhook URL structure
n8n generates webhook URLs in the format:
http://localhost:5678/webhook/<webhook-id>
For production use (calling from WordPress or external services), the webhook ID is stable — it does not change when the workflow is updated.
ITI webhook naming convention
All ITI product webhooks follow a consistent path structure:
/webhook/<product-name>
The full set of registered webhook paths (verified by test_n8n_workflows.py):
| Path | Product / Purpose |
|---|---|
/webhook/consulting-pipeline |
ITI Consulting Pipeline |
/webhook/proposal-evaluation |
C-Suite Proposal Evaluation |
/webhook/iti-marketing-suite |
ITI Marketing Suite |
/webhook/personal-advisor |
Personal Advisor Router |
/webhook/estate-advisor |
Estate Professional Advisor Router |
/webhook/travelplanner |
TravelPlanner |
/webhook/housing-insecure |
Housing Insecure (SafeHarbor) |
/webhook/career-coach |
Career Coach |
/webhook/expat-advisor |
Expat Advisor |
/webhook/executive-advisor |
Executive Advisor |
/webhook/backyard-gardener |
Backyard Gardener |
/webhook/scuba-gpt |
ScubaGPT |
/webhook/gd-chatbot |
GD Chatbot |
/webhook/patriot-university |
Patriot University |
/webhook/seo-assistant |
SEO Assistant |
/webhook/ai-news-cafe |
AI News Cafe |
/webhook/social-media |
Social Media Manager |
/webhook/email-marketing |
Email Marketing Manager |
/webhook/factchecker |
Factchecker |
/webhook/journey-mapper |
Journey Mapper |
/webhook/design-qa-review |
Design QA Review |
/webhook/design-system-audit |
Design System Audit |
/webhook/infra-health |
Infrastructure Health Monitor (GET) |
/webhook/patriot-health |
Patriot API Health Check (GET) |
Note: n8n workflows are stored in the n8n PostgreSQL database and Docker volume — not as JSON files in the Git repository. The pytest test suite at
ITI/infrastructure/n8n-dify/tests/test_n8n_workflows.pyserves as the contract for webhook path validation.
Webhook response patterns
Synchronous response — the workflow processes the request and returns a result within the HTTP connection timeout (typically 30–60 seconds):
Client → POST /webhook/... → [n8n processes] → Response with result
Asynchronous response — for long-running operations, the webhook immediately returns an acknowledgment, and the result is delivered via a callback URL or stored for polling:
Client → POST /webhook/... → {"status": "accepted", "jobId": "..."}
n8n processes in background
Client polls GET /webhook/iti-status/<jobId>
9.7 Common Node Types
| Node | Purpose | Key Parameters |
|---|---|---|
| Webhook | HTTP trigger | path, method, responseMode |
| HTTP Request | Call external APIs | url, method, authentication, body |
| Code | Run JavaScript | jsCode |
| Set | Transform/add fields | assignments (field name + value) |
| If | Conditional branching | conditions |
| Merge | Combine branches | mode (append, combine, etc.) |
| Schedule Trigger | Cron-based trigger | rule (cron expression) |
| Postgres | Query PostgreSQL | operation, query |
| AI Agent (LangChain) | Claude AI integration | model, systemMessage, tools |
9.8 Workflow Organization Best Practices
- One workflow per product action. Do not build monolithic workflows that handle multiple unrelated product requests.
- Name workflows clearly. Use the pattern:
[Product] - [Action](e.g., “Travel Planner – Generate Itinerary”). - Add descriptions. Every workflow should have a description explaining what it does, what triggers it, and what it returns.
- Use sticky notes in the canvas to document complex logic.
- Tag workflows by product or category for easy filtering.
- Test with manual triggers before activating the real trigger.
Previous: Chapter 8 — Nginx Reverse Proxy | Next: Chapter 10 — n8n Debugging & Operations
