Все статьи
8 мин чтения

Как убрать ошибку 429 «Too Many Requests» на toncenter

Ошибка 429 «Too Many Requests» на toncenter: почему бьёт по ИИ-агентам, быстрый фикс бэкоффом и настоящее решение — свой ключ с гарантированным throughput.

toncenterошибка 429rate limit TONMCP TONTONNodeИИ-агенты TON

Токен-агент на TON падает в самый неподходящий момент: пользователь просит «покажи мой баланс и последние сделки», агент честно идёт в toncenter — а в ответ прилетает не JSON с данными, а сухое HTTP 429 Too Many Requests. Агент за один тик попытался собрать баланс кошелька, состояние аккаунта, историю транзакций и дёрнуть пару get-методов — и публичный toncenter захлопнулся на втором запросе. Пользователь видит «что-то пошло не так», а вы — стену красных логов с одним и тем же статусом. Это не баг вашего кода. Это публичный rate limit toncenter, в который упирается любой агент, как только начинает работать активнее одного запроса в секунду.

Разберём, откуда берётся toncenter 429, почему именно ИИ-агенты ловят Too Many Requests на TON чаще всех, как быстро сбить частоту ошибок бэкоффом — и как убрать потолок совсем, перейдя на свой ключ с гарантированной пропускной способностью.

Что означает 429 «Too Many Requests» на toncenter

Код 429 — это стандартный HTTP-ответ «слишком много запросов». Сервер не сломался и не отверг ваши данные: он просто говорит, что вы превысили разрешённую частоту обращений и вас притормаживают (rate limiting). У toncenter (v2) тело ответа при этом выглядит примерно так:

{ "ok": false, "error": "Rate limit exceeded", "code": 429 }

Ключевое: "ok": false и "code": 429 — это HTTP-статус, продублированный в теле, а не внутренний код ошибки контракта. И обратите внимание: поля result с данными аккаунта здесь вообще нет — текст лимита лежит в поле error. Поэтому ваш код, если он рассчитывает достать данные из result, получит undefined и, скорее всего, упадёт где-то дальше по стеку с невнятной ошибкой парсинга — а настоящая причина лежит в error. Правило простое: при ok: false сначала проверяйте code и читайте error, а не разбирайте несуществующий result.

Отдельно про фольклор: в TON-комьюнити гуляет «ошибка 228». Это не код API, а мем — никакой сервер вам 228 не вернёт. Реальный код лимита именно 429, и искать в документации нужно его. 429 — временная ошибка: тот же самый вызов пройдёт, если сделать его медленнее или с валидным ключом.

Почему без ключа toncenter даёт ~1 запрос/с

Публичный toncenter без API-ключа ограничивает вас примерно одним запросом в секунду. Это не баг и не жадность — это защита общего бесплатного ресурса, которым пользуются тысячи людей одновременно. Пара нюансов, о которые спотыкаются даже опытные разработчики:

  • Общий пул — это про анонимный трафик. Без ключа вы делите единый публичный лимит примерно в 1 rps со всеми безымянными запросами со всего мира. В час пик реально доступная вам частота может оказаться даже ниже.
  • Платный ключ поднимает потолок — но только если он реально передан в запросе. Классическая ловушка: ключ есть, а заголовок X-API-Key потерялся при рефакторинге HTTP-клиента, и вы снова сидите на публичном лимите, часами не понимая, почему платный тариф «не работает».

Один запрос в секунду — это нормально для ручного дебага в браузере или скрипта, который раз в минуту проверяет баланс. Для любой автоматизации, а тем более для агента, это смертельно мало.

Почему ИИ-агенты ловят 429 чаще всего: бёрст-паттерн

Вот где собака зарыта. Обычное приложение шлёт запросы более-менее равномерно. ИИ-агент работает иначе — бёрстами (burst, всплеск). Он работает тиками: на одном шаге рассуждения ему нужно собрать контекст, и он дёргает десятки вызовов подряд, почти одновременно.

Представьте один шаг: «пользователь просит проверить, пришёл ли платёж». Чтобы ответить, агент за доли секунды дёргает подряд:

  1. get_masterchain_info — узнать текущую голову блокчейна;
  2. get_balance — баланс кошелька;
  3. get_account_state — статус и флаги аккаунта;
  4. get_transactions — последние транзакции;
  5. run_get_method — прочитать get-метод контракта;
  6. get_jetton_balance — а заодно и баланс USDT.

Шесть вызовов за один тик. Лимит — один в секунду. Первый пройдёт, а остальные вернут 429, и агент либо застрянет, либо начнёт галлюцинировать на неполных данных. Причём это не «кривой агент» — это нормальная архитектура автономного рассуждения: собери контекст, потом думай. Хуже того, поймав ошибки, агент часто пытается «починить» их повторными вызовами — и добивает уже исчерпанную квоту. Публичный лимит просто не рассчитан на такой профиль нагрузки.

Похожая история и с публичными лайтсерверами из глобального конфига TON — под нагрузкой они отвечают not ready или отваливаются по ADNL-таймауту. Об этом отдельно: почему лайтсервер отвечает «not ready» и что делать. И у tonapi.io та же болезнь 429 — разбор здесь.

Быстрый фикс: ретраи с экспоненциальным бэкоффом и Retry-After

Первое, что стоит сделать прямо сейчас, — перестать бить в стену на полной скорости. Если 429 всё же прилетел, не долбите сервер повторно сразу: это только продлевает бан. Это паллиатив — он снижает частоту 429, но не поднимает потолок. Правильный паллиатив состоит из четырёх частей.

1. Экспоненциальный бэкофф с джиттером. Каждую следующую попытку ждите дольше предыдущей, плюс случайная добавка, чтобы параллельные воркеры не синхронизировались и не били в одну секунду.

async function fetchWithBackoff(url, opts = {}, maxRetries = 5) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    const res = await fetch(url, opts);
    if (res.status !== 429) return res;

    // Приоритет — Retry-After от сервера, иначе экспонента с джиттером
    const retryAfter = res.headers.get("Retry-After");
    const baseMs = retryAfter
      ? Number(retryAfter) * 1000
      : Math.min(1000 * 2 ** attempt, 16000);
    const jitter = Math.random() * 300;
    await new Promise((r) => setTimeout(r, baseMs + jitter));
  }
  throw new Error("toncenter: 429 не отпустил после ретраев");
}

2. Уважайте заголовок Retry-After, если он пришёл. toncenter на 429 его обычно не присылает, поэтому основную ставку делайте на свою формулу бэкоффа. Но если сервер всё же указал, сколько ждать, — ждите ровно столько, а не гадайте (в коде выше это и делает ветка if (retryAfter)).

3. Ограничьте конкуренцию. Поставьте перед toncenter очередь или семафор, который выпускает не больше ~1 запроса в секунду. Тогда бёрст агента растянется во времени: тот самый список из шести вызовов выполнится последовательно, за ~6 секунд, но без единого 429.

4. Кэшируйте повторяющиеся чтения. get_masterchain_info в рамках одного шага можно запросить один раз и переиспользовать. Метаданные жетона (decimals, символ) не меняются — читайте их один раз. Баланс, который вы читали 300 мс назад, вряд ли изменился.

Это работает и делает агента вежливее, но признаем честно: бэкофф не поднимает потолок. Вы всё ещё заперты в 1 rps, просто теперь вежливо стоите в очереди вместо того, чтобы падать. Пользователь ждёт секунды там, где мог бы ждать миллисекунды. Для агента, которому нужна отзывчивость, это лечение симптома, а не болезни. Другие обходные пути публичных API — в подборке альтернатив toncenter на 2026.

Настоящее решение: свой ключ и TON через MCP

Корень проблемы в том, что вы делите узкий публичный канал с тысячами анонимных запросов. Единственный способ убрать 429 по-настоящему — получить собственную гарантированную пропускную способность вместо общей квоты. Тогда бёрст агента из шести вызовов проходит целиком, а не упирается в стену на пятом, и агент может собирать контекст на полной скорости. Ретраи с бэкоффом остаются как страховка от сетевых сбоев, но перестают быть основным механизмом выживания.

И есть путь, который вдобавок убирает возню с HTTP-статусами вообще. Если данные из TON нужны именно ИИ-агенту, логичнее отдавать их не сырым REST-ответом, который надо парсить и обрабатывать на 429, а как готовые инструменты через MCP.

MCP (Model Context Protocol) — стандарт, по которому ИИ-агенты (Claude, Cursor, ChatGPT/Codex, любой MCP-клиент) вызывают внешние инструменты. Вместо того чтобы учить агента правильно формировать HTTP-запрос к toncenter, ловить 429, читать Retry-After и парсить JSON, вы даёте ему типизированные инструменты, а всю чёрную работу с сетью берёт на себя сервер.

TONNode — это hosted MCP-сервер для TON, ровно 16 инструментов. Те шесть чтений, которыми агент обычно и пробивает лимит toncenter, здесь — готовые вызовы:

  • get_masterchain_info — голова мастерчейна;
  • get_balance — баланс GRAM;
  • get_account_state — статус, флаги, последняя транзакция;
  • get_transactions — история транзакций;
  • run_get_method — любой read-only get-метод контракта;
  • get_jetton_balance — баланс жетона или USDT (адрес джеттон-кошелька вычисляется он-чейн).

(Кстати, GRAM — это переименованный в июне 2026 Toncoin. Сеть по-прежнему называется TON, изменилось только имя монеты.)

Под капотом пакет @tonnode/mcp работает по нативному протоколу TON — ADNL, без HTTP-прослоек. То есть вы не просто меняете один REST-эндпоинт на другой: агент общается с сетью напрямую, а вы перестаёте вручную разгребать HTTP-семантику лимитов. Пакет open source (MIT), лежит на npm и GitHub (tonnode/mcp).

Разница на практике: агенту больше не нужно знать, что такое 429, Retry-After или ADNL-таймаут. Он говорит «дай баланс и последние транзакции этого адреса» — и получает структурированный ответ. Тот же бёрст из шести вызовов уходит на сервер, у которого есть пропускная способность под вашим ключом, а не на общий публичный лимит.

Как подключить и с чего начать бесплатно

Есть два пути, и начать можно вообще без регистрации.

Бесплатно и локально

Полный набор инструментов чтения через публичный конфиг — просто добавьте в настройки вашего MCP-клиента:

{
  "mcpServers": {
    "ton": {
      "command": "npx",
      "args": ["-y", "@tonnode/mcp"]
    }
  }
}

Никаких ключей, npx сам подтянет пакет. Этого достаточно, чтобы попробовать и убедиться, что агент читает TON без единого 429. Подробный разбор — в гайде по MCP для TON бесплатно.

Hosted-эндпоинт со своим ключом

Когда нужна гарантированная пропускная способность под реальную нагрузку, подключаете hosted-эндпоинт со своим ключом:

{
  "mcpServers": {
    "ton": {
      "type": "http",
      "url": "https://mcp.tonnode.io/mcp",
      "headers": { "Authorization": "Bearer tn_live_…" }
    }
  }
}

Дальше просто разговариваете с агентом на человеческом языке — он сам выберет нужный инструмент:

«Проверь адрес EQC…: возьми баланс через get_balance, статус аккаунта через get_account_state и последние 10 транзакций через get_transactions. Затем через get_jetton_balance посмотри баланс USDT.»

Агент вызовет нужные инструменты в нужном порядке — а не будет вслепую колотиться в rate limit.

Тарифы

На всех тарифах доступны все 16 инструментов — платите вы только за пропускную способность:

Тариф Цена Пропускная способность
Hobby бесплатно навсегда 60 запросов/мин
Pro $29/мес 300 запросов/мин
Scale $199/мес 1200 запросов/мин

Даже бесплатный Hobby на 60 запросов/мин — это совсем другой режим, чем публичный toncenter с его ~1 rps: те же ~60 запросов в минуту, но уже гарантированно ваши, а не общие с толпой анонимов. Бёрст агента из десятка вызовов проходит целиком, без единого 429. Ключ Hobby выдаётся сразу после входа, без карты.

Оплатить платные тарифы можно в GRAM или USDT в сети TON через TonConnect, либо в BTC/ETH/SOL и других через счёт xRocket в Telegram.

Пара честных оговорок, чтобы не было завышенных ожиданий: TONNode сейчас закрывает задачи чтения и построения транзакций, но не предлагает как готовые продукты pay-per-request, REST-API v2, вебхуки, SSE-стримы или письменный SLA с процентами аптайма. Архивная нода с глубокой историей ещё синхронизируется — это пункт роадмапа, а не сегодняшняя гарантия. Всё, что описано выше, работает уже сейчас.

Практичный план перехода

  1. Заберите бесплатный ключ Hobby (60 запросов/мин, без карты): tonnode.io/dashboard?plan=hobby.
  2. Пропишите hosted-конфиг выше в свой MCP-клиент.
  3. Замените ручные вызовы toncenter на инструменты get_balance, get_account_state, get_transactions, run_get_method, get_jetton_balance.
  4. Как только агент упрётся в 60 запросов/мин под нагрузкой — переходите на Pro за $29/мес (300 запросов/мин): tonnode.io/pricing.

Итог

  • 429 «Too Many Requests» на toncenter — это упор в публичный лимит ~1 rps, а не поломка вашего кода. (И это точно не «228» — такого кода не существует.)
  • ИИ-агенты ловят его чаще всех из-за бёрст-паттерна: десятки вызовов за один тик рассуждения.
  • Ретраи с экспоненциальным бэкоффом, Retry-After, семафор и кэш снижают частоту 429, но потолок не двигают — ценой скорости.
  • Настоящий выход — свой ключ с гарантированной пропускной способностью. А если данные нужны именно агенту, TONNode отдаёт те же чтения TON как MCP-инструменты, и вопрос «как обработать 429» просто исчезает из вашего кода.

Начните бесплатно: получить ключ Hobby — 60 запросов/мин, без карты. Если у агента реальная нагрузка и бёрсты плотные — сразу берите Pro за $29/мес, 300 запросов/мин.

Дайте вашему агенту доступ к TON

16 MCP-инструментов: чтение, некастодиальные свапы, кроссчейн и кошельки. Бесплатный тариф — 60 запр/мин, карта не нужна.