{
  "name": "wf_main",
  "nodes": [
    {
      "parameters": {
        "content": "## wf_main\n\nTelegram entry point.\n\n**Commands:** /start, /setkey, /agents, /cancel, /help.\n**Callbacks:** agent:<id>, action:<mode>.\n**Text input in await_* state** is forwarded to wf_editor.\n\n**Credentials.** TG_BOT (Telegram), MYSQL (n8n_app).\n\n**Sub-workflow contract** (wf_main \u2192 wf_editor):\n```\n{ user_id, eleven_api_key, eleven_agent_id, mode, payload, chat_id }\n```\nmode \u2208 {prompt, welcome, kb_text, kb_url}.",
        "height": 320,
        "width": 600
      },
      "id": "sticky-readme",
      "name": "README",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -200,
        -100
      ]
    },
    {
      "parameters": {
        "updates": [
          "message",
          "callback_query"
        ],
        "additionalFields": {}
      },
      "id": "tg-trigger",
      "name": "Telegram Trigger",
      "type": "n8n-nodes-base.telegramTrigger",
      "typeVersion": 1.1,
      "position": [
        200,
        600
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "const update = $json;\nconst msg = update.message;\nconst cb = update.callback_query;\n\nlet kind = 'ignore';\nlet command = null;\nlet command_args = null;\nlet callback_payload = null;\nlet text = null;\nlet chat_id = null;\nlet telegram_user_id = null;\nlet username = null;\nlet first_name = null;\nlet callback_query_id = null;\nlet message_id = null;\n\nif (cb) {\n  const data = cb.data || '';\n  telegram_user_id = cb.from.id;\n  username = cb.from.username || null;\n  first_name = cb.from.first_name || null;\n  chat_id = cb.message && cb.message.chat ? cb.message.chat.id : null;\n  message_id = cb.message ? cb.message.message_id : null;\n  callback_query_id = cb.id;\n\n  if (data.startsWith('agent:')) {\n    kind = 'callback_agent';\n    callback_payload = data.slice(6);\n  } else if (data.startsWith('action:')) {\n    kind = 'callback_action';\n    callback_payload = data.slice(7);\n  }\n} else if (msg) {\n  telegram_user_id = msg.from.id;\n  username = msg.from.username || null;\n  first_name = msg.from.first_name || null;\n  chat_id = msg.chat.id;\n  message_id = msg.message_id;\n  text = msg.text || null;\n\n  if (text && text.startsWith('/')) {\n    kind = 'command';\n    const parts = text.split(/\\s+/);\n    command = parts[0].split('@')[0].toLowerCase();\n    command_args = parts.slice(1).join(' ').trim();\n  } else if (text) {\n    kind = 'text_input';\n  }\n}\n\nreturn [{\n  json: {\n    kind, command, command_args, callback_payload, text,\n    telegram_user_id, username, first_name,\n    chat_id, message_id, callback_query_id,\n  },\n}];"
      },
      "id": "parse-update",
      "name": "Parse Update",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        420,
        600
      ]
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "INSERT INTO users (id, username, first_name) VALUES ($1, $2, $3) ON DUPLICATE KEY UPDATE username = VALUES(username), first_name = VALUES(first_name)",
        "options": {
          "queryBatching": "single",
          "queryReplacement": "={{ $json.telegram_user_id }},{{ $json.username }},{{ $json.first_name }}"
        }
      },
      "id": "upsert-user",
      "name": "Upsert User",
      "type": "n8n-nodes-base.mySql",
      "typeVersion": 2.4,
      "position": [
        640,
        600
      ],
      "credentials": {
        "mySql": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "INSERT IGNORE INTO user_sessions (user_id) VALUES ($1)",
        "options": {
          "queryBatching": "single",
          "queryReplacement": "={{ [$('Parse Update').first().json.telegram_user_id] }}"
        }
      },
      "id": "ensure-session",
      "name": "Ensure Session",
      "type": "n8n-nodes-base.mySql",
      "typeVersion": 2.4,
      "position": [
        860,
        600
      ],
      "credentials": {
        "mySql": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "SELECT u.eleven_api_key, s.selected_eleven_agent_id, s.state FROM users u JOIN user_sessions s ON s.user_id = u.id WHERE u.id = $1",
        "options": {
          "queryBatching": "single",
          "queryReplacement": "={{ [$('Parse Update').first().json.telegram_user_id] }}"
        }
      },
      "id": "get-ctx",
      "name": "Get Context",
      "type": "n8n-nodes-base.mySql",
      "typeVersion": 2.4,
      "position": [
        1080,
        600
      ],
      "credentials": {
        "mySql": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "typeValidation": "strict",
                  "version": 2
                },
                "combinator": "and",
                "conditions": [
                  {
                    "leftValue": "={{ $('Parse Update').first().json.kind }}",
                    "rightValue": "command",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ]
              },
              "renameOutput": true,
              "outputKey": "command"
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "typeValidation": "strict",
                  "version": 2
                },
                "combinator": "and",
                "conditions": [
                  {
                    "leftValue": "={{ $('Parse Update').first().json.kind }}",
                    "rightValue": "callback_agent",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ]
              },
              "renameOutput": true,
              "outputKey": "callback_agent"
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "typeValidation": "strict",
                  "version": 2
                },
                "combinator": "and",
                "conditions": [
                  {
                    "leftValue": "={{ $('Parse Update').first().json.kind }}",
                    "rightValue": "callback_action",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ]
              },
              "renameOutput": true,
              "outputKey": "callback_action"
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "typeValidation": "strict",
                  "version": 2
                },
                "combinator": "and",
                "conditions": [
                  {
                    "leftValue": "={{ $('Parse Update').first().json.kind }}",
                    "rightValue": "text_input",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ]
              },
              "renameOutput": true,
              "outputKey": "text_input"
            }
          ]
        },
        "options": {
          "fallbackOutput": "none"
        }
      },
      "id": "route-by-kind",
      "name": "Route by Kind",
      "type": "n8n-nodes-base.switch",
      "typeVersion": 3.2,
      "position": [
        1300,
        600
      ]
    },
    {
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "typeValidation": "strict",
                  "version": 2
                },
                "combinator": "and",
                "conditions": [
                  {
                    "leftValue": "={{ $('Parse Update').first().json.command }}",
                    "rightValue": "/start",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ]
              },
              "renameOutput": true,
              "outputKey": "/start"
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "typeValidation": "strict",
                  "version": 2
                },
                "combinator": "and",
                "conditions": [
                  {
                    "leftValue": "={{ $('Parse Update').first().json.command }}",
                    "rightValue": "/setkey",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ]
              },
              "renameOutput": true,
              "outputKey": "/setkey"
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "typeValidation": "strict",
                  "version": 2
                },
                "combinator": "and",
                "conditions": [
                  {
                    "leftValue": "={{ $('Parse Update').first().json.command }}",
                    "rightValue": "/agents",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ]
              },
              "renameOutput": true,
              "outputKey": "/agents"
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "typeValidation": "strict",
                  "version": 2
                },
                "combinator": "and",
                "conditions": [
                  {
                    "leftValue": "={{ $('Parse Update').first().json.command }}",
                    "rightValue": "/cancel",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ]
              },
              "renameOutput": true,
              "outputKey": "/cancel"
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "typeValidation": "strict",
                  "version": 2
                },
                "combinator": "and",
                "conditions": [
                  {
                    "leftValue": "={{ $('Parse Update').first().json.command }}",
                    "rightValue": "/help",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ]
              },
              "renameOutput": true,
              "outputKey": "/help"
            }
          ]
        },
        "options": {
          "fallbackOutput": "extra",
          "renameFallbackOutput": "other"
        }
      },
      "id": "route-by-command",
      "name": "Route by Command",
      "type": "n8n-nodes-base.switch",
      "typeVersion": 3.2,
      "position": [
        1520,
        120
      ]
    },
    {
      "parameters": {
        "jsCode": "const ctx = $('Parse Update').first().json;\nconst row = $('Get Context').first().json;\nconst hasKey = !!(row && row.eleven_api_key);\n\nconst lines = [\n  '\ud83d\udc4b \u042f \u043f\u043e\u043c\u043e\u0433\u0443 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0432\u0430\u0448\u0438\u043c\u0438 \u0433\u043e\u043b\u043e\u0441\u043e\u0432\u044b\u043c\u0438 \u0430\u0433\u0435\u043d\u0442\u0430\u043c\u0438 ElevenLabs:',\n  '\u2014 \u043c\u0435\u043d\u044f\u0442\u044c prompt \u0438 welcome message,',\n  '\u2014 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u0442\u0435\u043a\u0441\u0442 \u0438 URL \u0432 knowledge base.',\n  '',\n];\nif (hasKey) {\n  lines.push('/agents \u2014 \u0441\u043f\u0438\u0441\u043e\u043a \u0432\u0430\u0448\u0438\u0445 \u0430\u0433\u0435\u043d\u0442\u043e\u0432');\n  lines.push('/help \u2014 \u0441\u043f\u0440\u0430\u0432\u043a\u0430');\n} else {\n  lines.push('\u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u0440\u0438\u0448\u043b\u0438\u0442\u0435 \u0441\u0432\u043e\u0439 API-\u043a\u043b\u044e\u0447 ElevenLabs:');\n  lines.push('<code>/setkey sk_xxx</code>');\n  lines.push('');\n  lines.push('\u041a\u043b\u044e\u0447 \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u0432 \u043c\u043e\u0435\u0439 \u0431\u0430\u0437\u0435 \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043a \u0432\u0430\u0448\u0435\u043c\u0443 \u0430\u043a\u043a\u0430\u0443\u043d\u0442\u0443 ElevenLabs.');\n}\n\nreturn [{ json: { chat_id: ctx.chat_id, text: lines.join('\\n') } }];\n"
      },
      "id": "build-start",
      "name": "Build /start",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1740,
        -120
      ]
    },
    {
      "parameters": {
        "operation": "sendMessage",
        "chatId": "={{ $json.chat_id }}",
        "text": "={{ $json.text }}",
        "additionalFields": {
          "parse_mode": "HTML",
          "appendAttribution": false
        }
      },
      "id": "send-start",
      "name": "Send /start",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        1960,
        -120
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "const ctx = $('Parse Update').first().json;\nconst key = (ctx.command_args || '').trim();\n\nif (!key) {\n  return [{ json: { chat_id: ctx.chat_id, valid_format: false, msg: '\u26a0\ufe0f \u041f\u0440\u0438\u0448\u043b\u0438\u0442\u0435 \u043a\u043b\u044e\u0447 \u0442\u0430\u043a:\\n<code>/setkey sk_xxx</code>' } }];\n}\nif (key.length < 20) {\n  return [{ json: { chat_id: ctx.chat_id, valid_format: false, msg: '\u26a0\ufe0f \u0421\u043b\u0438\u0448\u043a\u043e\u043c \u043a\u043e\u0440\u043e\u0442\u043a\u0438\u0439 \u043a\u043b\u044e\u0447 \u2014 \u044d\u0442\u043e \u043d\u0435 \u043f\u043e\u0445\u043e\u0436\u0435 \u043d\u0430 API-key ElevenLabs.' } }];\n}\nreturn [{ json: { chat_id: ctx.chat_id, valid_format: true, key } }];"
      },
      "id": "setkey-parse",
      "name": "Parse /setkey",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1740,
        80
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "typeValidation": "strict",
            "version": 2
          },
          "combinator": "and",
          "conditions": [
            {
              "leftValue": "={{ $json.valid_format }}",
              "rightValue": true,
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              }
            }
          ]
        }
      },
      "id": "setkey-if-format",
      "name": "IF /setkey format",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        1960,
        80
      ]
    },
    {
      "parameters": {
        "method": "GET",
        "url": "https://api.elevenlabs.io/v1/user",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "xi-api-key",
              "value": "={{ $json.key }}"
            }
          ]
        },
        "options": {
          "timeout": 10000,
          "response": {
            "response": {
              "fullResponse": true,
              "neverError": true
            }
          }
        }
      },
      "id": "setkey-validate",
      "name": "Validate Key via /v1/user",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        2180,
        0
      ],
      "onError": "continueRegularOutput"
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "typeValidation": "loose",
            "version": 2
          },
          "combinator": "and",
          "conditions": [
            {
              "leftValue": "={{ $json.statusCode }}",
              "rightValue": 400,
              "operator": {
                "type": "number",
                "operation": "lt"
              }
            }
          ]
        }
      },
      "id": "setkey-if-ok",
      "name": "IF key accepted",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        2400,
        0
      ]
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "UPDATE users SET eleven_api_key = $1 WHERE id = $2",
        "options": {
          "queryBatching": "single",
          "queryReplacement": "={{ $('Parse /setkey').first().json.key }},{{ $('Parse Update').first().json.telegram_user_id }}"
        }
      },
      "id": "setkey-save",
      "name": "Save Key",
      "type": "n8n-nodes-base.mySql",
      "typeVersion": 2.4,
      "position": [
        2620,
        -80
      ],
      "credentials": {
        "mySql": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "operation": "sendMessage",
        "chatId": "={{ $('Parse Update').first().json.chat_id }}",
        "text": "\u2705 \u041a\u043b\u044e\u0447 \u043f\u0440\u0438\u043d\u044f\u0442 \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0451\u043d. /agents \u2014 \u0441\u043f\u0438\u0441\u043e\u043a \u0432\u0430\u0448\u0438\u0445 \u0430\u0433\u0435\u043d\u0442\u043e\u0432.",
        "additionalFields": {
          "parse_mode": "HTML",
          "appendAttribution": false
        }
      },
      "id": "send-setkey-ok",
      "name": "Send /setkey ok",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        2840,
        -80
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "operation": "sendMessage",
        "chatId": "={{ $('Parse Update').first().json.chat_id }}",
        "text": "=\u274c ElevenLabs \u043e\u0442\u0432\u0435\u0440\u0433 \u043a\u043b\u044e\u0447 (\u043a\u043e\u0434 {{ $('Validate Key via /v1/user').first().json.statusCode }}). \u041f\u0440\u043e\u0432\u0435\u0440\u044c\u0442\u0435, \u0447\u0442\u043e \u0441\u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043b\u0438 \u043f\u043e\u043b\u043d\u044b\u0439 \u043a\u043b\u044e\u0447 \u0438\u0437 Profile \u2192 API Keys.",
        "additionalFields": {
          "parse_mode": "HTML",
          "appendAttribution": false
        }
      },
      "id": "send-setkey-bad",
      "name": "Send /setkey bad",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        2620,
        100
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "operation": "sendMessage",
        "chatId": "={{ $json.chat_id }}",
        "text": "={{ $json.msg }}",
        "additionalFields": {
          "parse_mode": "HTML",
          "appendAttribution": false
        }
      },
      "id": "send-setkey-format-err",
      "name": "Send /setkey format err",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        2180,
        180
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "const ctx = $('Parse Update').first().json;\nconst row = $('Get Context').first().json;\nconst hasKey = !!(row && row.eleven_api_key);\nreturn [{ json: { chat_id: ctx.chat_id, has_key: hasKey, api_key: hasKey ? row.eleven_api_key : null } }];"
      },
      "id": "agents-ctx",
      "name": "Agents \u2014 check key",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1740,
        300
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "typeValidation": "strict",
            "version": 2
          },
          "combinator": "and",
          "conditions": [
            {
              "leftValue": "={{ $json.has_key }}",
              "rightValue": true,
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              }
            }
          ]
        }
      },
      "id": "agents-if-key",
      "name": "IF has key",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        1960,
        300
      ]
    },
    {
      "parameters": {
        "method": "GET",
        "url": "https://api.elevenlabs.io/v1/convai/agents",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "xi-api-key",
              "value": "={{ $json.api_key }}"
            }
          ]
        },
        "options": {
          "timeout": 15000,
          "response": {
            "response": {
              "fullResponse": true,
              "neverError": true
            }
          }
        }
      },
      "id": "agents-fetch",
      "name": "Fetch Agents",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        2180,
        220
      ],
      "onError": "continueRegularOutput"
    },
    {
      "parameters": {
        "jsCode": "const ctx = $('Parse Update').first().json;\nconst resp = $json;\nconst code = resp.statusCode;\nconst body = resp.body || resp;\n\nif (code >= 400) {\n  return [{ json: { chat_id: ctx.chat_id, text: `\u274c ElevenLabs \u0432\u0435\u0440\u043d\u0443\u043b ${code} \u043f\u0440\u0438 \u043f\u043e\u043f\u044b\u0442\u043a\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0441\u043f\u0438\u0441\u043e\u043a \u0430\u0433\u0435\u043d\u0442\u043e\u0432. \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u043a\u043b\u044e\u0447 \u0443\u0441\u0442\u0430\u0440\u0435\u043b \u2014 /setkey <\u043d\u043e\u0432\u044b\u0439>.`, reply_markup: null } }];\n}\n\n// ElevenLabs Convai response shape: { agents: [{agent_id, name, ...}], has_more, next_cursor }\nconst agents = (body && Array.isArray(body.agents)) ? body.agents : [];\n\nif (agents.length === 0) {\n  return [{ json: { chat_id: ctx.chat_id, text: '\u0423 \u0432\u0430\u0441 \u043f\u043e\u043a\u0430 \u043d\u0435\u0442 \u0430\u0433\u0435\u043d\u0442\u043e\u0432 \u0432 ElevenLabs. \u0421\u043e\u0437\u0434\u0430\u0439\u0442\u0435 \u0430\u0433\u0435\u043d\u0442\u0430 \u0432 ElevenLabs Console \u0438 \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435 \u0441\u043d\u043e\u0432\u0430.', reply_markup: null } }];\n}\n\nconst inline_keyboard = agents.map(a => [{ text: a.name || a.agent_id, callback_data: `agent:${a.agent_id}` }]);\nreturn [{ json: { chat_id: ctx.chat_id, text: '\ud83c\udf99 \u0412\u0430\u0448\u0438 \u0430\u0433\u0435\u043d\u0442\u044b:', reply_markup: { inline_keyboard } } }];"
      },
      "id": "agents-build",
      "name": "Build Agents Keyboard",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        2400,
        220
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "=https://api.telegram.org/bot{{ $env.TELEGRAM_BOT_TOKEN }}/sendMessage",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify({chat_id: $json.chat_id, text: $json.text, parse_mode: 'HTML', reply_markup: $json.reply_markup}) }}",
        "options": {
          "response": {
            "response": {
              "fullResponse": true,
              "neverError": true
            }
          }
        }
      },
      "id": "agents-send",
      "name": "Send Agents",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        2620,
        220
      ]
    },
    {
      "parameters": {
        "operation": "sendMessage",
        "chatId": "={{ $('Parse Update').first().json.chat_id }}",
        "text": "\ud83d\udd11 \u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u0440\u0438\u0448\u043b\u0438\u0442\u0435 \u0441\u0432\u043e\u0439 ElevenLabs API \u043a\u043b\u044e\u0447:\n<code>/setkey sk_xxx</code>",
        "additionalFields": {
          "parse_mode": "HTML",
          "appendAttribution": false
        }
      },
      "id": "agents-no-key",
      "name": "Send no key (/agents)",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        2180,
        400
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "UPDATE user_sessions SET state = 'idle' WHERE user_id = $1",
        "options": {
          "queryBatching": "single",
          "queryReplacement": "={{ [$('Parse Update').first().json.telegram_user_id] }}"
        }
      },
      "id": "cancel-update",
      "name": "Cancel: reset state",
      "type": "n8n-nodes-base.mySql",
      "typeVersion": 2.4,
      "position": [
        1740,
        500
      ],
      "credentials": {
        "mySql": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "operation": "sendMessage",
        "chatId": "={{ $('Parse Update').first().json.chat_id }}",
        "text": "\ud83d\udd04 \u041e\u0442\u043c\u0435\u043d\u0435\u043d\u043e.",
        "additionalFields": {
          "parse_mode": "HTML",
          "appendAttribution": false
        }
      },
      "id": "send-cancel",
      "name": "Send /cancel",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        1960,
        500
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "operation": "sendMessage",
        "chatId": "={{ $('Parse Update').first().json.chat_id }}",
        "text": "\ud83d\udcd6 <b>\u041a\u043e\u043c\u0430\u043d\u0434\u044b</b>\n/start \u2014 \u043f\u0440\u0438\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u0435\n/setkey &lt;key&gt; \u2014 \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432\u0430\u0448 ElevenLabs API-\u043a\u043b\u044e\u0447\n/agents \u2014 \u043c\u043e\u0438 \u0430\u0433\u0435\u043d\u0442\u044b\n/cancel \u2014 \u043e\u0442\u043c\u0435\u043d\u0438\u0442\u044c \u0442\u0435\u043a\u0443\u0449\u0443\u044e \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044e\n/help \u2014 \u044d\u0442\u0430 \u0441\u043f\u0440\u0430\u0432\u043a\u0430\n\n<b>\u041a\u0430\u043a \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0430\u0433\u0435\u043d\u0442\u0430:</b>\n1. /setkey sk_xxx \u2014 \u043e\u0434\u0438\u043d \u0440\u0430\u0437, \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442 \u0432\u0430\u0448 \u043a\u043b\u044e\u0447\n2. /agents \u2192 \u0432\u044b\u0431\u0440\u0430\u0442\u044c \u0430\u0433\u0435\u043d\u0442\u0430 \u043a\u043d\u043e\u043f\u043a\u043e\u0439\n3. \u0412\u044b\u0431\u0440\u0430\u0442\u044c \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435: Prompt / Welcome / KB\n4. \u041f\u0440\u0438\u0441\u043b\u0430\u0442\u044c \u043d\u043e\u0432\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0442\u0435\u043a\u0441\u0442\u043e\u043c\n\n<b>\u041a\u0430\u043a \u043f\u043e\u0433\u043e\u0432\u043e\u0440\u0438\u0442\u044c \u0441 \u0430\u0433\u0435\u043d\u0442\u043e\u043c:</b>\n\u0421\u0430\u043c \u0440\u0430\u0437\u0433\u043e\u0432\u043e\u0440 \u0438\u0434\u0451\u0442 \u0432 ElevenLabs Console: \u0432\u0430\u0448 \u0430\u0433\u0435\u043d\u0442 \u2192 \u043a\u043d\u043e\u043f\u043a\u0430 <b>Test agent</b>. \u0411\u043e\u0442 \u043c\u0435\u043d\u044f\u0435\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0430\u0433\u0435\u043d\u0442\u0430, \u0433\u043e\u043b\u043e\u0441\u043e\u0432\u043e\u0439 \u0440\u0430\u0437\u0433\u043e\u0432\u043e\u0440 \u0432\u0435\u0434\u0451\u0442\u0441\u044f \u0432 Console \u0438\u043b\u0438 \u0447\u0435\u0440\u0435\u0437 \u0432\u0438\u0434\u0436\u0435\u0442/SDK ElevenLabs.",
        "additionalFields": {
          "parse_mode": "HTML",
          "appendAttribution": false
        }
      },
      "id": "send-help",
      "name": "Send /help",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        1740,
        700
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "method": "POST",
        "url": "=https://api.telegram.org/bot{{ $env.TELEGRAM_BOT_TOKEN }}/answerCallbackQuery",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify({callback_query_id: $('Parse Update').first().json.callback_query_id}) }}",
        "options": {
          "response": {
            "response": {
              "fullResponse": true,
              "neverError": true
            }
          }
        }
      },
      "id": "answer-cb-agent",
      "name": "Answer CB (agent)",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1520,
        850
      ]
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "UPDATE user_sessions SET selected_eleven_agent_id = $1, state = 'idle' WHERE user_id = $2",
        "options": {
          "queryBatching": "single",
          "queryReplacement": "={{ $('Parse Update').first().json.callback_payload }},{{ $('Parse Update').first().json.telegram_user_id }}"
        }
      },
      "id": "set-selected-agent",
      "name": "Set Selected Agent",
      "type": "n8n-nodes-base.mySql",
      "typeVersion": 2.4,
      "position": [
        1740,
        850
      ],
      "credentials": {
        "mySql": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "operation": "sendMessage",
        "chatId": "={{ $('Parse Update').first().json.chat_id }}",
        "text": "=\u2705 \u0410\u0433\u0435\u043d\u0442 \u0432\u044b\u0431\u0440\u0430\u043d: <code>{{ $('Parse Update').first().json.callback_payload }}</code>\n\n\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435:",
        "replyMarkup": "inlineKeyboard",
        "inlineKeyboard": {
          "rows": [
            {
              "row": {
                "buttons": [
                  {
                    "text": "\u270f\ufe0f Prompt",
                    "additionalFields": {
                      "callback_data": "action:prompt"
                    }
                  },
                  {
                    "text": "\ud83d\udcac Welcome",
                    "additionalFields": {
                      "callback_data": "action:welcome"
                    }
                  }
                ]
              }
            },
            {
              "row": {
                "buttons": [
                  {
                    "text": "\ud83d\udcda KB: \u0442\u0435\u043a\u0441\u0442",
                    "additionalFields": {
                      "callback_data": "action:kb_text"
                    }
                  },
                  {
                    "text": "\ud83d\udcda KB: URL",
                    "additionalFields": {
                      "callback_data": "action:kb_url"
                    }
                  }
                ]
              }
            }
          ]
        },
        "additionalFields": {
          "parse_mode": "HTML",
          "appendAttribution": false
        }
      },
      "id": "send-action-menu",
      "name": "Send Action Menu",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        1960,
        850
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "method": "POST",
        "url": "=https://api.telegram.org/bot{{ $env.TELEGRAM_BOT_TOKEN }}/answerCallbackQuery",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify({callback_query_id: $('Parse Update').first().json.callback_query_id}) }}",
        "options": {
          "response": {
            "response": {
              "fullResponse": true,
              "neverError": true
            }
          }
        }
      },
      "id": "answer-cb-action",
      "name": "Answer CB (action)",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1520,
        1080
      ]
    },
    {
      "parameters": {
        "jsCode": "const ctx = $('Parse Update').first().json;\nconst session = $('Get Context').first().json;\nconst mode = ctx.callback_payload;\n\nconst modeConfig = {\n  prompt:   { state: 'await_prompt',   text: '\u270f\ufe0f \u041f\u0440\u0438\u0448\u043b\u0438\u0442\u0435 \u043d\u043e\u0432\u044b\u0439 <b>prompt</b> (1\u201310 000 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432).\\n/cancel \u2014 \u043e\u0442\u043c\u0435\u043d\u0430.' },\n  welcome:  { state: 'await_welcome',  text: '\ud83d\udcac \u041f\u0440\u0438\u0448\u043b\u0438\u0442\u0435 \u043d\u043e\u0432\u044b\u0439 <b>welcome message</b> (1\u20131 000 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432).\\n/cancel \u2014 \u043e\u0442\u043c\u0435\u043d\u0430.' },\n  kb_text:  { state: 'await_kb_text',  text: '\ud83d\udcda \u041f\u0440\u0438\u0448\u043b\u0438\u0442\u0435 <b>\u0442\u0435\u043a\u0441\u0442</b> \u0434\u043b\u044f \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0432 knowledge base.\\n/cancel \u2014 \u043e\u0442\u043c\u0435\u043d\u0430.' },\n  kb_url:   { state: 'await_kb_url',   text: '\ud83d\udcda \u041f\u0440\u0438\u0448\u043b\u0438\u0442\u0435 <b>URL</b> (https://...) \u0434\u043b\u044f \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0432 knowledge base.\\n/cancel \u2014 \u043e\u0442\u043c\u0435\u043d\u0430.' },\n};\n\nif (!session || !session.selected_eleven_agent_id) {\n  return [{ json: { chat_id: ctx.chat_id, text: '\u26a0\ufe0f \u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u0432\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0430\u0433\u0435\u043d\u0442\u0430: /agents', valid: false } }];\n}\nconst cfg = modeConfig[mode];\nif (!cfg) {\n  return [{ json: { chat_id: ctx.chat_id, text: '\u26a0\ufe0f \u041d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u043e\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435.', valid: false } }];\n}\nreturn [{ json: {\n  chat_id: ctx.chat_id,\n  text: cfg.text,\n  new_state: cfg.state,\n  telegram_user_id: ctx.telegram_user_id,\n  valid: true,\n} }];"
      },
      "id": "build-action-prompt",
      "name": "Build Action Prompt",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1740,
        1080
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "typeValidation": "strict",
            "version": 2
          },
          "combinator": "and",
          "conditions": [
            {
              "leftValue": "={{ $json.valid }}",
              "rightValue": true,
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              }
            }
          ]
        }
      },
      "id": "if-valid-action",
      "name": "IF action valid",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        1960,
        1080
      ]
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "UPDATE user_sessions SET state = $1 WHERE user_id = $2",
        "options": {
          "queryBatching": "single",
          "queryReplacement": "={{ $json.new_state }},{{ $json.telegram_user_id }}"
        }
      },
      "id": "set-await-state",
      "name": "Set Await State",
      "type": "n8n-nodes-base.mySql",
      "typeVersion": 2.4,
      "position": [
        2180,
        1000
      ],
      "credentials": {
        "mySql": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "operation": "sendMessage",
        "chatId": "={{ $('Build Action Prompt').first().json.chat_id }}",
        "text": "={{ $('Build Action Prompt').first().json.text }}",
        "additionalFields": {
          "parse_mode": "HTML",
          "appendAttribution": false
        }
      },
      "id": "send-action-prompt",
      "name": "Send Action Prompt",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        2400,
        1000
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "operation": "sendMessage",
        "chatId": "={{ $json.chat_id }}",
        "text": "={{ $json.text }}",
        "additionalFields": {
          "parse_mode": "HTML",
          "appendAttribution": false
        }
      },
      "id": "send-action-error",
      "name": "Send Action Error",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        2180,
        1180
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "typeValidation": "strict",
                  "version": 2
                },
                "combinator": "or",
                "conditions": [
                  {
                    "leftValue": "={{ $('Get Context').first().json.state }}",
                    "rightValue": "await_prompt",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  },
                  {
                    "leftValue": "={{ $('Get Context').first().json.state }}",
                    "rightValue": "await_welcome",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  },
                  {
                    "leftValue": "={{ $('Get Context').first().json.state }}",
                    "rightValue": "await_kb_text",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  },
                  {
                    "leftValue": "={{ $('Get Context').first().json.state }}",
                    "rightValue": "await_kb_url",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ]
              },
              "renameOutput": true,
              "outputKey": "await"
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "typeValidation": "strict",
                  "version": 2
                },
                "combinator": "and",
                "conditions": [
                  {
                    "leftValue": "={{ $('Get Context').first().json.state }}",
                    "rightValue": "processing",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ]
              },
              "renameOutput": true,
              "outputKey": "processing"
            }
          ]
        },
        "options": {
          "fallbackOutput": "extra",
          "renameFallbackOutput": "idle"
        }
      },
      "id": "route-by-state",
      "name": "Route by State",
      "type": "n8n-nodes-base.switch",
      "typeVersion": 3.2,
      "position": [
        1520,
        1400
      ]
    },
    {
      "parameters": {
        "jsCode": "const ctx = $('Parse Update').first().json;\nconst session = $('Get Context').first().json;\nconst stateToMode = { await_prompt: 'prompt', await_welcome: 'welcome', await_kb_text: 'kb_text', await_kb_url: 'kb_url' };\nconst mode = stateToMode[session.state];\nreturn [{ json: {\n  user_id: ctx.telegram_user_id,\n  eleven_api_key: session.eleven_api_key,\n  eleven_agent_id: session.selected_eleven_agent_id,\n  mode,\n  payload: ctx.text,\n  chat_id: ctx.chat_id,\n} }];"
      },
      "id": "prepare-editor-call",
      "name": "Prepare Editor Call",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1740,
        1300
      ]
    },
    {
      "parameters": {
        "workflowId": {
          "__rl": true,
          "value": "REPLACE_WITH_WF_EDITOR_ID",
          "mode": "id"
        },
        "workflowInputs": {
          "mappingMode": "passThrough"
        },
        "options": {}
      },
      "id": "exec-editor",
      "name": "Execute wf_editor",
      "type": "n8n-nodes-base.executeWorkflow",
      "typeVersion": 1.2,
      "position": [
        1960,
        1300
      ]
    },
    {
      "parameters": {
        "operation": "sendMessage",
        "chatId": "={{ $('Parse Update').first().json.chat_id }}",
        "text": "\u23f3 \u041f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0430\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f \u0435\u0449\u0451 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f. \u041f\u043e\u0434\u043e\u0436\u0434\u0438\u0442\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u0435\u043a\u0443\u043d\u0434 \u0438\u043b\u0438 /cancel.",
        "additionalFields": {
          "parse_mode": "HTML",
          "appendAttribution": false
        }
      },
      "id": "send-processing",
      "name": "Send Processing",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        1740,
        1500
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "const ctx = $('Parse Update').first().json;\nconst row = $('Get Context').first().json;\nconst hasKey = !!(row && row.eleven_api_key);\nconst text = hasKey\n  ? '\u041d\u0435 \u043f\u043e\u043d\u0438\u043c\u0430\u044e. \u041d\u0430\u0436\u043c\u0438\u0442\u0435 /agents, \u0447\u0442\u043e\u0431\u044b \u0432\u044b\u0431\u0440\u0430\u0442\u044c \u0430\u0433\u0435\u043d\u0442\u0430 \u0438 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435.'\n  : '\ud83d\udd11 \u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u0440\u0438\u0448\u043b\u0438\u0442\u0435 \u0441\u0432\u043e\u0439 API-\u043a\u043b\u044e\u0447:\\n<code>/setkey sk_xxx</code>';\nreturn [{ json: { chat_id: ctx.chat_id, text } }];"
      },
      "id": "idle-hint-build",
      "name": "Build Idle Hint",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1740,
        1700
      ]
    },
    {
      "parameters": {
        "operation": "sendMessage",
        "chatId": "={{ $json.chat_id }}",
        "text": "={{ $json.text }}",
        "additionalFields": {
          "parse_mode": "HTML",
          "appendAttribution": false
        }
      },
      "id": "send-idle-hint",
      "name": "Send Idle Hint",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1.2,
      "position": [
        1960,
        1700
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    }
  ],
  "connections": {
    "Telegram Trigger": {
      "main": [
        [
          {
            "node": "Parse Update",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Update": {
      "main": [
        [
          {
            "node": "Upsert User",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Upsert User": {
      "main": [
        [
          {
            "node": "Ensure Session",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Ensure Session": {
      "main": [
        [
          {
            "node": "Get Context",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Context": {
      "main": [
        [
          {
            "node": "Route by Kind",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Route by Kind": {
      "main": [
        [
          {
            "node": "Route by Command",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Answer CB (agent)",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Answer CB (action)",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Route by State",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Route by Command": {
      "main": [
        [
          {
            "node": "Build /start",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Parse /setkey",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Agents \u2014 check key",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Cancel: reset state",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Send /help",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build /start": {
      "main": [
        [
          {
            "node": "Send /start",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse /setkey": {
      "main": [
        [
          {
            "node": "IF /setkey format",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF /setkey format": {
      "main": [
        [
          {
            "node": "Validate Key via /v1/user",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Send /setkey format err",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Validate Key via /v1/user": {
      "main": [
        [
          {
            "node": "IF key accepted",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF key accepted": {
      "main": [
        [
          {
            "node": "Save Key",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Send /setkey bad",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Save Key": {
      "main": [
        [
          {
            "node": "Send /setkey ok",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Agents \u2014 check key": {
      "main": [
        [
          {
            "node": "IF has key",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF has key": {
      "main": [
        [
          {
            "node": "Fetch Agents",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Send no key (/agents)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Agents": {
      "main": [
        [
          {
            "node": "Build Agents Keyboard",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Agents Keyboard": {
      "main": [
        [
          {
            "node": "Send Agents",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Cancel: reset state": {
      "main": [
        [
          {
            "node": "Send /cancel",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Answer CB (agent)": {
      "main": [
        [
          {
            "node": "Set Selected Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Selected Agent": {
      "main": [
        [
          {
            "node": "Send Action Menu",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Answer CB (action)": {
      "main": [
        [
          {
            "node": "Build Action Prompt",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Action Prompt": {
      "main": [
        [
          {
            "node": "IF action valid",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF action valid": {
      "main": [
        [
          {
            "node": "Set Await State",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Send Action Error",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Await State": {
      "main": [
        [
          {
            "node": "Send Action Prompt",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Route by State": {
      "main": [
        [
          {
            "node": "Prepare Editor Call",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Send Processing",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Build Idle Hint",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Editor Call": {
      "main": [
        [
          {
            "node": "Execute wf_editor",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Idle Hint": {
      "main": [
        [
          {
            "node": "Send Idle Hint",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "tags": [],
  "versionId": "wfm-v3-init"
}