AutomationFlowsDevOps › Aidp - Main Workflow V7

Aidp - Main Workflow V7

AIDP - Main Workflow v7. Uses executeCommand, github, jira. Webhook trigger; 12 nodes.

Webhook trigger★★★★☆ complexity12 nodesExecute CommandGitHubJira
DevOps Trigger: Webhook Nodes: 12 Complexity: ★★★★☆ Added:

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "name": "AIDP - Main Workflow v7",
  "nodes": [
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "aidp-trigger",
        "responseMode": "responseNode",
        "options": {}
      },
      "id": "webhook-trigger",
      "name": "Jira Webhook",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [
        240,
        300
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict"
          },
          "conditions": [
            {
              "id": "check-label",
              "leftValue": "={{ JSON.stringify(($json.body?.issue || $json.issue)?.fields?.labels || []) }}",
              "rightValue": "ai-task",
              "operator": {
                "type": "string",
                "operation": "contains"
              }
            },
            {
              "id": "check-status",
              "leftValue": "={{ ($json.body?.issue || $json.issue)?.fields?.status?.name }}",
              "rightValue": "In Progress",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "filter-conditions",
      "name": "Filter AI Tasks",
      "type": "n8n-nodes-base.filter",
      "typeVersion": 2,
      "position": [
        460,
        300
      ]
    },
    {
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "// ============================================\n// AIDP v7 - Smart Issue Parser\n// ============================================\n\n// Get issue from webhook (handles both formats)\nconst issue = $input.item.json.body?.issue || $input.item.json.issue;\nif (!issue) throw new Error('No issue found in webhook payload');\n\nconst fields = issue.fields;\nconst jiraKey = issue.key;\nconst projectKey = jiraKey.split('-')[0];\nconst summary = fields.summary || '';\n\n// ============================================\n// EXTRACT DESCRIPTION (handles ADF and plain text)\n// ============================================\nlet description = '';\n\nif (typeof fields.description === 'string') {\n  // Plain text (from Jira Automation with plainText)\n  description = fields.description;\n} else if (fields.description?.content) {\n  // ADF format - extract text recursively\n  const extractText = (node) => {\n    if (!node) return '';\n    if (node.type === 'text') return node.text || '';\n    if (node.content) return node.content.map(extractText).join('');\n    return '';\n  };\n  description = fields.description.content.map(extractText).join('\\n');\n}\n\n// ============================================\n// KNOWN REPOS MAPPING (fallbacks)\n// ============================================\nconst KNOWN_REPOS = {\n  'SCRUM': { url: 'https://github.com/andresKillem/aidp-test-repo', branch: 'main' },\n  'VIDA': { url: 'https://github.com/andresKillem/vidaconvida', branch: 'master' },\n  'TEST': { url: 'https://github.com/andresKillem/aidp-test-repo', branch: 'main' }\n};\n\n// ============================================\n// EXTRACT REPO URL FROM DESCRIPTION\n// ============================================\nlet repoUrl = null;\nlet baseBranch = 'main';\n\n// Pattern 1: Look for \"Repository: URL\" or \"Repo: URL\"\nconst repoLabelMatch = description.match(/(?:repository|repo)[:\\s]+((https?:\\/\\/)?github\\.com\\/[\\w.-]+\\/[\\w.-]+)/i);\nif (repoLabelMatch) {\n  repoUrl = repoLabelMatch[1];\n  if (!repoUrl.startsWith('http')) repoUrl = 'https://' + repoUrl;\n}\n\n// Pattern 2: Look for any GitHub URL in description\nif (!repoUrl) {\n  const githubMatch = description.match(/https:\\/\\/github\\.com\\/[\\w.-]+\\/[\\w.-]+/);\n  if (githubMatch) {\n    repoUrl = githubMatch[0].replace(/\\.git$/, '').replace(/\\/$/, '');\n  }\n}\n\n// Pattern 3: Fallback to project mapping\nif (!repoUrl) {\n  const mapping = KNOWN_REPOS[projectKey];\n  if (mapping) {\n    repoUrl = mapping.url;\n    baseBranch = mapping.branch;\n  } else {\n    repoUrl = KNOWN_REPOS['SCRUM'].url;\n    baseBranch = KNOWN_REPOS['SCRUM'].branch;\n  }\n}\n\n// ============================================\n// EXTRACT BASE BRANCH FROM DESCRIPTION\n// ============================================\n// Pattern: \"Branch: main\" or \"Base: master\" or \"base-branch: develop\"\nconst branchMatch = description.match(/(?:branch|base|base[- ]?branch)[:\\s]+(\\w+)/i);\nif (branchMatch) {\n  baseBranch = branchMatch[1];\n}\n\n// Auto-detect branch for known repos\nif (repoUrl.includes('vidaconvida')) baseBranch = 'master';\n\n// ============================================\n// EXTRACT ACCEPTANCE CRITERIA\n// ============================================\nlet acceptanceCriteria = '';\nconst acPatterns = [\n  /##\\s*acceptance\\s*criteria[\\s:]*([\\s\\S]*?)(?=##|$)/i,\n  /acceptance\\s*criteria[:\\s]*([\\s\\S]*?)(?=##|requirements|$)/i,\n  /\\bac[:\\s]+([\\s\\S]*?)(?=##|$)/i\n];\n\nfor (const pattern of acPatterns) {\n  const match = description.match(pattern);\n  if (match && match[1].trim()) {\n    acceptanceCriteria = match[1].trim();\n    break;\n  }\n}\n\n// ============================================\n// GENERATE BRANCH NAME\n// ============================================\nconst slugify = (text) => {\n  return text\n    .toLowerCase()\n    .replace(/[^a-z0-9]+/g, '-')\n    .replace(/^-+|-+$/g, '')\n    .substring(0, 50);\n};\nconst branchName = `ai/${jiraKey.toLowerCase()}-${slugify(summary)}`;\n\n// ============================================\n// EXTRACT OWNER AND REPO FROM URL\n// ============================================\nconst repoMatch = repoUrl.match(/github\\.com\\/([^/]+)\\/([^/]+)/);\nconst owner = repoMatch ? repoMatch[1] : 'andresKillem';\nconst repo = repoMatch ? repoMatch[2].replace('.git', '').replace(/\\/$/, '') : 'aidp-test-repo';\n\n// ============================================\n// RETURN PARSED DATA\n// ============================================\nreturn {\n  // Jira info\n  jiraKey,\n  projectKey,\n  jiraUrl: `https://polarpipeline.atlassian.net/browse/${jiraKey}`,\n  summary,\n  description,\n  acceptanceCriteria,\n  priority: fields.priority?.name || 'Medium',\n  reporter: fields.reporter?.displayName || 'Unknown',\n  \n  // Git info\n  repoUrl,\n  owner,\n  repo,\n  baseBranch,\n  branchName\n};"
      },
      "id": "parse-issue",
      "name": "Parse Issue Data",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        680,
        300
      ]
    },
    {
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "// ============================================\n// AIDP v7 - Prompt Builder\n// ============================================\n\nconst data = $input.item.json;\n\nconst prompt = `# Task: ${data.summary}\n\n## Context\n- **Repository**: ${data.repoUrl}\n- **Base Branch**: ${data.baseBranch}\n- **Feature Branch**: ${data.branchName}\n- **Jira Issue**: [${data.jiraKey}](${data.jiraUrl})\n- **Priority**: ${data.priority}\n\n## Requirements\n${data.description}\n\n## Acceptance Criteria\n${data.acceptanceCriteria || 'Use best judgment based on the requirements above.'}\n\n## Execution Instructions\n\n### Phase 1: Explore\n- Read and understand the existing codebase structure\n- Identify patterns, conventions, and architecture\n- Check package.json, README, or similar for project context\n\n### Phase 2: Plan\n- Create a clear mental model of the solution\n- Identify all files to create or modify\n- Consider edge cases\n\n### Phase 3: Implement\n- Write clean, maintainable code\n- Follow existing patterns exactly\n- Include appropriate error handling\n\n### Phase 4: Commit & Push\n- Stage changes: git add -A\n- Commit with conventional format: feat|fix|chore: description\n- Push to feature branch\n\n## Constraints\n- DO NOT modify unrelated files\n- DO NOT create a PR - only commit and push\n- DO NOT include AI references in commit messages\n- Keep changes minimal and focused`;\n\n// Encode as base64 for shell safety\nconst promptB64 = Buffer.from(prompt).toString('base64');\n\nreturn { ...data, prompt, promptB64 };"
      },
      "id": "build-prompt",
      "name": "Build Prompt",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        900,
        300
      ]
    },
    {
      "parameters": {
        "command": "={{ 'docker exec aidp-claude-executor /usr/local/bin/aidp-executor \"' + $json.repoUrl + '\" \"' + $json.branchName + '\" \"' + $json.promptB64 + '\" \"' + $json.jiraKey + '\" \"' + $json.baseBranch + '\"' }}"
      },
      "id": "execute-claude",
      "name": "Execute Claude Code",
      "type": "n8n-nodes-base.executeCommand",
      "typeVersion": 1,
      "position": [
        1120,
        300
      ]
    },
    {
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "// ============================================\n// AIDP v7 - Result Parser\n// ============================================\n\nconst input = $input.item.json;\nconst stdout = input.stdout || '';\nconst stderr = input.stderr || '';\nlet result;\n\ntry {\n  // Look for JSON result in stdout\n  const jsonMatch = stdout.match(/\\{[\\s\\S]*\"status\"\\s*:\\s*\"[^\"]+\"[\\s\\S]*\\}/);\n  if (jsonMatch) {\n    result = JSON.parse(jsonMatch[0]);\n  } else {\n    throw new Error('No valid JSON result found in executor output');\n  }\n} catch (e) {\n  // Build error result with debugging info\n  result = {\n    status: 'error',\n    error_message: e.message,\n    raw_output: stdout.substring(0, 500),\n    stderr: stderr.substring(0, 500)\n  };\n}\n\n// Get original data from Build Prompt node\nconst orig = $('Build Prompt').item.json;\n\n// Determine success\nconst success = result.status === 'success';\n\nreturn {\n  ...orig,\n  executorResult: result,\n  success,\n  commitCount: result.commit_count || 0,\n  filesChanged: result.files_changed || 0\n};"
      },
      "id": "parse-result",
      "name": "Parse Result",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1340,
        300
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict"
          },
          "conditions": [
            {
              "id": "check-success",
              "leftValue": "={{ $json.success }}",
              "rightValue": true,
              "operator": {
                "type": "boolean",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "check-success",
      "name": "Success?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        1560,
        300
      ]
    },
    {
      "parameters": {
        "owner": {
          "__rl": true,
          "value": "={{ $json.owner }}",
          "mode": "expression"
        },
        "repository": {
          "__rl": true,
          "value": "={{ $json.repo }}",
          "mode": "expression"
        },
        "title": "={{ '[' + $json.jiraKey + '] ' + $json.summary }}",
        "body": "={{ '## Summary\\n\\n' + $json.summary + '\\n\\n## Jira Issue\\n\\n[' + $json.jiraKey + '](' + $json.jiraUrl + ')\\n\\n## Changes\\n\\n- Commits: ' + $json.commitCount + '\\n- Files changed: ' + $json.filesChanged + '\\n\\n' + ($json.executorResult.claude_summary || '') + '\\n\\n---\\n_Generated by AIDP_' }}",
        "base": "={{ $json.baseBranch }}",
        "head": "={{ $json.branchName }}"
      },
      "id": "create-pr",
      "name": "Create PR",
      "type": "n8n-nodes-base.github",
      "typeVersion": 1,
      "position": [
        1780,
        200
      ],
      "credentials": {
        "githubApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "const pr = $input.item.json;\nconst orig = $('Parse Result').item.json;\nreturn {\n  ...orig,\n  prNumber: pr.number,\n  prUrl: pr.html_url\n};"
      },
      "id": "extract-pr",
      "name": "Extract PR Info",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        2000,
        200
      ]
    },
    {
      "parameters": {
        "resource": "issueComment",
        "operation": "add",
        "issueKey": "={{ $json.jiraKey }}",
        "comment": "={{ '\u2705 *AIDP Completed Successfully*\\n\\n\ud83d\udd17 *Pull Request:* [PR #' + $json.prNumber + '](' + $json.prUrl + ')\\n\\n\ud83d\udcca *Stats:*\\n- Commits: ' + $json.commitCount + '\\n- Files changed: ' + $json.filesChanged + '\\n\\n\ud83c\udf3f *Branch:* `' + $json.branchName + '`\\n\\n_Awaiting human review._' }}"
      },
      "id": "jira-comment-success",
      "name": "Jira Comment Success",
      "type": "n8n-nodes-base.jira",
      "typeVersion": 1,
      "position": [
        2220,
        200
      ],
      "credentials": {
        "jiraSoftwareCloudApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "resource": "issueComment",
        "operation": "add",
        "issueKey": "={{ $json.jiraKey }}",
        "comment": "={{ '\u274c *AIDP Failed*\\n\\n*Error:* ' + ($json.executorResult?.error_message || 'Unknown error') + '\\n\\n*Repository:* ' + $json.repoUrl + '\\n*Branch:* ' + $json.branchName + '\\n\\n_Please review the requirements and try again._' }}"
      },
      "id": "jira-comment-error",
      "name": "Jira Comment Error",
      "type": "n8n-nodes-base.jira",
      "typeVersion": 1,
      "position": [
        1780,
        450
      ],
      "credentials": {
        "jiraSoftwareCloudApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "respondWith": "json",
        "responseBody": "={{ JSON.stringify({ status: 'processed', jiraKey: $json.jiraKey, success: $json.success, repoUrl: $json.repoUrl, branch: $json.branchName }) }}"
      },
      "id": "respond-webhook",
      "name": "Respond to Webhook",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.1,
      "position": [
        2440,
        300
      ]
    }
  ],
  "connections": {
    "Jira Webhook": {
      "main": [
        [
          {
            "node": "Filter AI Tasks",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter AI Tasks": {
      "main": [
        [
          {
            "node": "Parse Issue Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Issue Data": {
      "main": [
        [
          {
            "node": "Build Prompt",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Prompt": {
      "main": [
        [
          {
            "node": "Execute Claude Code",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Execute Claude Code": {
      "main": [
        [
          {
            "node": "Parse Result",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Result": {
      "main": [
        [
          {
            "node": "Success?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Success?": {
      "main": [
        [
          {
            "node": "Create PR",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Jira Comment Error",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create PR": {
      "main": [
        [
          {
            "node": "Extract PR Info",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract PR Info": {
      "main": [
        [
          {
            "node": "Jira Comment Success",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Jira Comment Success": {
      "main": [
        [
          {
            "node": "Respond to Webhook",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Jira Comment Error": {
      "main": [
        [
          {
            "node": "Respond to Webhook",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1",
    "saveManualExecutions": true,
    "saveDataSuccessExecution": "all",
    "saveDataErrorExecution": "all"
  }
}

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

AIDP - Main Workflow v7. Uses executeCommand, github, jira. Webhook trigger; 12 nodes.

Source: https://github.com/andresKillem/aidp/blob/8839fb212f6336a3aa9793485da729542e0fd7da/n8n-workflows/main-workflow-v7.json — original creator credit. Request a take-down →

More DevOps workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

DevOps

AIDP - Main Workflow v3. Uses executeCommand, github, jira. Webhook trigger; 12 nodes.

Execute Command, GitHub, Jira
DevOps

This n8n workflow template uses community nodes and is only compatible with the self-hosted version of n8n.

Execute Command, GitHub, Read Write File
DevOps

GitHub PR Deep-Link & Routing Validator (n8n + ExecuteCommand + GitHub Comment). Uses executeCommand, github. Webhook trigger; 5 nodes.

Execute Command, GitHub
DevOps

🔥 n8n Members Sale – n8n Community Members Get ideoGener8r for Just $10! (Reg. $15) Use Coupon Code: (Valid for n8n community members)

n8n, GitHub
DevOps

Code Github. Uses manualTrigger, stickyNote, httpRequest, noOp. Event-driven trigger; 24 nodes.

HTTP Request, GitHub, Execute Command +1