{
  "name": "Long-Running Agent with Reset and Handoff Notes",
  "nodes": [
    {
      "id": "b88bcda5-64b2-45c0-b420-90f9cf722cde",
      "name": "Start",
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [
        0,
        100
      ],
      "parameters": {}
    },
    {
      "id": "cb63ea69-5d20-4ff8-a131-fd6d022e152f",
      "name": "Config",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        200,
        100
      ],
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "c0",
              "name": "arms",
              "value": "reset,baseline",
              "type": "string"
            },
            {
              "id": "c1",
              "name": "model",
              "value": "deepseek-flash",
              "type": "string"
            },
            {
              "id": "c2",
              "name": "max_rounds",
              "value": 8,
              "type": "number"
            },
            {
              "id": "c3",
              "name": "reset_every",
              "value": 3,
              "type": "number"
            },
            {
              "id": "c4",
              "name": "max_history_tokens",
              "value": 6000,
              "type": "number"
            },
            {
              "id": "c5",
              "name": "marks",
              "value": 10,
              "type": "number"
            },
            {
              "id": "c6",
              "name": "max_value",
              "value": 50,
              "type": "number"
            },
            {
              "id": "c7",
              "name": "usd_per_1m_hit",
              "value": 0.003,
              "type": "number"
            },
            {
              "id": "c8",
              "name": "usd_per_1m_miss",
              "value": 0.15,
              "type": "number"
            },
            {
              "id": "c9",
              "name": "usd_per_1m_out",
              "value": 0.6,
              "type": "number"
            }
          ]
        },
        "options": {}
      }
    },
    {
      "id": "b7f70013-a7ae-4577-bfc4-5d5c1b859a8e",
      "name": "Create table",
      "type": "n8n-nodes-base.dataTable",
      "typeVersion": 1.1,
      "position": [
        400,
        100
      ],
      "parameters": {
        "resource": "table",
        "operation": "create",
        "tableName": "ctx_handoff",
        "columns": {
          "column": [
            {
              "name": "run_id",
              "type": "string"
            },
            {
              "name": "arm",
              "type": "string"
            },
            {
              "name": "kind",
              "type": "string"
            },
            {
              "name": "round",
              "type": "number"
            },
            {
              "name": "session",
              "type": "number"
            },
            {
              "name": "score",
              "type": "number"
            },
            {
              "name": "best_score",
              "type": "number"
            },
            {
              "name": "artifact",
              "type": "string"
            },
            {
              "name": "repeats",
              "type": "string"
            },
            {
              "name": "text",
              "type": "string"
            },
            {
              "name": "prompt_tokens",
              "type": "number"
            },
            {
              "name": "cache_hit_tokens",
              "type": "number"
            },
            {
              "name": "cache_miss_tokens",
              "type": "number"
            },
            {
              "name": "output_tokens",
              "type": "number"
            }
          ]
        },
        "options": {
          "createIfNotExists": true
        }
      }
    },
    {
      "id": "812dab87-43ba-449f-9020-cfbe861900df",
      "name": "Start arm",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        600,
        100
      ],
      "parameters": {
        "jsCode": "// Starts one experiment arm. Round 1 is played once and shared: later arms fork\n// from it, so both arms are identical up to their first different decision.\nconst cfg = $('Config').first().json;\nconst prev = $input.first().json;\nconst allowed = ['reset', 'baseline'];\nconst arms = String(cfg.arms).split(',').map(s => s.trim()).filter(Boolean);\nif (!arms.length || arms.some(a => !allowed.includes(a)))\n  throw new Error(`Config.arms must list only \"reset\" and/or \"baseline\", got \"${cfg.arms}\"`);\nif (!Number.isInteger(cfg.reset_every) || cfg.reset_every < 1) throw new Error('Config.reset_every must be an integer >= 1');\nif (!Number.isInteger(cfg.max_rounds) || cfg.max_rounds < 2) throw new Error('Config.max_rounds must be an integer >= 2');\nconst queue = Array.isArray(prev.arms_left) ? prev.arms_left : arms;\nconst [arm, ...rest] = queue;\nconst fork = prev.fork || null;   // shared round 1, set by Score\nreturn [{ json: {\n  run_id: prev.run_id || 'run-' + $execution.id,\n  arm,                 // 'reset' = clear history + handoff note; 'baseline' = keep everything\n  arms_left: rest,\n  round: fork ? 1 : 0,\n  session: 1,\n  history: fork ? fork.history : [],   // the conversation: this is what a reset deletes\n  handoff: '',\n  best: fork ? fork.best : null,       // best artifact so far (environment, survives resets)\n  feedback: fork ? fork.feedback : '',\n  fork,\n} }];\n"
      }
    },
    {
      "id": "4ceb5f2d-dc9b-440d-a78d-51ca38cf8929",
      "name": "Build prompt",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        800,
        100
      ],
      "parameters": {
        "jsCode": "// Builds the next request: system task + this session's history + a new user turn.\nconst cfg = $('Config').first().json;\nconst s = $input.first().json;\nconst K = cfg.marks, M = cfg.max_value, MAX = K * (K - 1) / 2;\nconst system = `You are working on a puzzle over many rounds. Pick exactly ${K} distinct integers from 0 to ${M}. ` +\n  `Score = how many DIFFERENT values occur among all ${MAX} pairwise differences |a-b|. ` +\n  `Each round, propose one complete set. ` +\n  `Reply only with JSON: {\"marks\":[${K} integers],\"idea\":\"one short sentence: what you changed and why\"}`;\nconst round = s.round + 1;\nconst bestLine = s.best\n  ? `Best set so far: ${JSON.stringify(s.best.marks)} (score ${s.best.score}/${MAX}). Its repeated differences: ${s.best.repeats}.`\n  : `No valid set yet.`;\nlet user;\nif (s.history.length === 0) {\n  user = `Round ${round}. You start with a fresh context.`;\n  if (s.handoff) user += `\\nHandoff note from your previous session:\\n${s.handoff}`;\n  if (s.best) user += `\\n${bestLine}`;\n  user += `\\nPropose a set.`;\n} else {\n  // Same information for both arms: last feedback + best set with its repeats.\n  user = `Round ${round}. ${s.feedback}\\n${bestLine}\\nPropose an improved set.`;\n}\nconst history = [...s.history, { role: 'user', content: user }];\nreturn [{ json: { ...s, round, system, history, body: {\n  model: cfg.model,\n  thinking: { type: 'disabled' },\n  response_format: { type: 'json_object' },\n  max_tokens: 300,\n  messages: [{ role: 'system', content: system }, ...history],\n} } }];\n"
      }
    },
    {
      "id": "e4c5ffae-fae9-46ce-83cc-1ffc04df7440",
      "name": "DeepSeek",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.5,
      "position": [
        1000,
        100
      ],
      "parameters": {
        "method": "POST",
        "url": "https://api.deepseek.com/chat/completions",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "deepSeekApi",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify($json.body) }}",
        "options": {
          "timeout": 120000
        }
      },
      "credentials": {
        "deepSeekApi": {
          "name": "DeepSeek account"
        }
      },
      "retryOnFail": true,
      "waitBetweenTries": 3000,
      "onError": "continueRegularOutput"
    },
    {
      "id": "5be40bb1-e91d-4d2a-9c66-f07660d787db",
      "name": "Score",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1200,
        100
      ],
      "parameters": {
        "jsCode": "// Deterministic score: number of distinct pairwise differences.\nconst cfg = $('Config').first().json;\nconst s = $('Build prompt').last().json;\nconst r = $input.first().json;\nconst K = cfg.marks, M = cfg.max_value, MAX = K * (K - 1) / 2;\nconst apiError = !Array.isArray(r.choices);\nconst content = r.choices?.[0]?.message?.content ?? '';\nlet marks = null, idea = '', problem = '';\nif (apiError) problem = 'API error';\nelse {\n  try { const p = JSON.parse(content); marks = p.marks; idea = String(p.idea ?? ''); }\n  catch (e) { problem = 'the reply was not valid JSON'; }\n}\nif (!problem) {\n  if (!Array.isArray(marks) || marks.length !== K) problem = `it needs exactly ${K} numbers`;\n  else if (marks.some(x => !Number.isInteger(x) || x < 0 || x > M)) problem = `all numbers must be integers 0..${M}`;\n  else if (new Set(marks).size !== K) problem = 'the numbers must be distinct';\n}\nlet score = 0, repeats = '';\nif (!problem) {\n  marks = [...marks].sort((a, b) => a - b);\n  const seen = {};\n  for (let i = 0; i < K; i++) for (let j = i + 1; j < K; j++) {\n    const d = marks[j] - marks[i];\n    (seen[d] = seen[d] || []).push(`${marks[j]}-${marks[i]}`);\n  }\n  score = Object.keys(seen).length;\n  repeats = Object.entries(seen).filter(([, p]) => p.length > 1)\n    .map(([d, p]) => `${d} (${p.join(', ')})`).join('; ') || 'none';\n}\nconst feedback = apiError\n  ? `The last request failed (API error), so that round has no score.`\n  : problem\n    ? `Your last answer was invalid: ${problem}. Score 0.`\n    : `Your set ${JSON.stringify(marks)} scored ${score}/${MAX}. Repeated differences: ${repeats}.`;\nlet best = s.best;\nif (score > 0 && (!best || score > best.score)) best = { marks, score, repeats, round: s.round };\nconst u = r.usage || {};\nconst history = [...s.history, { role: 'assistant', content: content || '(no reply)' }];\n// Round 1 is played once (by the first arm) and shared: the other arms fork from here.\nconst shared = !s.fork && s.round === 1;\nconst fork = s.fork || (shared ? { history, best, feedback } : null);\n// When to forget: every reset_every rounds, or when the prompt has grown too big.\nlet action = 'continue';\nif (s.round >= cfg.max_rounds) action = 'finish';\nelse if (s.arm === 'reset' && (s.round % cfg.reset_every === 0 || (u.prompt_tokens || 0) > cfg.max_history_tokens)) action = 'reset';\nconst { body, ...state } = s;\nreturn [{ json: {\n  ...state,\n  history, best, feedback, action, fork,\n  row: {\n    run_id: s.run_id, arm: shared ? 'shared' : s.arm, kind: 'attempt', round: s.round, session: s.session,\n    score, best_score: best ? best.score : 0, artifact: JSON.stringify(marks), repeats,\n    text: apiError ? `API ERROR: ${JSON.stringify(r.error ?? r).slice(0, 300)}` : problem ? `INVALID: ${problem}` : idea,\n    prompt_tokens: u.prompt_tokens || 0, cache_hit_tokens: u.prompt_cache_hit_tokens || 0,\n    cache_miss_tokens: u.prompt_cache_miss_tokens || 0, output_tokens: u.completion_tokens || 0,\n  },\n} }];\n"
      }
    },
    {
      "id": "292a5209-a1ca-4a47-ba4c-a9a039969292",
      "name": "Log round",
      "type": "n8n-nodes-base.dataTable",
      "typeVersion": 1.1,
      "position": [
        1400,
        100
      ],
      "parameters": {
        "resource": "row",
        "operation": "insert",
        "dataTableId": {
          "__rl": true,
          "mode": "name",
          "value": "ctx_handoff"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "run_id": "={{ $json.row.run_id }}",
            "arm": "={{ $json.row.arm }}",
            "kind": "={{ $json.row.kind }}",
            "round": "={{ $json.row.round }}",
            "session": "={{ $json.row.session }}",
            "score": "={{ $json.row.score }}",
            "best_score": "={{ $json.row.best_score }}",
            "artifact": "={{ $json.row.artifact }}",
            "repeats": "={{ $json.row.repeats }}",
            "text": "={{ $json.row.text }}",
            "prompt_tokens": "={{ $json.row.prompt_tokens }}",
            "cache_hit_tokens": "={{ $json.row.cache_hit_tokens }}",
            "cache_miss_tokens": "={{ $json.row.cache_miss_tokens }}",
            "output_tokens": "={{ $json.row.output_tokens }}"
          },
          "matchingColumns": [],
          "schema": [
            {
              "id": "run_id",
              "displayName": "run_id",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "arm",
              "displayName": "arm",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "kind",
              "displayName": "kind",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "round",
              "displayName": "round",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "number",
              "canBeUsedToMatch": true
            },
            {
              "id": "session",
              "displayName": "session",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "number",
              "canBeUsedToMatch": true
            },
            {
              "id": "score",
              "displayName": "score",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "number",
              "canBeUsedToMatch": true
            },
            {
              "id": "best_score",
              "displayName": "best_score",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "number",
              "canBeUsedToMatch": true
            },
            {
              "id": "artifact",
              "displayName": "artifact",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "repeats",
              "displayName": "repeats",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "text",
              "displayName": "text",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "prompt_tokens",
              "displayName": "prompt_tokens",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "number",
              "canBeUsedToMatch": true
            },
            {
              "id": "cache_hit_tokens",
              "displayName": "cache_hit_tokens",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "number",
              "canBeUsedToMatch": true
            },
            {
              "id": "cache_miss_tokens",
              "displayName": "cache_miss_tokens",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "number",
              "canBeUsedToMatch": true
            },
            {
              "id": "output_tokens",
              "displayName": "output_tokens",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "number",
              "canBeUsedToMatch": true
            }
          ]
        },
        "options": {}
      }
    },
    {
      "id": "d03783e7-4c96-43f2-ae07-11cfb376ed78",
      "name": "Keep state",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1600,
        100
      ],
      "parameters": {
        "jsCode": "// The Data Table node outputs the stored row; carry the loop state forward instead.\nreturn [{ json: $('Score').last().json }];\n"
      }
    },
    {
      "id": "de3002e9-bd58-496b-94dd-69b64b777c16",
      "name": "Next step",
      "type": "n8n-nodes-base.switch",
      "typeVersion": 3.2,
      "position": [
        1800,
        100
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 2
                },
                "conditions": [
                  {
                    "id": "r_continue",
                    "leftValue": "={{ $json.action }}",
                    "rightValue": "continue",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "continue"
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 2
                },
                "conditions": [
                  {
                    "id": "r_reset",
                    "leftValue": "={{ $json.action }}",
                    "rightValue": "reset",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "reset"
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "strict",
                  "version": 2
                },
                "conditions": [
                  {
                    "id": "r_finish",
                    "leftValue": "={{ $json.action }}",
                    "rightValue": "finish",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "finish"
            }
          ]
        },
        "options": {}
      }
    },
    {
      "id": "c891a802-4d96-43c9-b343-c04653118402",
      "name": "Write note",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.5,
      "position": [
        1000,
        360
      ],
      "parameters": {
        "method": "POST",
        "url": "https://api.deepseek.com/chat/completions",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "deepSeekApi",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify({\n  model: $('Config').first().json.model,\n  thinking: { type: 'disabled' },\n  response_format: { type: 'json_object' },\n  max_tokens: 250,\n  messages: [\n    { role: 'system', content: $json.system },\n    ...$json.history,\n    { role: 'user', content: $json.feedback + '\\nYour conversation is now deleted. A fresh session continues with only the task, your note and the best set so far. Do not repeat the best set; it is attached separately. Write a handoff note of at most 80 words: what you tried, what did not work, which ideas are still untried. Reply only with JSON: {\\\"note\\\":\\\"...\\\"}' }\n  ]\n}) }}",
        "options": {
          "timeout": 120000
        }
      },
      "credentials": {
        "deepSeekApi": {
          "name": "DeepSeek account"
        }
      },
      "retryOnFail": true,
      "waitBetweenTries": 3000,
      "onError": "continueRegularOutput"
    },
    {
      "id": "3ac96283-0071-4097-a132-2a716a94f118",
      "name": "Save note",
      "type": "n8n-nodes-base.dataTable",
      "typeVersion": 1.1,
      "position": [
        1200,
        360
      ],
      "parameters": {
        "resource": "row",
        "operation": "insert",
        "dataTableId": {
          "__rl": true,
          "mode": "name",
          "value": "ctx_handoff"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "run_id": "={{ $('Keep state').last().json.run_id }}",
            "arm": "={{ $('Keep state').last().json.arm }}",
            "kind": "note",
            "round": "={{ $('Keep state').last().json.round }}",
            "session": "={{ $('Keep state').last().json.session }}",
            "score": 0,
            "best_score": "={{ $('Keep state').last().json.row.best_score }}",
            "artifact": "",
            "repeats": "",
            "text": "={{ (() => { const c = $json.choices?.[0]?.message?.content ?? ''; try { return JSON.parse(c).note || c; } catch (e) { return c; } })() }}",
            "prompt_tokens": "={{ $json.usage?.prompt_tokens ?? 0 }}",
            "cache_hit_tokens": "={{ $json.usage?.prompt_cache_hit_tokens ?? 0 }}",
            "cache_miss_tokens": "={{ $json.usage?.prompt_cache_miss_tokens ?? 0 }}",
            "output_tokens": "={{ $json.usage?.completion_tokens ?? 0 }}"
          },
          "matchingColumns": [],
          "schema": [
            {
              "id": "run_id",
              "displayName": "run_id",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "arm",
              "displayName": "arm",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "kind",
              "displayName": "kind",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "round",
              "displayName": "round",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "number",
              "canBeUsedToMatch": true
            },
            {
              "id": "session",
              "displayName": "session",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "number",
              "canBeUsedToMatch": true
            },
            {
              "id": "score",
              "displayName": "score",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "number",
              "canBeUsedToMatch": true
            },
            {
              "id": "best_score",
              "displayName": "best_score",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "number",
              "canBeUsedToMatch": true
            },
            {
              "id": "artifact",
              "displayName": "artifact",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "repeats",
              "displayName": "repeats",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "text",
              "displayName": "text",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "prompt_tokens",
              "displayName": "prompt_tokens",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "number",
              "canBeUsedToMatch": true
            },
            {
              "id": "cache_hit_tokens",
              "displayName": "cache_hit_tokens",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "number",
              "canBeUsedToMatch": true
            },
            {
              "id": "cache_miss_tokens",
              "displayName": "cache_miss_tokens",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "number",
              "canBeUsedToMatch": true
            },
            {
              "id": "output_tokens",
              "displayName": "output_tokens",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "number",
              "canBeUsedToMatch": true
            }
          ]
        },
        "options": {}
      }
    },
    {
      "id": "79008e3e-a918-43f4-9f0f-41024944a6c4",
      "name": "Load memory",
      "type": "n8n-nodes-base.dataTable",
      "typeVersion": 1.1,
      "position": [
        1400,
        360
      ],
      "parameters": {
        "resource": "row",
        "operation": "get",
        "dataTableId": {
          "__rl": true,
          "mode": "name",
          "value": "ctx_handoff"
        },
        "matchType": "allConditions",
        "filters": {
          "conditions": [
            {
              "keyName": "run_id",
              "condition": "eq",
              "keyValue": "={{ $('Keep state').last().json.run_id }}"
            }
          ]
        },
        "returnAll": true
      },
      "alwaysOutputData": true
    },
    {
      "id": "0406bfae-21dc-4e65-82e5-d8638aafa80a",
      "name": "Fresh session",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1600,
        360
      ],
      "parameters": {
        "jsCode": "// New session: empty history. Only the task, the latest handoff note and the best\n// artifact are carried over, and both are read back from the Data Table.\nconst s = $('Keep state').last().json;\nconst rows = $input.all().map(i => i.json).filter(r => r.kind && (r.arm === s.arm || r.arm === 'shared'));\nconst attempts = rows.filter(r => r.kind === 'attempt' && r.score > 0)\n  .sort((a, b) => b.score - a.score || a.round - b.round);\nconst notes = rows.filter(r => r.kind === 'note').sort((a, b) => b.round - a.round);\nconst top = attempts[0];\nreturn [{ json: {\n  ...s,\n  history: [],\n  session: s.session + 1,\n  handoff: notes[0] ? notes[0].text : '',\n  best: top ? { marks: JSON.parse(top.artifact), score: top.score, repeats: top.repeats, round: top.round } : s.best,\n  feedback: '',\n} }];\n"
      }
    },
    {
      "id": "088e5874-8556-4429-91d8-e3fc34d62e57",
      "name": "Next arm?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        2000,
        -160
      ],
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "loose",
            "version": 2
          },
          "conditions": [
            {
              "id": "more",
              "leftValue": "={{ $json.arms_left.length > 0 }}",
              "rightValue": "",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "looseTypeValidation": true,
        "options": {}
      }
    },
    {
      "id": "a225a956-14e9-4abe-a666-92124e5220ce",
      "name": "Load results",
      "type": "n8n-nodes-base.dataTable",
      "typeVersion": 1.1,
      "position": [
        2200,
        -160
      ],
      "parameters": {
        "resource": "row",
        "operation": "get",
        "dataTableId": {
          "__rl": true,
          "mode": "name",
          "value": "ctx_handoff"
        },
        "matchType": "allConditions",
        "filters": {
          "conditions": [
            {
              "keyName": "run_id",
              "condition": "eq",
              "keyValue": "={{ $json.run_id }}"
            }
          ]
        },
        "returnAll": true
      },
      "alwaysOutputData": true
    },
    {
      "id": "d321a468-cf01-4117-9899-df06036af6c7",
      "name": "Chart",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        2400,
        -160
      ],
      "parameters": {
        "jsCode": "// Best score vs round for each arm + Mermaid xychart (renders in Pele) + cost.\n// Round 1 is shared by all arms, so the lines start at the same point.\nconst cfg = $('Config').first().json;\nconst MAX = cfg.marks * (cfg.marks - 1) / 2;\nconst rows = $input.all().map(i => i.json).filter(r => r.kind);\nconst arms = String(cfg.arms).split(',').map(s => s.trim()).filter(Boolean);\nconst rounds = Array.from({ length: cfg.max_rounds }, (_, i) => i + 1);\nconst attempt = (a, n) => rows.find(x => x.kind === 'attempt' && x.round === n && (x.arm === a || x.arm === 'shared'));\nconst series = {}, resets = {};\nfor (const arm of arms) {\n  let best = 0;\n  series[arm] = rounds.map(n => { const r = attempt(arm, n); if (r) best = Math.max(best, r.score); return best; });\n  resets[arm] = rows.filter(r => r.arm === arm && r.kind === 'note').map(r => r.round).sort((a, b) => a - b);\n}\nconst all = arms.flatMap(a => series[a]);\nconst lo = Math.max(0, Math.min(...all) - 2);\nconst chart = [\n  'xychart-beta',\n  `  title \"Best score vs round, one run (n=1, noisy). Lines: ${arms.join(', ')}\"`,\n  `  x-axis \"round (1 = shared)\" [${rounds.join(', ')}]`,\n  `  y-axis \"distinct differences (max ${MAX})\" ${lo} --> ${MAX}`,\n  ...arms.map(a => `  line [${series[a].join(', ')}]`),\n].join('\\n');\nconst head = `| round | ${arms.map(a => a + ' score').join(' | ')} | ${arms.map(a => a + ' best').join(' | ')} |`;\nconst sep = '|' + ' --- |'.repeat(1 + 2 * arms.length);\nconst lines = rounds.map(n => `| ${n}${n === 1 ? ' (shared)' : ''}${arms.some(a => resets[a].includes(n)) ? ' (reset after)' : ''} | ` +\n  arms.map(a => { const r = attempt(a, n); return r ? r.score : ''; }).join(' | ') +\n  ' | ' + arms.map(a => series[a][n - 1]).join(' | ') + ' |');\nconst sum = k => rows.reduce((t, r) => t + (Number(r[k]) || 0), 0);\nconst cost = (sum('cache_hit_tokens') * cfg.usd_per_1m_hit + sum('cache_miss_tokens') * cfg.usd_per_1m_miss\n  + sum('output_tokens') * cfg.usd_per_1m_out) / 1e6;\nreturn [{ json: {\n  chart,\n  table: [head, sep, ...lines].join('\\n'),\n  final_best: Object.fromEntries(arms.map(a => [a, series[a][series[a].length - 1]])),\n  gain_over_round_1: Object.fromEntries(arms.map(a => [a, series[a][series[a].length - 1] - series[a][0]])),\n  resets,\n  calls: rows.length,\n  api_errors: rows.filter(r => String(r.text).startsWith('API ERROR')).length,\n  tokens: { cache_hit: sum('cache_hit_tokens'), cache_miss: sum('cache_miss_tokens'), output: sum('output_tokens') },\n  cost_usd_offpeak: Number(cost.toFixed(5)),\n} }];\n"
      }
    },
    {
      "id": "e530c96e-69d9-40f3-8f5a-f5ea8bfc9aae",
      "name": "Note overview",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -600,
        -340
      ],
      "parameters": {
        "content": "## Reset with handoff\nA fix for **context inertia**: in one long conversation an agent keeps polishing its first idea. Here `deepseek-flash` improves a puzzle over 8 rounds: 10 distinct integers in 0..50, scored by **Score** as the number of different pairwise differences (max 45). 0..50 is shorter than the best 10-mark Golomb ruler (length 55), so 45 is out of reach and a remembered textbook answer does not win.\n\nRound 1 is played once and both arms fork from it. **reset** deletes the conversation every 3 rounds; the next session gets only the task, a handoff note and the best set. **baseline** keeps its whole history. Both see the same feedback; reset spends 2 extra calls on notes.\n\nSources: Drew Breunig, [The State of Context Engineering](https://www.dbreunig.com/2026/10/24/the-state-of-context-engineering.html), [Context Inertia](https://www.dbreunig.com/2026/10/14/context-inertia.html).\n\n### Setup\n1. Needs n8n with Data Tables (2.x). Pick your **DeepSeek** credential in **DeepSeek** and **Write note**.\n2. **Create table** makes `ctx_handoff` on the first run. If a table with that name but other columns exists, rename it first. Rows pile up per `run_id`; delete the table when done.\n3. Tune **Config**, run. **Chart** returns a Mermaid `xychart-beta` (Pele), a table and the cost.\n\n### Cost and noise\n18 small calls, thinking off: about $0.0015 off-peak. One run is n=1: repeat it before reading anything into the gap.",
        "width": 560,
        "height": 760,
        "color": 7
      }
    },
    {
      "id": "f75b97e2-1272-4dd8-9611-ee7323c04c69",
      "name": "Note inertia",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        560,
        -340
      ],
      "parameters": {
        "content": "## 1 · The inertia problem\nModels are trained to stay with a goal, so in a long run they keep polishing the idea already in their context. In Microsoft's [Fork-and-Flush](https://arxiv.org/abs/2610.07447) runs, scores jump and then flatten into long plateaus of ever-smaller changes. Breunig calls this [context inertia](https://www.dbreunig.com/2026/10/14/context-inertia.html). Every round adds an attempt and its feedback to **history**.",
        "width": 580,
        "height": 400,
        "color": 4
      }
    },
    {
      "id": "b9807bef-6ec0-4d47-81d1-38361db6dc1b",
      "name": "Note environment",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        1160,
        -340
      ],
      "parameters": {
        "content": "## 2 · Artifacts survive, conversation does not\nAnthropic's [Memento](https://www.anthropic.com/research/self-replicating-ai) harness and [Scaling Discovery Requires Forgetting](https://arxiv.org/abs/2610.20563) clear the context but keep the environment. **Log round** writes every attempt to the Data Table; the reset arm rebuilds its next session from it. DenisM on HN: *\"checkpointing into artifacts (code, design, intent) to start with fresh context\"* ([comment](https://news.ycombinator.com/item?id=50237697)).",
        "width": 580,
        "height": 400,
        "color": 6
      }
    },
    {
      "id": "85ebb628-dade-455f-af11-14e472d60cd4",
      "name": "Note handoff",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        960,
        520
      ],
      "parameters": {
        "content": "## 3 · What goes into a handoff note\nThe old session writes the note before its history is deleted, so it still sees everything, including its last score. Same prefix and JSON mode as the rounds, so the call reuses the prompt cache. At most 80 words: **what was tried, what failed, what is still untried**. The best set is attached separately, so the note need not repeat it (models often do anyway). Notes can misremember, which is why **Fresh session** takes the best set from the table, not from the note.",
        "width": 780,
        "height": 300,
        "color": 5
      }
    },
    {
      "id": "f88a05b7-ee90-4ce6-a244-4f4dea1c28ef",
      "name": "Note delete",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        2000,
        0
      ],
      "parameters": {
        "content": "## 4 · \"Delete your context\"\nBreunig's question for an agent acting strangely: *\"How big is your context?\"* Around 200k tokens is his warning point, and sometimes resetting really is the fix ([post](https://www.dbreunig.com/2026/10/24/the-state-of-context-engineering.html)). **Score** sets the next step: reset every `reset_every` rounds, or earlier if the prompt passes `max_history_tokens`. The baseline never resets.",
        "width": 500,
        "height": 340,
        "color": 3
      }
    }
  ],
  "connections": {
    "Start": {
      "main": [
        [
          {
            "node": "Config",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Config": {
      "main": [
        [
          {
            "node": "Create table",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create table": {
      "main": [
        [
          {
            "node": "Start arm",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Start arm": {
      "main": [
        [
          {
            "node": "Build prompt",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build prompt": {
      "main": [
        [
          {
            "node": "DeepSeek",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "DeepSeek": {
      "main": [
        [
          {
            "node": "Score",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Score": {
      "main": [
        [
          {
            "node": "Log round",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Log round": {
      "main": [
        [
          {
            "node": "Keep state",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Keep state": {
      "main": [
        [
          {
            "node": "Next step",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Next step": {
      "main": [
        [
          {
            "node": "Build prompt",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Write note",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Next arm?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Write note": {
      "main": [
        [
          {
            "node": "Save note",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Save note": {
      "main": [
        [
          {
            "node": "Load memory",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Load memory": {
      "main": [
        [
          {
            "node": "Fresh session",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fresh session": {
      "main": [
        [
          {
            "node": "Build prompt",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Next arm?": {
      "main": [
        [
          {
            "node": "Start arm",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Load results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Load results": {
      "main": [
        [
          {
            "node": "Chart",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1"
  },
  "pinData": {},
  "meta": {
    "templateCredsSetupCompleted": false
  }
}
