AutomationFlowsGeneral › Regret Log

Regret Log

Regret Log. Scheduled trigger; 10 nodes.

Cron / scheduled trigger★★★★☆ complexity10 nodes
General Trigger: Cron / scheduled Nodes: 10 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": "Regret Log",
  "nodes": [
    {
      "id": "04eab4ca-4634-490a-ad1d-c5cc4362b3cc",
      "name": "Every Monday",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.3,
      "position": [
        0,
        208
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "weeks",
              "triggerAtDay": [
                1
              ],
              "triggerAtHour": 8
            }
          ]
        }
      }
    },
    {
      "id": "0776dda6-b485-4934-a9f8-74826a29d1c3",
      "name": "Load Every Approval A Human Saw",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        240,
        208
      ],
      "parameters": {
        "mode": "runOnceForAllItems",
        "jsCode": "const rows = [];\nconst spec = [\n  { category: 'Refund under 50 EUR', n: 420, overturned: 4, confidence: 0.71 },\n  { category: 'Refund over 500 EUR', n: 38, overturned: 21, confidence: 0.74 },\n  { category: 'Route ticket to a team', n: 1900, overturned: 22, confidence: 0.66 },\n  { category: 'Reply to an angry customer', n: 260, overturned: 148, confidence: 0.81 },\n  { category: 'Close duplicate ticket', n: 640, overturned: 9, confidence: 0.69 }\n];\nspec.forEach(function (s) {\n  rows.push({ category: s.category, seen: s.n, overturned: s.overturned, avg_confidence: s.confidence });\n});\nreturn [{ json: { window: 'last 90 days', decisions: rows, threshold_today: 0.95 } }];"
      }
    },
    {
      "id": "575e2261-6e58-4198-a1bd-d8deea3a02b4",
      "name": "How Often Did The Human Change Anything",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        480,
        208
      ],
      "parameters": {
        "mode": "runOnceForAllItems",
        "jsCode": "const d = $input.first().json;\nconst scored = d.decisions.map(function (c) {\n  const regret = c.overturned / c.seen;\n  let verdict = 'CALIBRATED';\n  let action = 'Leave the gate where it is.';\n  if (regret < 0.02) {\n    verdict = 'THEATRE';\n    action = 'The human changed nothing in ' + Math.round((1 - regret) * 100) + '% of cases. This gate is not review, it is a queue. Drop the threshold and let it through.';\n  } else if (regret > 0.4) {\n    verdict = 'SHOULD NOT BE AUTOMATED';\n    action = 'The human rewrote ' + Math.round(regret * 100) + '% of these. The model is not doing this job. Stop asking it to.';\n  }\n  return {\n    category: c.category, seen: c.seen, overturned: c.overturned,\n    regret_rate: Number(regret.toFixed(3)), verdict: verdict, action: action,\n    suggested_threshold: verdict === 'THEATRE' ? 0.6 : (verdict === 'SHOULD NOT BE AUTOMATED' ? 1.01 : 0.85),\n    escalations_removed_per_week: verdict === 'THEATRE' ? Math.round((c.seen - c.overturned) / 13) : 0\n  };\n});\nconst theatre = scored.filter(function (s) { return s.verdict === 'THEATRE'; });\nconst stop = scored.filter(function (s) { return s.verdict === 'SHOULD NOT BE AUTOMATED'; });\nconst saved = scored.reduce(function (a, s) { return a + s.escalations_removed_per_week; }, 0);\nconst worst = scored.slice().sort(function (a, b) { return b.regret_rate - a.regret_rate; })[0];\nconst say = 'One global approval threshold of ' + d.threshold_today + ' is applied to five very different decisions. ' +\n  theatre.length + ' of them are approval theatre - the human agreed with the model almost every time, so the gate only taught people to click Approve without reading. ' +\n  stop.length + ' should never have been automated: \\\"' + (worst ? worst.category : 'n/a') + '\\\" was rewritten ' + (worst ? Math.round(worst.regret_rate * 100) : 0) + '% of the time. ' +\n  'Setting the threshold per category instead of globally removes about ' + saved + ' pointless escalations a week and puts the attention where it changes an outcome.';\nconst headline = theatre.length > 0 ? 'theatre' : (stop.length > 0 ? 'stop' : 'calibrated');\nreturn [{ json: { plain_english: say, headline: headline, per_category: scored, escalations_removed_per_week: saved } }];"
      }
    },
    {
      "id": "ef62e5af-b00a-451b-80a8-591693c5cb45",
      "name": "What Should Change",
      "type": "n8n-nodes-base.switch",
      "typeVersion": 3.2,
      "position": [
        760,
        208
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "outputKey": "theatre",
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 2
                },
                "conditions": [
                  {
                    "id": "r1",
                    "leftValue": "={{ $json.headline }}",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "rightValue": "theatre"
                  }
                ],
                "combinator": "and"
              }
            },
            {
              "outputKey": "stop",
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 2
                },
                "conditions": [
                  {
                    "id": "r2",
                    "leftValue": "={{ $json.headline }}",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "rightValue": "stop"
                  }
                ],
                "combinator": "and"
              }
            },
            {
              "outputKey": "calibrated",
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 2
                },
                "conditions": [
                  {
                    "id": "r3",
                    "leftValue": "={{ $json.headline }}",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "rightValue": "calibrated"
                  }
                ],
                "combinator": "and"
              }
            }
          ]
        },
        "options": {}
      }
    },
    {
      "id": "dc8ceda8-9b7e-4e7b-8237-39cca2773697",
      "name": "LOWER THE GATE: Humans Are Rubber-Stamping",
      "type": "n8n-nodes-base.noOp",
      "typeVersion": 1,
      "position": [
        1020,
        32
      ],
      "parameters": {}
    },
    {
      "id": "aaa2398d-9e3a-4f16-b670-9c386e64af90",
      "name": "PULL THE STEP: Model Is Not Doing This Job",
      "type": "n8n-nodes-base.noOp",
      "typeVersion": 1,
      "position": [
        1020,
        208
      ],
      "parameters": {}
    },
    {
      "id": "d43c4d52-49e4-42a5-87bd-3ed02f9bb646",
      "name": "HOLD: Gate Is Earning Its Keep",
      "type": "n8n-nodes-base.noOp",
      "typeVersion": 1,
      "position": [
        1020,
        384
      ],
      "parameters": {}
    },
    {
      "id": "0bd816cb-70bc-46b4-914e-e2d5fd493e63",
      "name": "Sticky Note 2ba665b7",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -50,
        158
      ],
      "parameters": {
        "content": "## Regret Log - the approval gate that grades itself\n\nHuman-in-the-loop is in the JD. Everyone builds it the same way: an approval node with one confidence threshold, forever.\n\nNobody measures the only number that matters - **how often did the human actually change anything?**\n\nIf the answer is 1%, that gate is not review. It is a queue that trained people to click Approve without reading, which is worse than no gate because it manufactures the *appearance* of oversight.",
        "color": 4,
        "width": 540,
        "height": 200
      }
    },
    {
      "id": "ae6103ca-c2d7-4dac-939c-e4284207728d",
      "name": "Sticky Note 44e259c9",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        430,
        158
      ],
      "parameters": {
        "content": "## Regret rate splits into three, not two\n\n- **< 2% overturned -> THEATRE.** The human adds nothing. Lower the threshold and give them their attention back.\n- **> 40% overturned -> SHOULD NOT BE AUTOMATED.** The model is not doing this job. No prompt fixes this.\n- **In between -> CALIBRATED.** The gate is working. Leave it alone.\n\nOne threshold across five different decisions is the bug. Regret rate is what lets you set five.",
        "color": 3,
        "width": 580,
        "height": 200
      }
    },
    {
      "id": "75969540-8266-42e6-8cd3-4d2d0211b8cb",
      "name": "Sticky Note 2ade8018",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        970,
        158
      ],
      "parameters": {
        "content": "## The compounding bit\n\nEvery override is a free, perfectly-labelled training example that a human already paid for.\n\nToday that signal is thrown away the moment the button is clicked. Capture it and human-in-the-loop stops being a fixed tax and starts being **the mechanism by which the system earns more autonomy.**",
        "color": 5,
        "width": 300,
        "height": 376
      }
    }
  ],
  "connections": {
    "Every Monday": {
      "main": [
        [
          {
            "node": "Load Every Approval A Human Saw",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Load Every Approval A Human Saw": {
      "main": [
        [
          {
            "node": "How Often Did The Human Change Anything",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "How Often Did The Human Change Anything": {
      "main": [
        [
          {
            "node": "What Should Change",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "What Should Change": {
      "main": [
        [
          {
            "node": "LOWER THE GATE: Humans Are Rubber-Stamping",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "PULL THE STEP: Model Is Not Doing This Job",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "HOLD: Gate Is Earning Its Keep",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1"
  }
}
Pro

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

About this workflow

Regret Log. Scheduled trigger; 10 nodes.

Source: https://github.com/User0394934/trust-loop/blob/main/workflows/regret-log.json — original creator credit. Request a take-down →

More General workflows → · Browse all categories →

Related workflows

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

General

This template is an interactive playground designed to help you master the most useful keyboard shortcuts in n8n and supercharge your building speed. Forget boring lists—this workflow gives you hands-

General

Workflow 2469. Uses moveBinaryData, googleDrive, itemLists, n8n. Scheduled trigger; 33 nodes.

Move Binary Data, Google Drive, Item Lists +1
General

Perfect for content publishing with organic scheduling patterns, social media automation, API systems that need to avoid rate limiting, or any automation requiring randomised timing control across mul

n8n, Read Write File, Stop And Error +1
General

Complete backup solution that saves both workflows and credentials to local/server disk with optional FTP upload for off-site redundancy.

Read Write File, Email Send, Execute Command +3
General

todoist automate. Uses todoist, executionData. Scheduled trigger; 27 nodes.

Todoist, Execution Data