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 →
{
"name": "AIDP - Main Workflow v3",
"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.issue?.fields?.labels || []) }}",
"rightValue": "ai-task",
"operator": {
"type": "string",
"operation": "contains"
}
},
{
"id": "check-status",
"leftValue": "={{ $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": "const issue = $input.item.json.issue;\nconst fields = issue.fields;\n\nconst jiraKey = issue.key;\nconst projectKey = jiraKey.split('-')[0];\nconst summary = fields.summary;\n\nlet descriptionText = '';\nif (typeof fields.description === 'string') {\n descriptionText = fields.description;\n} else if (fields.description?.content) {\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 descriptionText = fields.description.content.map(extractText).join('\\n');\n}\n\nconst REPO_MAPPING = {\n 'SCRUM': 'https://github.com/andresKillem/aidp-test-repo',\n 'DEFAULT': 'https://github.com/andresKillem'\n};\n\nlet repoUrl = fields.customfield_10039;\nif (!repoUrl) {\n const githubMatch = descriptionText.match(/https:\\/\\/github\\.com\\/[\\w-]+\\/[\\w.-]+/);\n if (githubMatch) repoUrl = githubMatch[0].replace(/\\.git$/, '');\n}\nif (!repoUrl) repoUrl = REPO_MAPPING[projectKey] || REPO_MAPPING['DEFAULT'];\n\nconst baseBranch = fields.customfield_10040 || 'main';\n\nlet acceptanceCriteria = '';\nconst acMatch = descriptionText.match(/(?:acceptance criteria|ac)[:\\s]*([\\s\\S]*?)(?=##|$)/i);\nif (acMatch) acceptanceCriteria = acMatch[1].trim();\n\nconst slugify = (text) => text.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '').substring(0, 50);\nconst branchName = `ai/${jiraKey.toLowerCase()}-${slugify(summary)}`;\n\nconst repoMatch = repoUrl.match(/github\\.com\\/([^/]+)\\/([^/]+)/);\nconst owner = repoMatch ? repoMatch[1] : 'andresKillem';\nconst repo = repoMatch ? repoMatch[2].replace('.git', '') : 'aidp-test-repo';\n\nreturn {\n jiraKey,\n projectKey,\n jiraUrl: `https://polarpipeline.atlassian.net/browse/${jiraKey}`,\n summary,\n description: descriptionText,\n acceptanceCriteria,\n repoUrl,\n owner,\n repo,\n baseBranch,\n branchName,\n priority: fields.priority?.name || 'Medium',\n reporter: fields.reporter?.displayName || 'Unknown'\n};"
},
"id": "parse-issue",
"name": "Parse Issue Data",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
680,
300
]
},
{
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "const data = $input.item.json;\n\nconst prompt = `# Task: ${data.summary}\n\n## Context\n- Repository: ${data.repoUrl}\n- Base Branch: ${data.baseBranch}\n- Jira Issue: [${data.jiraKey}](${data.jiraUrl})\n- Feature Branch: ${data.branchName}\n\n## Requirements\n${data.description}\n\n## Acceptance Criteria\n${data.acceptanceCriteria || 'Use best judgment based on requirements.'}\n\n## Instructions\n1. Explore the codebase first\n2. Plan before coding\n3. Implement with tests\n4. Commit with conventional format\n5. Self-review before finishing\n\n## Constraints\n- DO NOT modify unrelated files\n- DO NOT create a PR - only commit and push\n- Keep changes minimal and focused`;\n\nreturn { ...data, prompt };"
},
"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 + '\" /dev/stdin \"' + $json.jiraKey + '\" \"' + $json.baseBranch + '\" <<\"AIDP_EOF\"\\n' + $json.prompt + '\\nAIDP_EOF' }}"
},
"id": "execute-claude",
"name": "Execute Claude Code",
"type": "n8n-nodes-base.executeCommand",
"typeVersion": 1,
"position": [
1120,
300
]
},
{
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "const input = $input.item.json;\nconst stdout = input.stdout || '';\nlet result;\n\ntry {\n const jsonMatch = stdout.match(/\\{[\\s\\S]*\"status\"[\\s\\S]*\\}/);\n if (jsonMatch) result = JSON.parse(jsonMatch[0]);\n else throw new Error('No JSON found');\n} catch (e) {\n result = { status: 'error', error_message: e.message, raw_output: stdout.substring(0, 1000) };\n}\n\nconst orig = $('Build Prompt').item.json;\nreturn { ...orig, executorResult: result, success: result.status === 'success' };"
},
"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' + ($json.executorResult.claude_summary || 'See commits') + '\\n\\n---\\n\ud83e\udd16 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 { ...orig, prNumber: pr.number, prUrl: pr.html_url };"
},
"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*\\n\\n\ud83d\udd17 Pull Request: [PR #' + $json.prNumber + '](' + $json.prUrl + ')\\n\\nBranch: `' + $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\\nError: ' + ($json.executorResult?.error_message || 'Unknown error') + '\\n\\n_Please review 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 }) }}"
},
"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
}
}
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.
githubApijiraSoftwareCloudApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
AIDP - Main Workflow v3. Uses executeCommand, github, jira. Webhook trigger; 12 nodes.
Source: https://github.com/andresKillem/aidp/blob/8839fb212f6336a3aa9793485da729542e0fd7da/n8n-workflows/main-workflow-v3.json — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
This n8n workflow template uses community nodes and is only compatible with the self-hosted version of n8n.
GitHub PR Deep-Link & Routing Validator (n8n + ExecuteCommand + GitHub Comment). Uses executeCommand, github. Webhook trigger; 5 nodes.
🔥 n8n Members Sale – n8n Community Members Get ideoGener8r for Just $10! (Reg. $15) Use Coupon Code: (Valid for n8n community members)
Code Github. Uses manualTrigger, stickyNote, httpRequest, noOp. Event-driven trigger; 24 nodes.
This n8n workflow template uses community nodes and is only compatible with the self-hosted version of n8n.