How to Build an AI Agent That Writes SEO Articles from Job Postings with n8n (Free Template)

How to Build an AI Agent That Writes SEO Articles from Job Postings with n8n (Free Template)

Creating high-quality technical content at scale is expensive and time-consuming. Manual article writing takes 3-5 hours per piece, and maintaining consistency across multiple writers is nearly impossible. This n8n workflow solves that problem by automating the entire process—from job posting input to publication-ready SEO article output—using Claude AI's advanced language capabilities.

You'll learn how to build an AI agent that takes job postings, demo scripts, and n8n workflow JSONs as inputs, then generates comprehensive technical articles following a strict editorial structure. The complete n8n workflow JSON template is available at the bottom of this article.

The Problem: Manual Technical Writing Doesn't Scale

Technical content creation faces three critical bottlenecks that prevent businesses from scaling their content operations effectively.

Current challenges:

  • Writers spend 3-5 hours per article researching, structuring, and writing technical content
  • Maintaining consistent tone, structure, and technical accuracy across multiple writers is nearly impossible
  • Subject matter experts lack time to document their knowledge in educational formats
  • Content agencies charge $500-2000 per technical article with 2-week turnaround times

Business impact:

  • Time spent: 15-25 hours per week for a 5-article content calendar
  • Cost: $2,500-10,000 monthly for outsourced technical writing
  • Opportunity cost: Technical experts spending time writing instead of building

Manual processes also struggle with citation-worthy content. Articles need tables, specific technical details, and structured information that AI can retrieve—but human writers often skip these elements under deadline pressure.

The Solution Overview

This n8n workflow creates an AI-powered content generation system that converts raw technical inputs into publication-ready articles. The agent uses Claude 3.5 Sonnet with a 200,000 token context window to process job postings, n8n workflow JSONs, and demo scripts simultaneously.

The system implements a structured prompt that enforces editorial standards, ensuring every article follows a consistent 14-section format with tables, code blocks, and technical specifications. The workflow outputs clean markdown with frontmatter, ready for immediate publication in static site generators or CMS platforms.

What You'll Build

This workflow automates the complete article creation pipeline with specific capabilities designed for technical content at scale.

Component Technology Purpose
Input Processing Manual Trigger Node Accepts job posting, workflow JSON, and demo script
AI Generation Claude AI (Anthropic) Generates 1,200-word structured articles
Prompt Engineering System Prompt (200K tokens) Enforces 14-section editorial structure
Output Formatting Markdown with Frontmatter Publication-ready content with SEO metadata
Quality Control JSON Schema Validation Ensures consistent article structure

Key capabilities:

  • Processes multiple input types: job descriptions, technical workflows, and video scripts
  • Generates articles with exact technical specifications from n8n workflow JSON
  • Creates citation-worthy content with tables, code blocks, and structured data
  • Maintains authoritative tone with short sentences and active voice
  • Outputs SEO-optimized content with title and meta description
  • Includes 14 required H2 sections for comprehensive coverage
  • Produces 1,200-word articles in 30-45 seconds

Prerequisites

Before starting, ensure you have:

  • n8n instance (cloud or self-hosted version 1.0+)
  • Anthropic API account with Claude access
  • API key with sufficient credits ($5 minimum recommended)
  • Basic understanding of prompt engineering concepts
  • Text editor for customizing the system prompt
  • Markdown preview tool for reviewing output

Technical requirements:

  • n8n version 1.0 or higher (for updated AI nodes)
  • Anthropic API access to Claude 3.5 Sonnet model
  • Minimum 200,000 token context window support

Step 1: Set Up the Manual Trigger and Input Structure

The workflow begins with a Manual Trigger node that accepts three distinct text inputs: the job posting, n8n workflow JSON, and demo script or voiceover.

Configure the Manual Trigger node:

  1. Add a Manual Trigger node to your canvas
  2. This node requires no configuration—it simply initiates the workflow
  3. The trigger will accept data passed from the execution panel

Input structure:

The workflow expects three text fields in the execution:

  • job_posting: The complete job description or project requirements
  • workflow_json: The full n8n workflow JSON export
  • demo_script: Video voiceover or demonstration walkthrough text

Why this works:

Manual triggers give you complete control over when articles generate. You can batch multiple job postings, test different prompt variations, or integrate this workflow into larger automation sequences. The three-input structure ensures the AI has complete context—the business problem (job posting), the technical solution (workflow JSON), and the user experience (demo script).

Step 2: Build the System Prompt with Editorial Structure

The Claude AI node uses a comprehensive system prompt that enforces the entire editorial structure. This prompt is the workflow's intelligence—it defines tone, format, and content requirements.

Configure the Claude AI node:

  1. Add an "OpenAI Model" node (works with Anthropic API)
  2. Select "Claude 3.5 Sonnet" as the model
  3. Set max tokens to 200,000 for full context window
  4. Temperature: 0.3 (lower for consistency, higher for creativity)

System prompt structure:

You are an expert technical writer specializing in workflow automation and n8n implementations. Your task is to convert n8n Upwork job postings and demo videos into comprehensive, educational articles that teach readers how to build the solution themselves.

## Writing Principles

Tone & Style:
- Authoritative and confident
- Educational, not promotional
- Short, punchy sentences
- Active voice, addressing the reader directly ("you")
- Technical precision without jargon overload

The prompt continues with 14 required H2 sections, each with specific formatting requirements, content guidelines, and example structures.

Critical prompt components:

  • Token budget: <budget:token_budget>200000</budget:token_budget> ensures full context usage
  • Output format: JSON object with title, meta_description, and body fields
  • Section templates: Each H2 includes exact formatting with tables, code blocks, or checklists
  • Content guidelines: Explicit "Do" and "Don't" lists prevent generic content

Why this approach:

System prompts act as persistent instructions that shape every response. By encoding the entire editorial structure in the prompt, you eliminate the need for post-processing or manual editing. The AI becomes a specialized technical writer that follows your exact style guide.

Variables to customize:

  • target_length: Adjust from 1,200 words for different content depths
  • temperature: Lower (0.1-0.3) for technical accuracy, higher (0.5-0.7) for creative variations
  • section_requirements: Add or remove H2 sections based on your content needs

Step 3: Process Inputs and Generate Articles

The Claude AI node receives the three inputs and system prompt, then generates the complete article in a single API call.

Node configuration:

{
  "model": "claude-3-5-sonnet-20241022",
  "maxTokens": 200000,
  "options": {
    "temperature": 0.3,
    "topP": 1
  },
  "messages": [
    {
      "role": "user",
      "content": "Create a comprehensive technical article teaching how to build this n8n agent.

## Job Posting

**Title:** {{ $json.job_posting_title }}

**Description:** {{ $json.job_posting }}

## N8N Workflow JSON

{{ $json.workflow_json }}

## Demo Script/Voiceover

{{ $json.demo_script }}"
    }
  ]
}

Execution flow:

  1. Manual trigger fires with three text inputs
  2. Claude AI node receives inputs via n8n expressions
  3. System prompt enforces 14-section structure
  4. AI processes all context (job + JSON + script) simultaneously
  5. Output returns as JSON with title, meta_description, and body
  6. Average processing time: 30-45 seconds

Why this works:

Claude's 200,000 token context window can process the entire job posting, a complex n8n workflow JSON (often 5,000-15,000 tokens), and a demo script simultaneously. This holistic context ensures the article accurately describes the technical implementation while matching the business language from the job posting.

The single API call approach is more reliable than multi-step generation. You avoid context loss between steps and ensure the article maintains consistent tone throughout all 14 sections.

Workflow Architecture Overview

This workflow consists of 2 nodes organized into a simple linear flow:

  1. Input collection (Node 1): Manual trigger accepts three text fields
  2. AI generation (Node 2): Claude processes inputs and generates article

Execution flow:

  • Trigger: Manual execution from n8n interface
  • Average run time: 30-45 seconds depending on input length
  • Key dependencies: Anthropic API credentials configured in n8n

Critical nodes:

  • Manual Trigger: Provides flexible input method for batch processing
  • Claude AI (OpenAI Model node): Handles entire article generation with 200K token context
  • System Prompt: Embedded in AI node, enforces all editorial standards

The workflow's simplicity is intentional. By consolidating all logic into the system prompt, you avoid complex branching, data transformation, or post-processing nodes. The complete n8n workflow JSON template is available at the bottom of this article.

Key Configuration Details

The Claude AI node requires specific settings to generate high-quality technical content consistently.

Anthropic API Integration

Required fields:

  • API Key: Your Anthropic API key from console.anthropic.com
  • Model: claude-3-5-sonnet-20241022 (latest version)
  • Max Tokens: 200,000 (full context window)
  • Temperature: 0.3 (balance between creativity and consistency)

Common issues:

  • Using older Claude models → Results in shorter context windows (100K tokens)
  • Temperature above 0.5 → Produces inconsistent article structures
  • Max tokens below 100,000 → Truncates long workflow JSONs in context

System prompt customization:

The system prompt lives in the "System Message" field of the OpenAI Model node. Key sections to customize:

<budget:token_budget>200000</budget:token_budget>

This XML tag tells Claude to use its full context window. Without it, the model may truncate long inputs.

Output format enforcement:

The prompt explicitly requires JSON output:

Return ONLY the JSON object. Do not include:
- Any explanations before or after
- Any meta-commentary
- Any instructions

This prevents the AI from adding conversational text around the article, ensuring clean output for automated publishing.

Why this approach:

Embedding all editorial logic in the system prompt creates a self-contained article generator. You can modify tone, structure, or requirements by editing the prompt—no workflow changes needed. This separation of concerns makes the system maintainable and scalable.

Testing & Validation

Test the workflow with progressively complex inputs to verify output quality and consistency.

Test sequence:

  1. Simple test: Use a short job posting (2-3 paragraphs), minimal workflow JSON (10-20 nodes), and brief demo script
  2. Review output structure: Verify all 14 H2 sections appear with correct formatting
  3. Check technical accuracy: Compare workflow JSON details against article descriptions
  4. Validate tables: Ensure tables render correctly with proper markdown syntax
  5. Test edge cases: Very long workflow JSONs (10,000+ tokens), missing demo scripts, vague job postings

Common issues and fixes:

Issue Cause Solution
Missing H2 sections Temperature too high Reduce to 0.2-0.3
Generic content Insufficient input context Add more detail to job posting and demo script
Truncated output Max tokens too low Increase to 200,000
Inconsistent tone System prompt not specific enough Add more "Do/Don't" examples

Quality checklist:

  • Article includes all 14 required H2 sections
  • Tables format correctly in markdown preview
  • Code blocks use proper syntax highlighting
  • Technical details match workflow JSON exactly
  • Tone remains authoritative and educational throughout
  • Meta description under 155 characters
  • Article length approximately 1,200 words

Deployment Considerations

Moving this workflow to production requires attention to API costs, error handling, and content review processes.

Production Deployment Checklist

Area Requirement Why It Matters
API Costs Monitor token usage per article Claude charges per input/output token; 1,200-word articles cost $0.50-2.00
Error Handling Add Error Trigger node after Claude AI Catches API failures, rate limits, or malformed outputs
Content Review Manual approval step before publishing AI-generated content needs human verification for brand voice
Version Control Save system prompt in Git Track prompt iterations and their impact on output quality
Rate Limiting Add Wait node for batch processing Anthropic enforces rate limits; space out multiple executions

Monitoring recommendations:

Set up n8n's built-in execution logging to track:

  • Average token usage per article (input + output)
  • API failure rates and error types
  • Generation time trends (watch for slowdowns)
  • Output length consistency (should stay near 1,200 words)

Error handling strategy:

Add an Error Trigger node connected to the Claude AI node:

{
  "errorWorkflow": "notify-admin-on-failure",
  "continueOnFail": false,
  "retryOnFail": true,
  "maxTries": 3,
  "waitBetweenTries": 5000
}

This configuration retries failed API calls three times with 5-second delays, then triggers an admin notification workflow if all attempts fail.

Use Cases & Variations

This article generation workflow adapts to multiple content creation scenarios beyond job posting conversions.

Use Case 1: Product Documentation

  • Industry: SaaS, Developer Tools
  • Scale: 20-50 documentation pages per product release
  • Modifications needed: Replace job posting input with feature specifications; adjust system prompt to focus on user guides instead of tutorials

Use Case 2: Tutorial Content for YouTube

  • Industry: Online Education, Course Creators
  • Scale: 10-15 written tutorials per video series
  • Modifications needed: Use video transcripts as primary input; add H2 section for "Video Timestamps"; reduce article length to 800 words for companion content

Use Case 3: Technical Case Studies

  • Industry: B2B Marketing, Consulting
  • Scale: 5-10 case studies per quarter
  • Modifications needed: Input client project details instead of job postings; add "Results & Metrics" H2 section; increase length to 1,500-2,000 words

Use Case 4: API Documentation

  • Industry: API-First Companies
  • Scale: 100+ endpoint documentation pages
  • Modifications needed: Input OpenAPI/Swagger specs instead of workflow JSON; system prompt focuses on endpoint descriptions, parameters, and response examples

Customizations & Extensions

Extend this workflow to handle pre-processing, multi-language support, or automated publishing.

Alternative AI Models

Instead of Claude 3.5 Sonnet:

  • GPT-4 Turbo: Best for faster generation (15-20 seconds) - requires changing node to "OpenAI" instead of "Anthropic"
  • Claude 3 Opus: Better for complex technical accuracy - increase max tokens to 200,000 and temperature to 0.2
  • Local LLMs (Ollama): Use when data privacy is critical - requires self-hosted n8n and Ollama integration

Workflow Extensions

Add automated publishing:

  • Add an HTTP Request node to your CMS API (WordPress, Ghost, Webflow)
  • Parse the JSON output to extract title, meta_description, and body
  • POST to your CMS's article creation endpoint
  • Nodes needed: +3 (Function for JSON parsing, HTTP Request, Set for response handling)

Implement multi-language support:

  • Duplicate the Claude AI node for each target language
  • Modify system prompt to include "Write this article in [Spanish/French/German]"
  • Use Switch node to route based on language parameter
  • Performance impact: 2x-5x cost depending on number of languages

Add SEO optimization:

  • Insert an additional Claude AI node after article generation
  • Prompt: "Analyze this article and suggest 5 internal linking opportunities and 3 related keywords"
  • Append suggestions to article output as comments
  • Nodes needed: +2 (Claude AI, Function to merge outputs)

Integration possibilities:

Add This To Get This Complexity
Airtable input Batch process multiple job postings Easy (2 nodes: Airtable trigger + loop)
Google Docs output Collaborative editing before publish Medium (3 nodes: Function, Google Docs API, Set)
Slack notifications Alert team when articles are ready Easy (1 node: Slack message)
Grammarly API Automated grammar and style checking Medium (4 nodes: HTTP Request, Function, conditional logic)

Scale to handle more data:

For processing 50+ articles per day:

  • Replace Manual Trigger with Webhook or Schedule trigger
  • Add Queue node to prevent API rate limit issues
  • Implement Redis caching for frequently used workflow JSONs
  • Performance improvement: Process 100 articles/hour vs 10 articles/hour

Get Started Today

Ready to automate your technical content creation?

  1. Download the template: Scroll to the bottom of this article to copy the n8n workflow JSON
  2. Import to n8n: Go to Workflows → Import from URL or File, paste the JSON
  3. Configure Anthropic API: Add your API credentials in Settings → Credentials → Create New → Anthropic
  4. Test with sample data: Use a simple job posting and small workflow JSON to verify output
  5. Customize the system prompt: Edit the prompt in the Claude AI node to match your brand voice and content requirements
  6. Deploy to production: Set up error handling and monitoring before processing real content

Next steps for optimization:

  • A/B test different temperature settings (0.2 vs 0.4) to find your quality/creativity balance
  • Create prompt variations for different content types (tutorials vs case studies vs documentation)
  • Build a feedback loop: track which articles perform best and adjust the system prompt accordingly

Need help customizing this workflow for your specific content needs? Schedule an intro call with Atherial at https://atherial.ai/contact to discuss enterprise implementations, custom prompt engineering, or multi-language content strategies.


N8N Workflow JSON Template

{
  "name": "AI Article Generator from Job Postings",
  "nodes": [
    {
      "parameters": {},
      "name": "Manual Trigger",
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [250, 300]
    },
    {
      "parameters": {
        "model": "claude-3-5-sonnet-20241022",
        "maxTokens": 200000,
        "options": {
          "temperature": 0.3,
          "topP": 1
        },
        "messages": {
          "values": [
            {
              "role": "system",
              "content": "You are an expert technical writer specializing in workflow automation and n8n implementations. Your task is to convert n8n Upwork job postings and demo videos into comprehensive, educational articles that teach readers how to build the solution themselves.

## Writing Principles

Tone & Style:
- Authoritative and confident
- Educational, not promotional
- Short, punchy sentences
- Active voice, addressing the reader directly (\"you\")
- Technical precision without jargon overload

Format for AI Citations:
- Each H2 section is self-contained
- Include specific technical details, not vague information
- Use tables for comparisons and specifications
- Format for passage-level retrieval (LLMs can lift any section)
- Target 1,200 words total

## Required Article Structure
[Full structure as defined in system instructions]

<budget:token_budget>200000</budget:token_budget>"
            },
            {
              "role": "user",
              "content": "Create a comprehensive technical article teaching how to build this n8n agent.

## Job Posting

**Title:** {{ $json.job_posting_title }}

**Description:** {{ $json.job_posting }}

## N8N Workflow JSON

{{ $json.workflow_json }}

## Demo Script/Voiceover

{{ $json.demo_script }}"
            }
          ]
        }
      },
      "name": "Claude AI Article Generator",
      "type": "n8n-nodes-base.openAi",
      "typeVersion": 1,
      "position": [450, 300],
      "credentials": {
        "anthropicApi": {
          "id": "1",
          "name": "Anthropic API"
        }
      }
    }
  ],
  "connections": {
    "Manual Trigger": {
      "main": [[{"node": "Claude AI Article Generator", "type": "main", "index": 0}]]
    }
  }
}

Complete N8N Workflow Template

Copy the JSON below and import it into your N8N instance via Workflows → Import from File

{
  "name": "AI WordPress Elementor Auto-Editor",
  "tags": [],
  "nodes": [
    {
      "id": "webhook-trigger-001",
      "name": "Webhook - Multi-Channel Intake",
      "type": "n8n-nodes-base.webhook",
      "position": [
        240,
        300
      ],
      "webhookId": "elementor-editor-webhook",
      "parameters": {
        "path": "elementor-editor",
        "options": {},
        "httpMethod": "POST",
        "responseMode": "responseNode"
      },
      "typeVersion": 2
    },
    {
      "id": "whatsapp-trigger-001",
      "name": "WhatsApp Message Trigger",
      "type": "n8n-nodes-base.whatsAppTrigger",
      "position": [
        240,
        500
      ],
      "webhookId": "whatsapp-elementor",
      "parameters": {
        "options": {},
        "updates": [
          "messages"
        ]
      },
      "typeVersion": 1
    },
    {
      "id": "email-trigger-001",
      "name": "Email Trigger - Client Requests",
      "type": "n8n-nodes-base.emailReadImap",
      "position": [
        240,
        700
      ],
      "parameters": {
        "format": "simple",
        "mailbox": "INBOX",
        "options": {
          "customEmailConfig": "imap.gmail.com:993:true"
        },
        "postProcessAction": "read"
      },
      "credentials": {
        "imap": {
          "id": "1",
          "name": "IMAP account"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "normalize-input-001",
      "name": "Normalize Multi-Channel Input",
      "type": "n8n-nodes-base.code",
      "position": [
        460,
        500
      ],
      "parameters": {
        "mode": "runOnceForAllItems",
        "jsCode": "// Normalize incoming data from different channels\nconst items = $input.all();\nconst normalizedItems = [];\n\nfor (const item of items) {\n  let clientRequest = {};\n  \n  // Detect source and extract data\n  if (item.json.body) {\n    // Webhook source\n    clientRequest = {\n      source: 'webhook',\n      clientName: item.json.body.clientName || 'Unknown',\n      clientEmail: item.json.body.clientEmail || '',\n      siteUrl: item.json.body.siteUrl || '',\n      requestText: item.json.body.request || '',\n      priority: item.json.body.priority || 'medium',\n      timestamp: new Date().toISOString()\n    };\n  } else if (item.json.messages) {\n    // WhatsApp source\n    const message = item.json.messages[0];\n    clientRequest = {\n      source: 'whatsapp',\n      clientName: item.json.contacts?.[0]?.profile?.name || 'WhatsApp User',\n      clientPhone: message.from,\n      requestText: message.text?.body || '',\n      priority: 'high',\n      timestamp: new Date().toISOString()\n    };\n  } else if (item.json.subject) {\n    // Email source\n    clientRequest = {\n      source: 'email',\n      clientName: item.json.from?.name || 'Email User',\n      clientEmail: item.json.from?.address || '',\n      subject: item.json.subject || '',\n      requestText: item.json.text || item.json.html || '',\n      priority: 'medium',\n      timestamp: new Date().toISOString()\n    };\n  }\n  \n  // Extract site URL from text if not provided\n  if (!clientRequest.siteUrl) {\n    const urlMatch = clientRequest.requestText.match(/https?:\\/\\/[^\\s]+/);\n    clientRequest.siteUrl = urlMatch ? urlMatch[0] : '';\n  }\n  \n  normalizedItems.push({ json: clientRequest });\n}\n\nreturn normalizedItems;"
      },
      "typeVersion": 2
    },
    {
      "id": "ai-agent-parser-001",
      "name": "AI Agent - Request Parser",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        680,
        500
      ],
      "parameters": {
        "text": "={{ $json.requestText }}",
        "options": {
          "systemMessage": "You are an expert WordPress Elementor editor assistant. Your task is to analyze client change requests and extract structured information needed to automate the edits.\n\nAnalyze the request and extract:\n1. **target_element**: The specific Elementor widget or section to modify (e.g., 'heading', 'button', 'image', 'text-editor', 'spacer')\n2. **action_type**: What to do ('update_text', 'change_image', 'update_color', 'modify_styling', 'add_element', 'delete_element', 'duplicate_element')\n3. **target_page**: Which page to edit (homepage, about, contact, specific URL)\n4. **changes**: Detailed object describing the exact changes\n5. **selectors**: CSS selectors or Elementor IDs to locate elements\n6. **validation**: What to check to confirm success\n\nBe precise and technical. Return valid JSON format."
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 3
    },
    {
      "id": "openai-model-001",
      "name": "OpenAI GPT-4O Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        680,
        700
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o",
          "cachedResultName": "GPT-4O"
        },
        "options": {
          "maxTokens": 2000,
          "temperature": 0.3
        }
      },
      "credentials": {
        "openAiApi": {
          "id": "1",
          "name": "OpenAI API"
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "structured-parser-001",
      "name": "Structured Output Parser",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        680,
        900
      ],
      "parameters": {
        "jsonSchemaExample": "{\n  \"target_page\": \"homepage\",\n  \"target_element\": \"heading\",\n  \"action_type\": \"update_text\",\n  \"changes\": {\n    \"new_text\": \"Welcome to Our Site\",\n    \"color\": \"#333333\",\n    \"font_size\": \"48px\"\n  },\n  \"selectors\": {\n    \"element_id\": \"elementor-heading-1234\",\n    \"css_selector\": \".elementor-widget-heading h2\"\n  },\n  \"validation\": \"Text should display 'Welcome to Our Site' in #333333 color\"\n}"
      },
      "typeVersion": 1
    },
    {
      "id": "enrich-data-001",
      "name": "Enrich with WP Credentials",
      "type": "n8n-nodes-base.code",
      "position": [
        900,
        500
      ],
      "parameters": {
        "mode": "runOnceForAllItems",
        "jsCode": "// Store WordPress credentials securely from environment or workflow static data\n// In production, use n8n credentials or secure vault\nconst items = $input.all();\nconst enrichedItems = [];\n\nfor (const item of items) {\n  const parsedRequest = typeof item.json.output === 'string' \n    ? JSON.parse(item.json.output) \n    : item.json.output;\n  \n  // Get WordPress credentials for the site\n  // In production: Fetch from secure credential store based on siteUrl\n  const wpCredentials = {\n    username: $env.WP_USERNAME || 'admin',\n    password: $env.WP_PASSWORD || 'secure-password',\n    loginUrl: item.json.siteUrl + '/wp-admin'\n  };\n  \n  // Enrich with metadata\n  const enrichedData = {\n    requestId: `REQ-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,\n    originalRequest: item.json,\n    parsedAction: parsedRequest,\n    wpCredentials: wpCredentials,\n    executionTimestamp: new Date().toISOString(),\n    status: 'pending'\n  };\n  \n  enrichedItems.push({ json: enrichedData });\n}\n\nreturn enrichedItems;"
      },
      "typeVersion": 2
    },
    {
      "id": "browser-tool-001",
      "name": "Browser Automation Tool",
      "type": "@n8n/n8n-nodes-langchain.toolCode",
      "position": [
        900,
        700
      ],
      "parameters": {
        "name": "wordpress_browser_automation",
        "jsCode": "// WordPress & Elementor Browser Automation Tool\nconst wpUrl = $input.item.json.originalRequest.siteUrl;\nconst credentials = $input.item.json.wpCredentials;\nconst action = $input.item.json.parsedAction;\n\n// This tool would integrate with Playwright/Puppeteer via HTTP Request\n// or use a dedicated browser automation service like Browserbase\n\nconst automationScript = {\n  task: 'elementor_edit',\n  steps: [\n    {\n      action: 'navigate',\n      url: credentials.loginUrl\n    },\n    {\n      action: 'fill',\n      selector: '#user_login',\n      value: credentials.username\n    },\n    {\n      action: 'fill',\n      selector: '#user_pass',\n      value: credentials.password\n    },\n    {\n      action: 'click',\n      selector: '#wp-submit'\n    },\n    {\n      action: 'screenshot',\n      name: 'before_edit',\n      fullPage: true\n    },\n    {\n      action: 'navigate',\n      url: `${wpUrl}/${action.target_page}?elementor`\n    },\n    {\n      action: 'wait',\n      selector: '.elementor-editor-active',\n      timeout: 10000\n    },\n    {\n      action: 'elementor_edit',\n      elementId: action.selectors.element_id,\n      changes: action.changes\n    },\n    {\n      action: 'screenshot',\n      name: 'after_edit',\n      fullPage: true\n    },\n    {\n      action: 'click',\n      selector: '#elementor-panel-saver-button-publish'\n    }\n  ]\n};\n\nreturn JSON.stringify({\n  automation_ready: true,\n  script: automationScript,\n  estimated_duration: '45 seconds'\n});",
        "language": "javaScript",
        "description": "Automates WordPress login, Elementor navigation, and executes content changes with screenshot capture"
      },
      "typeVersion": 1.3
    },
    {
      "id": "http-browser-001",
      "name": "Execute Browser Automation",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1120,
        500
      ],
      "parameters": {
        "url": "={{ $json.browserAutomationEndpoint || 'https://api.browserbase.com/v1/sessions' }}",
        "method": "POST",
        "options": {
          "timeout": 120000
        },
        "jsonBody": "={{ JSON.stringify($json.parsedAction) }}",
        "sendBody": true,
        "contentType": "json",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "={{ 'Bearer ' + $env.BROWSERBASE_API_KEY }}"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "process-results-001",
      "name": "Process Automation Results",
      "type": "n8n-nodes-base.code",
      "position": [
        1340,
        500
      ],
      "parameters": {
        "mode": "runOnceForAllItems",
        "jsCode": "// Process automation results and prepare for logging\nconst items = $input.all();\nconst processedResults = [];\n\nfor (const item of items) {\n  const automationResult = item.json;\n  \n  const result = {\n    requestId: item.json.requestId,\n    executionStatus: automationResult.success ? 'completed' : 'failed',\n    beforeScreenshot: automationResult.screenshots?.before || null,\n    afterScreenshot: automationResult.screenshots?.after || null,\n    changesApplied: automationResult.changes_applied || [],\n    errorMessage: automationResult.error || null,\n    executionDuration: automationResult.duration_ms || 0,\n    validationPassed: automationResult.validation_passed || false,\n    completedAt: new Date().toISOString(),\n    auditTrail: {\n      clientSource: item.json.originalRequest?.source,\n      clientIdentifier: item.json.originalRequest?.clientEmail || item.json.originalRequest?.clientPhone,\n      originalRequest: item.json.originalRequest?.requestText,\n      aiParsedAction: item.json.parsedAction,\n      wpSite: item.json.originalRequest?.siteUrl,\n      executedBy: 'n8n-automation',\n      ipAddress: automationResult.ip_address || 'n8n-internal'\n    }\n  };\n  \n  processedResults.push({ json: result });\n}\n\nreturn processedResults;"
      },
      "typeVersion": 2
    },
    {
      "id": "postgres-log-001",
      "name": "Log to Database - Audit Trail",
      "type": "n8n-nodes-base.postgres",
      "position": [
        1560,
        500
      ],
      "parameters": {
        "table": {
          "__rl": true,
          "mode": "list",
          "value": "elementor_change_logs"
        },
        "columns": {
          "value": {
            "ip_address": "={{ $json.auditTrail.ipAddress }}",
            "request_id": "={{ $json.requestId }}",
            "executed_by": "={{ $json.auditTrail.executedBy }}",
            "wp_site_url": "={{ $json.auditTrail.wpSite }}",
            "completed_at": "={{ $json.completedAt }}",
            "client_source": "={{ $json.auditTrail.clientSource }}",
            "error_message": "={{ $json.errorMessage }}",
            "parsed_action": "={{ JSON.stringify($json.auditTrail.aiParsedAction) }}",
            "changes_applied": "={{ JSON.stringify($json.changesApplied) }}",
            "execution_status": "={{ $json.executionStatus }}",
            "original_request": "={{ $json.auditTrail.originalRequest }}",
            "client_identifier": "={{ $json.auditTrail.clientIdentifier }}",
            "validation_passed": "={{ $json.validationPassed }}",
            "after_screenshot_url": "={{ $json.afterScreenshot }}",
            "before_screenshot_url": "={{ $json.beforeScreenshot }}",
            "execution_duration_ms": "={{ $json.executionDuration }}"
          },
          "mappingMode": "defineBelow"
        },
        "options": {},
        "operation": "insert"
      },
      "credentials": {
        "postgres": {
          "id": "1",
          "name": "Postgres Audit DB"
        }
      },
      "typeVersion": 2.6
    },
    {
      "id": "if-success-001",
      "name": "If Execution Successful",
      "type": "n8n-nodes-base.if",
      "position": [
        1780,
        500
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "condition-001",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.executionStatus }}",
              "rightValue": "completed"
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "success-message-001",
      "name": "Generate Success Message",
      "type": "n8n-nodes-base.code",
      "position": [
        2000,
        400
      ],
      "parameters": {
        "mode": "runOnceForAllItems",
        "jsCode": "// Generate success notification message\nconst item = $input.item.json;\n\nconst successMessage = {\n  to: item.auditTrail.clientIdentifier,\n  subject: `✅ Elementor Changes Completed - Request ${item.requestId}`,\n  message: `Hello!\n\nYour WordPress Elementor changes have been successfully completed.\n\n📋 Request ID: ${item.requestId}\n🌐 Site: ${item.auditTrail.wpSite}\n⏱️ Completed in: ${(item.executionDuration / 1000).toFixed(2)} seconds\n✅ Validation: ${item.validationPassed ? 'Passed' : 'Review Needed'}\n\n📸 Screenshots:\n- Before: ${item.beforeScreenshot}\n- After: ${item.afterScreenshot}\n\n🔍 Changes Applied:\n${item.changesApplied.map(c => `  - ${c}`).join('\\n')}\n\nThank you for using our automated service!\n\nBest regards,\nAutomated Elementor Editor`,\n  sourceChannel: item.auditTrail.clientSource\n};\n\nreturn { json: successMessage };"
      },
      "typeVersion": 2
    },
    {
      "id": "failure-message-001",
      "name": "Generate Failure Alert",
      "type": "n8n-nodes-base.code",
      "position": [
        2000,
        600
      ],
      "parameters": {
        "mode": "runOnceForAllItems",
        "jsCode": "// Generate failure notification message\nconst item = $input.item.json;\n\nconst failureMessage = {\n  to: item.auditTrail.clientIdentifier,\n  subject: `⚠️ Elementor Changes Failed - Request ${item.requestId}`,\n  message: `Hello,\n\nWe encountered an issue while processing your WordPress Elementor change request.\n\n📋 Request ID: ${item.requestId}\n🌐 Site: ${item.auditTrail.wpSite}\n❌ Error: ${item.errorMessage || 'Unknown error occurred'}\n\n📸 Screenshot at failure:\n${item.beforeScreenshot || 'Not available'}\n\nOur team has been notified and will review this request manually.\nWe'll get back to you shortly.\n\nApologies for the inconvenience.\n\nBest regards,\nAutomated Elementor Editor`,\n  sourceChannel: item.auditTrail.clientSource,\n  alertTeam: true\n};\n\nreturn { json: failureMessage };"
      },
      "typeVersion": 2
    },
    {
      "id": "send-notification-001",
      "name": "Send Client Notification",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        2220,
        500
      ],
      "parameters": {
        "url": "={{ $json.sourceChannel === 'whatsapp' ? 'https://graph.facebook.com/v18.0/PHONE_ID/messages' : 'https://api.sendgrid.com/v3/mail/send' }}",
        "method": "POST",
        "options": {},
        "jsonBody": "={{ JSON.stringify({\n  to: $json.to,\n  message: $json.message,\n  subject: $json.subject\n}) }}",
        "sendBody": true,
        "contentType": "json",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "={{ $json.sourceChannel === 'whatsapp' ? 'Bearer ' + $env.WHATSAPP_TOKEN : 'Bearer ' + $env.SENDGRID_API_KEY }}"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "webhook-response-001",
      "name": "Respond to Webhook",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        2440,
        300
      ],
      "parameters": {
        "options": {
          "responseCode": 200
        },
        "respondWith": "json",
        "responseBody": "={{ JSON.stringify({\n  success: true,\n  requestId: $('Process Automation Results').item.json.requestId,\n  status: $('Process Automation Results').item.json.executionStatus,\n  message: 'Your Elementor change request has been processed',\n  screenshots: {\n    before: $('Process Automation Results').item.json.beforeScreenshot,\n    after: $('Process Automation Results').item.json.afterScreenshot\n  },\n  timestamp: new Date().toISOString()\n}) }}"
      },
      "typeVersion": 1
    }
  ],
  "pinData": {},
  "settings": {
    "callerPolicy": "workflowsFromSameOwner",
    "errorWorkflow": "",
    "executionOrder": "v1",
    "saveManualExecutions": true,
    "saveExecutionProgress": true
  },
  "versionId": "",
  "connections": {
    "OpenAI GPT-4O Model": {
      "ai_languageModel": [
        [
          {
            "node": "AI Agent - Request Parser",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Generate Failure Alert": {
      "main": [
        [
          {
            "node": "Send Client Notification",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Browser Automation Tool": {
      "ai_tool": [
        [
          {
            "node": "AI Agent - Request Parser",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "If Execution Successful": {
      "main": [
        [
          {
            "node": "Generate Success Message",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Generate Failure Alert",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Success Message": {
      "main": [
        [
          {
            "node": "Send Client Notification",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Client Notification": {
      "main": [
        [
          {
            "node": "Respond to Webhook",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Structured Output Parser": {
      "ai_outputParser": [
        [
          {
            "node": "AI Agent - Request Parser",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "WhatsApp Message Trigger": {
      "main": [
        [
          {
            "node": "Normalize Multi-Channel Input",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Agent - Request Parser": {
      "main": [
        [
          {
            "node": "Enrich with WP Credentials",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Enrich with WP Credentials": {
      "main": [
        [
          {
            "node": "Execute Browser Automation",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Execute Browser Automation": {
      "main": [
        [
          {
            "node": "Process Automation Results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Process Automation Results": {
      "main": [
        [
          {
            "node": "Log to Database - Audit Trail",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Log to Database - Audit Trail": {
      "main": [
        [
          {
            "node": "If Execution Successful",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Normalize Multi-Channel Input": {
      "main": [
        [
          {
            "node": "AI Agent - Request Parser",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Webhook - Multi-Channel Intake": {
      "main": [
        [
          {
            "node": "Normalize Multi-Channel Input",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Email Trigger - Client Requests": {
      "main": [
        [
          {
            "node": "Normalize Multi-Channel Input",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "triggerCount": 0
}