Глава 14

Повторяйте запросы только там, где повтор безопасен

Не всякую ошибку лечит повтор. 429, временный 5xx или сетевой обрыв обычно retryable. Ошибка схемы, неверный ключ и policy denial повтором не исправляются - их повтор лишь сожжёт бюджет. А любой write получает idempotency key и проверяемую бизнес-транзакцию, потому что "повторить платёж" и "повторить чтение" - принципиально разные вещи.

Backoff с jitter применяется только к действительно временным ошибкам.

TypeScript
function retryableStatus(status: number) {
  return status === 408 || status === 409 || status === 429 || status >= 500;
}

async function withBackoff<T>(operation: () => Promise<T>) {
  for (let attempt = 0; attempt < 3; attempt += 1) {
    try {
      return await operation();
    } catch (error) {
      if (!isProviderError(error) || !retryableStatus(error.status)) throw error;
      if (attempt === 2) throw error;
      const jitter = Math.floor(Math.random() * 180);
      await delay(250 * 2 ** attempt + jitter);
    }
  }
  throw new Error("unreachable");
}

Важнее самого retry - то, что runtime показывает модели в ответ на разные ошибки.

Ошибка · Действие runtime · Что видит модель

  • Неверные tool arguments - Не запускает handler; invalid_arguments, максимум одна коррекция
  • Источник временно недоступен - Ограниченный retry; Нормализованный tool error
  • Order не принадлежит actor - Возвращает found: false; Без причины, раскрывающей существование чужого заказа
  • Preview истек - Не выполняет commit; Новый расчет через новый turn
  • Provider timeout - Закрывает run, сохраняет trace id; Без повторного side effect

Заметьте, что чужой заказ возвращает found: false без причины, раскрывающей его существование, а истёкший preview не докатывается до commit - новый расчёт идёт через новый turn. Это не про надёжность, а про безопасность.

Сохраняйте request ids. Официальные SDK дают типизированные ошибки и идентификаторы запросов. Записывайте их рядом со своим trace id, но не показывайте внутренние детали конечному пользователю.

Ядро агента собрано - контракт, tools, loop, бюджет, журнал, исходы, стриминг, ошибки. Пора собрать из этого живой продукт: агента поддержки магазина.

Ссылки