Как убрать ошибку 429 «Too Many Requests» на toncenter
Ошибка 429 «Too Many Requests» на toncenter: почему бьёт по ИИ-агентам, быстрый фикс бэкоффом и настоящее решение — свой ключ с гарантированным throughput.
Токен-агент на 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, всплеск). Он работает тиками: на одном шаге рассуждения ему нужно собрать контекст, и он дёргает десятки вызовов подряд, почти одновременно.
Представьте один шаг: «пользователь просит проверить, пришёл ли платёж». Чтобы ответить, агент за доли секунды дёргает подряд:
get_masterchain_info— узнать текущую голову блокчейна;get_balance— баланс кошелька;get_account_state— статус и флаги аккаунта;get_transactions— последние транзакции;run_get_method— прочитать get-метод контракта;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 с процентами аптайма. Архивная нода с глубокой историей ещё синхронизируется — это пункт роадмапа, а не сегодняшняя гарантия. Всё, что описано выше, работает уже сейчас.
Практичный план перехода
- Заберите бесплатный ключ Hobby (60 запросов/мин, без карты): tonnode.io/dashboard?plan=hobby.
- Пропишите hosted-конфиг выше в свой MCP-клиент.
- Замените ручные вызовы toncenter на инструменты
get_balance,get_account_state,get_transactions,run_get_method,get_jetton_balance. - Как только агент упрётся в 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 запр/мин, карта не нужна.