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": "Zero Risk \u2014 Ad Creative Brief (creative-director)",
"_meta": {
"version": "1.0-skeleton",
"purpose": "Triggered after Campaign Brief Agent emits a brief. Creative Director reads the brief, the client's Brand Book, and the campaign objective, then expands into 3-5 creative directions (concept + visual mood + copy hook) ready for content-creator and video-editor pickup.",
"owner_agent": "creative-director",
"outputs_to": "creative_directions table (or content table with type='creative_direction')",
"status": "skeleton \u00b7 spec ready \u00b7 NOT yet activated"
},
"nodes": [
{
"parameters": {
"httpMethod": "POST",
"path": "zero-risk/ad-creative-brief",
"responseMode": "responseNode",
"options": {}
},
"id": "webhook-trigger",
"name": "Webhook: Campaign Brief Ready",
"type": "n8n-nodes-base.webhook",
"typeVersion": 2,
"position": [
240,
300
]
},
{
"parameters": {
"jsCode": "const b = $input.first().json.body || $input.first().json;\nconst missing = [];\nif (!b.client_id) missing.push('client_id');\nif (!b.campaign_brief_id) missing.push('campaign_brief_id');\nif (missing.length) throw new Error(`Missing: ${missing.join(', ')}`);\nreturn [{ json: { client_id: b.client_id, campaign_brief_id: b.campaign_brief_id, n_directions: b.n_directions || 3 } }];"
},
"id": "validate",
"name": "Validate Input",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
480,
300
]
},
{
"parameters": {
"method": "GET",
"url": "={{ $env.NEXT_PUBLIC_SUPABASE_URL }}/rest/v1/campaign_briefs?id=eq.{{ $json.campaign_brief_id }}&select=*",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "apikey",
"value": "={{ $env.SUPABASE_SERVICE_ROLE_KEY }}"
},
{
"name": "Authorization",
"value": "=Bearer {{ $env.SUPABASE_SERVICE_ROLE_KEY }}"
}
]
},
"options": {}
},
"id": "fetch-brief",
"name": "Fetch Campaign Brief",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
720,
240
]
},
{
"parameters": {
"method": "GET",
"url": "={{ $env.ZERO_RISK_API_URL || 'https://zero-risk-platform.vercel.app' }}/api/brand-book/{{ $node['Validate Input'].json.client_id }}",
"options": {}
},
"id": "fetch-brand-book",
"name": "Fetch Brand Book",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
720,
360
]
},
{
"parameters": {
"jsCode": "const brief = ($node['Fetch Campaign Brief'].json[0]) || {};\nconst brandBook = $node['Fetch Brand Book'].json.brand_book || {};\nconst n = $node['Validate Input'].json.n_directions;\nconst task = `Read the following Campaign Brief and Brand Book and produce ${n} distinct Creative Directions for an ad campaign. Each direction must include: concept_name, big_idea, visual_mood (3-5 keywords), copy_hook (max 80 chars), recommended_channels, target_segment_id (if Brief specifies). Output strict JSON: { directions: [...] }.\\n\\n=== CAMPAIGN BRIEF ===\\n${JSON.stringify(brief)}\\n\\n=== BRAND BOOK ===\\nVoice: ${brandBook.voice_description || ''}\\nTagline: ${brandBook.tagline || ''}\\nKey messages: ${JSON.stringify(brandBook.key_messages || [])}\\nForbidden: ${JSON.stringify(brandBook.forbidden_words || [])}`;\nreturn [{ json: { task, client_id: $node['Validate Input'].json.client_id, campaign_brief_id: $node['Validate Input'].json.campaign_brief_id } }];"
},
"id": "build-task",
"name": "Build Creative Director Task",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
960,
300
]
},
{
"parameters": {
"method": "POST",
"url": "={{ $env.ZERO_RISK_API_URL || 'https://zero-risk-platform.vercel.app' }}/api/agents/run",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
},
{
"name": "x-api-key",
"value": "={{ $env.INTERNAL_API_KEY }}"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"agent\": \"creative-director\",\n \"task\": {{ JSON.stringify($json.task) }},\n \"client_id\": \"{{ $json.client_id }}\",\n \"step_name\": \"ad_creative_brief\"\n}",
"options": {
"timeout": 180000
}
},
"id": "invoke-creative-director",
"name": "Invoke creative-director (auto dual-review)",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
1200,
300
]
},
{
"parameters": {
"jsCode": "const raw = $input.first().json.response || '';\nconst m = raw.match(/\\{[\\s\\S]*\\}/);\nif (!m) throw new Error('creative-director did not return JSON');\nconst parsed = JSON.parse(m[0]);\nconst directions = parsed.directions || [];\nreturn directions.map(d => ({ json: { ...d, client_id: $node['Validate Input'].json.client_id, campaign_brief_id: $node['Validate Input'].json.campaign_brief_id } }));"
},
"id": "split-directions",
"name": "Split into N directions",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1440,
300
]
},
{
"parameters": {
"method": "POST",
"url": "={{ $env.NEXT_PUBLIC_SUPABASE_URL }}/rest/v1/content",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "apikey",
"value": "={{ $env.SUPABASE_SERVICE_ROLE_KEY }}"
},
{
"name": "Authorization",
"value": "=Bearer {{ $env.SUPABASE_SERVICE_ROLE_KEY }}"
},
{
"name": "Content-Type",
"value": "application/json"
},
{
"name": "Prefer",
"value": "return=representation"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={{ JSON.stringify({ title: $json.concept_name, body: JSON.stringify($json), type: 'creative_direction', status: 'draft', campaign_id: $json.campaign_brief_id, generated_by: 'creative-director' }) }}",
"options": {}
},
"id": "persist-directions",
"name": "Persist each direction",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
1680,
300
]
},
{
"parameters": {
"respondWith": "json",
"responseBody": "={\n \"success\": true,\n \"client_id\": \"{{ $node['Validate Input'].json.client_id }}\",\n \"directions_created\": {{ $node['Split into N directions'].json.length }}\n}",
"options": {
"responseCode": 200
}
},
"id": "respond",
"name": "Respond",
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1.1,
"position": [
1920,
300
]
}
],
"connections": {
"Webhook: Campaign Brief Ready": {
"main": [
[
{
"node": "Validate Input",
"type": "main",
"index": 0
}
]
]
},
"Validate Input": {
"main": [
[
{
"node": "Fetch Campaign Brief",
"type": "main",
"index": 0
},
{
"node": "Fetch Brand Book",
"type": "main",
"index": 0
}
]
]
},
"Fetch Campaign Brief": {
"main": [
[
{
"node": "Build Creative Director Task",
"type": "main",
"index": 0
}
]
]
},
"Fetch Brand Book": {
"main": [
[
{
"node": "Build Creative Director Task",
"type": "main",
"index": 0
}
]
]
},
"Build Creative Director Task": {
"main": [
[
{
"node": "Invoke creative-director (auto dual-review)",
"type": "main",
"index": 0
}
]
]
},
"Invoke creative-director (auto dual-review)": {
"main": [
[
{
"node": "Split into N directions",
"type": "main",
"index": 0
}
]
]
},
"Split into N directions": {
"main": [
[
{
"node": "Persist each direction",
"type": "main",
"index": 0
}
]
]
},
"Persist each direction": {
"main": [
[
{
"node": "Respond",
"type": "main",
"index": 0
}
]
]
}
},
"settings": {
"executionOrder": "v1",
"saveManualExecutions": true
},
"tags": [
{
"name": "zero-risk",
"id": "1"
},
{
"name": "creative-director",
"id": "12"
},
{
"name": "campaign",
"id": "13"
}
],
"triggerCount": 1,
"versionId": "1"
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Zero Risk — Ad Creative Brief (creative-director). Uses httpRequest. Webhook trigger; 9 nodes.
Source: https://github.com/emilacho/zero-risk-platform/blob/b91d7e73029d184db13fbe29c410317e2a267070/n8n-workflows/ad-creative-brief.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 template provides enterprise-level version control for your workflows using GitHub integration. Stop losing hours to broken workflows and manual exports – get proper commit history, visual di
This flow creates dummy files for every item added in your *Arrs (Radarr/Sonarr) with the tag .
eek-Go v2 (Batch-Then-Review). Uses httpRequest. Webhook trigger; 75 nodes.
This workflow receives webhook requests from a content calendar and uses the X API v2 to publish text posts, threads, image/video posts, and polls, as well as delete existing posts and run a credentia
This workflow acts as a central API gateway for all technical indicator agents in the Binance Spot Market Quant AI system. It listens for incoming webhook requests and dynamically routes them to the c