{
  "name": "Stickman AI Controller",
  "nodes": [
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "stickman",
        "responseMode": "responseNode",
        "options": {}
      },
      "id": "aab1c2d3-0001-4abc-8abc-000000000001",
      "name": "Webhook",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [240, 300],
      "webhookId": "stickman-ai-webhook"
    },
    {
      "parameters": {
        "promptType": "define",
        "text": "=Current stickman state:\n- Position: x={{ $json.body.x }}, y={{ $json.body.y }}\n- State: {{ $json.body.state }}\n- On ground: {{ $json.body.onGround }}\n- Velocity: vx={{ $json.body.vx }}, vy={{ $json.body.vy }}\n\nWhat action should the stickman take?",
        "messages": {
          "messageValues": [
            {
              "type": "SystemMessage",
              "message": "You are an AI controlling a stickman in a 2D platformer game. Based on the stickman's current state, decide the next action to take.\n\nThe canvas is 900px wide. The ground is near y=420.\nPlatforms exist at various heights — use jumps to reach them.\n\nYou receive: x, y, state (idle/walking/jumping/falling), onGround, vx, vy.\n\nAvailable actions:\n  \"left\"       – move left\n  \"right\"      – move right\n  \"jump\"       – jump straight up\n  \"idle\"       – stand still\n  \"left_jump\"  – jump while moving left\n  \"right_jump\" – jump while moving right\n\nKeep the stickman active and exploring. Avoid staying idle.\nStay within x bounds (0–900).\n\nRespond with ONLY valid JSON, no explanation:\n{\"action\": \"right\"}"
            }
          ]
        }
      },
      "id": "aab1c2d3-0002-4abc-8abc-000000000002",
      "name": "AI Decision",
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "typeVersion": 1.4,
      "position": [480, 300]
    },
    {
      "parameters": {
        "model": "gpt-4o-mini",
        "options": {}
      },
      "id": "aab1c2d3-0004-4abc-8abc-000000000004",
      "name": "OpenAI Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "typeVersion": 1,
      "position": [480, 460],
      "credentials": {
        "openAiApi": {
          "id": "YOUR_CREDENTIAL_ID",
          "name": "OpenAI account"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "// Parse the action from the LLM's JSON response\nconst raw = $input.first().json?.response?.text\n         ?? $input.first().json?.text\n         ?? '';\n\nconst valid = ['left','right','jump','idle','left_jump','right_jump'];\nlet action = 'idle';\n\ntry {\n  // Strip markdown code fences if the model added them\n  const cleaned = raw.replace(/```json?\\s*/gi, '').replace(/```/g, '').trim();\n  const parsed = JSON.parse(cleaned);\n  if (valid.includes(parsed.action)) action = parsed.action;\n} catch {\n  // Fallback: extract action with regex\n  const m = raw.match(/\"action\"\\s*:\\s*\"([^\"]+)\"/);\n  if (m && valid.includes(m[1])) action = m[1];\n}\n\nreturn [{ json: { action } }];"
      },
      "id": "aab1c2d3-0003-4abc-8abc-000000000003",
      "name": "Parse Action",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [720, 300]
    },
    {
      "parameters": {
        "respondWith": "json",
        "responseBody": "={{ $json }}",
        "options": {
          "responseHeaders": {
            "entries": [
              { "name": "Access-Control-Allow-Origin",  "value": "*" },
              { "name": "Access-Control-Allow-Methods", "value": "POST, GET, OPTIONS" },
              { "name": "Access-Control-Allow-Headers", "value": "Content-Type" }
            ]
          }
        }
      },
      "id": "aab1c2d3-0005-4abc-8abc-000000000005",
      "name": "Respond",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1,
      "position": [960, 300]
    }
  ],
  "connections": {
    "Webhook": {
      "main": [
        [{ "node": "AI Decision", "type": "main", "index": 0 }]
      ]
    },
    "OpenAI Chat Model": {
      "ai_languageModel": [
        [{ "node": "AI Decision", "type": "ai_languageModel", "index": 0 }]
      ]
    },
    "AI Decision": {
      "main": [
        [{ "node": "Parse Action", "type": "main", "index": 0 }]
      ]
    },
    "Parse Action": {
      "main": [
        [{ "node": "Respond", "type": "main", "index": 0 }]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "id": "stickman-ai-workflow-001",
  "meta": {
    "instanceId": "stickman-simulator"
  }
}
