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": "Triple Pendulum Pipeline Orchestrator",
"nodes": [
{
"parameters": {
"httpMethod": "POST",
"path": "triple-pendulum-pipeline",
"responseMode": "onReceived",
"options": {}
},
"id": "a1b2c3d4-0001-0001-0001-000000000001",
"name": "Training Complete",
"type": "n8n-nodes-base.webhook",
"typeVersion": 2,
"position": [
240,
300
]
},
{
"parameters": {
"language": "javaScript",
"jsCode": "// ---- CONFIG ----\nconst PIPELINE_SECRET = 'YOUR_PIPELINE_SECRET';\nconst LAUNCHER_SECRET = 'YOUR_LAUNCHER_SECRET';\nconst LAUNCHER_URL = 'http://10.1.4.232:8765/launch';\nconst TELEGRAM_BOT_URL = 'https://api.telegram.org/botYOUR_TELEGRAM_BOT_TOKEN/sendMessage';\nconst TELEGRAM_CHAT_ID = 935389847;\n\n// ---- STAGE DEFINITIONS ----\nconst STAGES = {\n M2: {\n pass_criteria: { ep7_success_rate: 0.80 },\n pass: { stage: 'M3b', config: 'training/configs/m3b_all_eps_tqc.yaml', module: 'training.train_m3_all_eps' },\n fail: { stage: 'HUMAN_REVIEW', note: 'M2 failed \u2014 manual intervention required' }\n },\n M3: {\n pass_criteria: { overall_success_rate: 0.75 },\n pass: { stage: 'M3b', config: 'training/configs/m3b_all_eps_tqc.yaml', module: 'training.train_m3_all_eps' },\n fail: { stage: 'M3b', config: 'training/configs/m3b_all_eps_tqc.yaml', module: 'training.train_m3_all_eps' }\n },\n M3b: {\n pass_criteria: { overall_success_rate: 0.75 },\n pass: { stage: 'M4', config: 'training/configs/m4_transitions_tqc.yaml', module: 'training.train_m4_transitions', note: 'Set pretrained_policy in config before launch' },\n fail: { stage: 'M3c', config: 'training/configs/m3c_all_eps_tqc.yaml', module: 'training.train_m3_all_eps' }\n },\n M3c: {\n pass_criteria: { overall_success_rate: 0.75 },\n pass: { stage: 'M4', config: 'training/configs/m4_transitions_tqc.yaml', module: 'training.train_m4_transitions', note: 'Set pretrained_policy in config before launch' },\n fail: { stage: 'HUMAN_REVIEW', note: 'M3c failed \u2014 hyperparameter tuning needed' }\n },\n M4: {\n pass_criteria: { overall_success_rate: 0.80 },\n pass: { stage: 'HUMAN_REVIEW', note: 'M4 passed (\u2265 80% over 56 transitions) \u2014 proceed to M5 domain randomization' },\n fail: { stage: 'HUMAN_REVIEW', note: 'M4 failed \u2014 extend budget or tune curriculum' }\n }\n};\n\n// ---- VALIDATE SECRET (constant-time, n8n disallows crypto module) ----\nconst _raw = $input.first().json;\nconst body = _raw.body || _raw;\nconst incomingSecret = String(body.pipeline_secret || '');\nfunction safeEqual(a, b) {\n if (a.length !== b.length) return false;\n let mismatch = 0;\n for (let i = 0; i < a.length; i++) mismatch |= a.charCodeAt(i) ^ b.charCodeAt(i);\n return mismatch === 0;\n}\nif (!safeEqual(incomingSecret, PIPELINE_SECRET)) {\n throw new Error('Invalid pipeline secret');\n}\n\n// ---- PARSE ----\nconst milestone = body.milestone || 'UNKNOWN';\nconst metrics = body.metrics || {};\nconst runName = body.run_name || 'unknown';\nconst runId = body.run_id || 'unknown';\n\n// ---- EVALUATE ----\nconst stageDef = STAGES[milestone];\nlet passed = false;\nlet next = { stage: 'HUMAN_REVIEW', note: 'Stage not defined' };\nlet reasons = [];\n\nif (stageDef) {\n const criteria = stageDef.pass_criteria;\n const checks = Object.entries(criteria).map(([k, threshold]) => {\n const actual = typeof metrics[k] === 'number' ? metrics[k] : 0;\n const ok = actual >= threshold;\n reasons.push(`${k}: ${(actual*100).toFixed(0)}% (need ${(threshold*100).toFixed(0)}%) ${ok ? '\\u2705' : '\\u274c'}`);\n return ok;\n });\n passed = checks.every(Boolean);\n next = passed ? stageDef.pass : stageDef.fail;\n} else {\n reasons.push(`unknown milestone: ${milestone} \\u274c`);\n next = { stage: 'HUMAN_REVIEW', note: `Unknown milestone '${milestone}' \u2014 add it to STAGES.` };\n}\n\n// ---- LAUNCH PAYLOAD ----\nconst canLaunch = next.stage && next.stage !== 'HUMAN_REVIEW' && next.module && next.config;\nconst launchPayload = canLaunch ? { secret: LAUNCHER_SECRET, module: next.module, config: next.config } : null;\n\n// ---- TELEGRAM MESSAGE ----\nconst bars = [0,1,2,3,4,5,6,7].map(i => {\n const sr = metrics['ep' + i + '_success_rate'];\n const b = typeof sr === 'number' ? (sr >= 0.8 ? '\\uD83D\\uDFE2' : sr >= 0.5 ? '\\uD83D\\uDFE1' : '\\uD83D\\uDD34') : '\\u25A1';\n return 'EP' + i + ': ' + b + ' ' + (typeof sr === 'number' ? (sr*100).toFixed(0) + '%' : 'n/a');\n}).join(' ');\n\nconst icon = passed ? '\\u2705' : '\\u26A0\\uFE0F';\nconst lines = [\n '*Triple Pendulum \u2014 ' + milestone + ' ' + icon + '*',\n 'Run: `' + runName + '`',\n '',\n '*Criteria:*',\n reasons.join('\\n'),\n '',\n '*Per-EP success:*',\n bars,\n '',\n canLaunch\n ? '*Next: launching ' + next.stage + '*\\n`' + next.config + '`'\n : '*Next: ' + next.stage + '*\\n' + (next.note || '')\n];\nconst message = lines.join('\\n');\n\nreturn [{ json: {\n milestone, runName, runId, passed, next, launchPayload, hasNextStage: canLaunch, message,\n telegramBotUrl: TELEGRAM_BOT_URL,\n telegramChatId: TELEGRAM_CHAT_ID,\n launcherUrl: LAUNCHER_URL,\n metrics\n} }];\n"
},
"id": "a1b2c3d4-0002-0002-0002-000000000002",
"name": "Evaluate & Route",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
480,
300
]
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"id": "cond-launch",
"leftValue": "={{ $json.hasNextStage }}",
"rightValue": true,
"operator": {
"type": "boolean",
"operation": "equals"
}
}
],
"combinator": "and"
},
"options": {}
},
"id": "a1b2c3d4-0003-0003-0003-000000000003",
"name": "Has Next Stage?",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
720,
300
]
},
{
"parameters": {
"method": "POST",
"url": "={{ $('Evaluate & Route').first().json.launcherUrl }}",
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={{ JSON.stringify($('Evaluate & Route').first().json.launchPayload) }}",
"options": {
"timeout": 10000
}
},
"id": "a1b2c3d4-0004-0004-0004-000000000004",
"name": "Launch Next Training",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
960,
160
]
},
{
"parameters": {
"method": "POST",
"url": "={{ $('Evaluate & Route').first().json.telegramBotUrl }}",
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={{ JSON.stringify({ chat_id: $('Evaluate & Route').first().json.telegramChatId, text: $('Evaluate & Route').first().json.message, parse_mode: 'Markdown', disable_web_page_preview: true }) }}",
"options": {
"timeout": 10000
}
},
"id": "a1b2c3d4-0005-0005-0005-000000000005",
"name": "Telegram Notify",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
1200,
300
]
}
],
"connections": {
"Training Complete": {
"main": [
[
{
"node": "Evaluate & Route",
"type": "main",
"index": 0
}
]
]
},
"Evaluate & Route": {
"main": [
[
{
"node": "Has Next Stage?",
"type": "main",
"index": 0
}
]
]
},
"Has Next Stage?": {
"main": [
[
{
"node": "Launch Next Training",
"type": "main",
"index": 0
}
],
[
{
"node": "Telegram Notify",
"type": "main",
"index": 0
}
]
]
},
"Launch Next Training": {
"main": [
[
{
"node": "Telegram Notify",
"type": "main",
"index": 0
}
]
]
},
"Telegram Notify": {
"main": [
[]
]
}
},
"settings": {
"executionOrder": "v1",
"callerPolicy": "workflowsFromSameOwner",
"availableInMCP": false
}
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Triple Pendulum Pipeline Orchestrator. Uses httpRequest. Webhook trigger; 5 nodes.
Source: https://github.com/fawraw/triple-pendulum-sim2real/blob/main/n8n/triple_pendulum_pipeline.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 .
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
Sign PDF documents with legally-compliant digital signatures using X.509 certificates. Supports multiple PAdES signature levels (B, T, LT, LTA) with optional visible stamps.
📡 This workflow serves as the central Alpha Vantage API fetcher for Tesla trading indicators, delivering cleaned 20-point JSON outputs for three timeframes: , , and . It is required by the following a