Skip to content

n8n Integration Plan for Forge

n8n (CT 106, 192.168.86.82:5678) is the nervous system, it watches external services and creates tasks for the Forge AI workforce.

Architecture

External Services → n8n (webhooks/polls) → SSH to UDev → task-creator.sh → tasks/pending/ → Supervisor picks up

All n8n workflows create tasks by SSH-ing into UDev and running task-creator.sh. This keeps n8n as a dumb relay, no AI logic in n8n, just event detection and task creation.

SSH Setup

n8n needs SSH access to UDev to create task files:

# On n8n container (CT 106):
ssh-keygen -t ed25519 -f /root/.ssh/id_ed25519 -N ""

# Copy the public key to UDev:
ssh-copy-id -i /root/.ssh/id_ed25519.pub [email protected]

# Test:
ssh [email protected] "echo ok"

In n8n, create an SSH credential (udev-ssh) pointing to 192.168.86.50 with the key.


Workflow 1: Email Watcher

Trigger: IMAP poll every 5 minutes Email account: Justin's business email (configure in n8n IMAP credentials: NOT personal Gmail per CLAUDE.md security rules) Action: Create a task for each new email

n8n Steps

  1. IMAP Email Trigger node
  2. Mailbox: INBOX
  3. Poll interval: 5 minutes
  4. Mark as read: yes (prevents re-processing)

  5. Function node, format the task

    const subject = $input.first().json.subject || '(no subject)';
    const from = $input.first().json.from?.text || 'unknown';
    const date = $input.first().json.date;
    const bodyPreview = ($input.first().json.text || '').substring(0, 500);
    
    return [{
      json: {
        name: `email-triage-${Date.now()}`,
        model: 'sonnet',
        priority: 'normal',
        prompt: `Triage this email and draft a response if needed.\n\nFrom: ${from}\nSubject: ${subject}\nDate: ${date}\n\nBody:\n${bodyPreview}`,
        tags: 'email,triage',
        budget: 15,
        created_by: 'n8n'
      }
    }];
    

  6. SSH node, create the task on UDev

  7. Credential: udev-ssh
  8. Command:
    /home/justinwieb/forge/infra/n8n/task-creator.sh \
      --name "{{ $json.name }}" \
      --model "{{ $json.model }}" \
      --priority "{{ $json.priority }}" \
      --prompt "{{ $json.prompt }}" \
      --tags "{{ $json.tags }}" \
      --budget "{{ $json.budget }}" \
      --created-by n8n
    

Workflow 2: Shopify Order Handler

Trigger: Shopify webhook (new order) Action: Create a high-priority task for order processing

n8n Steps

  1. Webhook node
  2. Method: POST
  3. Path: /shopify-order
  4. Configure Shopify to send orders/create webhook to http://192.168.86.82:5678/webhook/shopify-order

  5. Function node

    const order = $input.first().json;
    const orderId = order.id || order.order_number || 'unknown';
    const customerName = order.customer?.first_name || 'Unknown';
    const total = order.total_price || '0.00';
    const items = (order.line_items || []).map(i => `${i.quantity}x ${i.title}`).join(', ');
    
    return [{
      json: {
        name: `shopify-order-${orderId}`,
        model: 'haiku',
        priority: 'high',
        prompt: `New Shopify order #${orderId} from ${customerName} ($${total}). Items: ${items}. Verify inventory and update tracking if available.`,
        tags: 'shopify,orders,nova-design',
        budget: 10,
        created_by: 'n8n'
      }
    }];
    

  6. SSH node, same pattern as Workflow 1


Workflow 3: Scheduled Morning Briefing

Trigger: Cron at 6:00 AM CT daily Action: Create a task for the Coordinator to generate a daily briefing

n8n Steps

  1. Cron node
  2. Expression: 0 6 * * *
  3. Timezone: America/Chicago

  4. SSH node, create briefing task

    /home/justinwieb/forge/infra/n8n/task-creator.sh \
      --name "morning-briefing" \
      --model opus \
      --priority high \
      --prompt "Generate Justin's morning briefing. Check: (1) pending tasks in forge/tasks/pending/, (2) notification history in forge/notifications/history.log, (3) recent daily logs in forge/memory/daily/. Summarize what happened overnight, what's pending, and what needs attention today. Write the briefing to forge/notifications/latest.md and send via notify.sh as info priority." \
      --tags "briefing,daily" \
      --budget 30 \
      --created-by n8n
    


Workflow 4: Website Health Check

Trigger: Cron every 15 minutes Action: HTTP GET to each site, create critical task if non-200

n8n Steps

  1. Cron node
  2. Expression: */15 * * * *

  3. HTTP Request node (justinkrystal.com)

  4. URL: https://justinkrystal.com
  5. Options: Follow redirects, timeout 10s
  6. Continue on fail: yes

  7. HTTP Request node (shopnovadesign.com)

  8. URL: https://shopnovadesign.com
  9. Options: Follow redirects, timeout 10s
  10. Continue on fail: yes

  11. IF node, check for failures

  12. Condition: Either request returned non-200 or error

  13. SSH node (on failure branch)

    /home/justinwieb/forge/infra/n8n/task-creator.sh \
      --name "site-down-$(date +%s)" \
      --model haiku \
      --priority critical \
      --prompt "ALERT: Website health check failed. Check justinkrystal.com and shopnovadesign.com — one or both returned non-200. Diagnose and notify Justin via notify.sh critical." \
      --tags "monitoring,sites,critical" \
      --budget 10 \
      --created-by n8n
    

  14. Also directly call notify.sh via SSH for immediate alert:

    ssh [email protected] "/home/justinwieb/forge/scripts/forge_notify.sh critical 'Site Down' 'Health check failed for one or more sites'"
    


Workflow 5: Frigate Event Handler

Trigger: Frigate webhook (person detected) Action: Create task with event details

n8n Steps

  1. Webhook node
  2. Method: POST
  3. Path: /frigate-event
  4. Configure Frigate (/opt/frigate/config/config.yml on CT 108) to send MQTT or HTTP events:
    # In Frigate config.yml, under mqtt or http section:
    # Or use Frigate's built-in webhook support
    
  5. Alternative: Use MQTT trigger if Frigate is configured with MQTT broker

  6. IF node, filter for person events only

  7. Condition: $json.type === 'person' or $json.label === 'person'

  8. Function node

    const event = $input.first().json;
    const camera = event.camera || 'unknown';
    const score = event.score || event.top_score || 'N/A';
    const timestamp = event.start_time || new Date().toISOString();
    const snapshotUrl = event.snapshot?.url || event.thumbnail || 'no snapshot';
    const zone = event.entered_zones?.join(', ') || 'no zone';
    
    return [{
      json: {
        name: `frigate-person-${Date.now()}`,
        model: 'haiku',
        priority: 'high',
        prompt: `Person detected on camera "${camera}" at ${timestamp}. Confidence: ${score}. Zones: ${zone}. Snapshot: ${snapshotUrl}. Log this event and notify Justin if it's during unusual hours (10PM-6AM).`,
        tags: 'frigate,security,person-detected',
        budget: 5,
        created_by: 'n8n'
      }
    }];
    

  9. SSH node, create task + immediate notify for nighttime events

    /home/justinwieb/forge/infra/n8n/task-creator.sh \
      --name "{{ $json.name }}" \
      --model "{{ $json.model }}" \
      --priority "{{ $json.priority }}" \
      --prompt "{{ $json.prompt }}" \
      --tags "{{ $json.tags }}" \
      --budget "{{ $json.budget }}" \
      --created-by n8n
    


Setup Checklist

  • Generate SSH key on n8n container, copy to UDev
  • Create udev-ssh credential in n8n UI
  • Set up IMAP credentials for business email
  • Configure Shopify webhook to point to n8n
  • Configure Frigate to send HTTP events to n8n
  • Set environment variables on UDev for notify.sh channels:
  • FORGE_N8N_WEBHOOK, n8n notification relay webhook URL
  • FORGE_NTFY_TOPIC, ntfy.sh topic for push notifications
  • Test each workflow with a manual trigger first
  • Enable cron workflows (morning briefing, health check)