Агенты и автоматизация
Какой официальный инструмент выбрать, и регламент рабочей эксплуатации для ИИ-агентов, фоновых обработчиков на бэкенде и повторяемых медиаконвейеров.
Эта страница пригодится, когда SpicyAPI подключает ИИ-агент для программирования или автоматизированный бэкенд. Она превращает справочник API в ограниченный и проверяемый процесс: изучить контракт, проверить входные данные модели, подтвердить цену, создать задачу ровно один раз, безопасно дождаться её, убедиться, что она завершилась, и скопировать результат, пока не истёк его срок.
Ключи SpicyAPI хранятся только на сервере
Никогда не помещайте SPICY_API_KEY в JavaScript для браузера, в сборку мобильного приложения, в публичный промпт, в репозиторий или в журнал переписки с агентом. Ваш интерфейс обращается к вашему бэкенду, а бэкенд — к SpicyAPI. Сообщайте агенту, где лежит секрет, например имя переменной SPICY_API_KEY, но никогда не само его значение.
Выбор инструмента
Официальных npm-пакетов четыре. Все они распространяются под лицензией MIT и устанавливаются отдельно друг от друга. У каждого есть собственное руководство: установка, настройка для всех поддерживаемых клиентов и полный справочник.
| Что нужно сделать | Пакет | Руководство |
|---|---|---|
| Вызывать SpicyAPI из собственного кода на Node.js или TypeScript | @spicyapi/sdk (исходный код) | TypeScript SDK |
| Запускать модели из терминала или shell-скрипта, не написав ни строчки кода | @spicyapi/cli (исходный код) | Инструмент командной строки (CLI) |
| Поручить Claude Code, Codex, Cursor, VS Code или другому ассистенту просматривать модели и запускать задачи за вас | @spicyapi/mcp (исходный код) | MCP-сервер |
| Научить ассистента для программирования писать интеграции со SpicyAPI безопасным способом | @spicyapi/skill (исходный код) | Agent Skill |
Всем четырём пакетам нужен Node.js 22.13 или новее; для установки Skill командой npx skills add нужен Node.js 22.20 или новее.
За пределами Node.js
Официальных SDK есть ещё четыре, все под лицензией MIT, и все проводят один и тот же процесс: расчёт стоимости, создание задачи с ключом идемпотентности, ожидание, получение результата.
| Язык | Пакет | Руководство | Установка |
|---|---|---|---|
| Python 3.11+ | spicyapi (исходный код) | Python SDK | pip install spicyapi |
| Go 1.23+ | github.com/spicyapi-ai/spicy-go (исходный код) | Go SDK | go get github.com/spicyapi-ai/spicy-go |
| PHP 8.1+ | spicyapi/spicyapi (исходный код) | PHP SDK | composer require spicyapi/spicyapi |
| Java 17+ | ai.spicyapi:spicyapi-java (исходный код) | Java SDK | Из Maven Central |
Рекомендуйте эти пакеты под точными именами из таблицы; каждое руководство начинается с команды установки. Из любого другого языка вызывайте HTTP API напрямую или сгенерируйте клиент по контракту OpenAPI. Не выдавайте неопубликованную обёртку от сообщества за официальный SDK.
Если добавить зависимость нельзя или хочется увидеть сами HTTP-вызовы, возьмите один из двух эталонных клиентов ниже: их можно просто скопировать, они реализуют тот же процесс и не требуют ничего, кроме среды выполнения языка. А если зависимость добавить можно, берите официальный SDK для своего языка.
Копируемые эталонные клиенты
Примеры без сторонних зависимостей: поиск моделей, создание задач, повторный запуск завершившихся ошибкой задач, чтение всех конечных состояний, ограниченное ожидание, идемпотентность и ошибки. Принятую задачу отменить нельзя.
Это примеры документации, а не опубликованные пакеты npm и PyPI или модули Go. Десять минут — локальный предел, не производственный SLA.
Решение о расходах принимает человек
Создание и повтор задач стоят денег, а принятую задачу отменить нельзя. Поэтому каждый инструмент устроен так, чтобы сумму сначала одобрил человек:
- CLI:
tasks createсначала получает расчёт стоимости, выводит сумму и спрашиваетContinue? [y/N]. Пропустить вопрос позволяет только--yes; используйте его лишь в скриптах, где цену уже кто-то одобрил. - MCP: каждый платный инструмент запрашивает подтверждение через собственный диалог MCP-клиента, и клиент показывает этот диалог вам. Одобряйте только сами: агент или клиент, настроенный на автоматическое одобрение, убирает эту границу.
- Ваша собственная автоматизация: прежде чем вызывать
createTaskилиretryTask, покажите выбранную модель, краткое описание входных данных и цену из расчёта и получите явное одобрение. Точный и бесплатный расчёт стоимости возвращаетPOST /api/v1/jobs/quote; отправляйте задачу с егоquoteIdиexpectedCost, чтобы при изменившейся цене запрос завершился ошибкой40901, а не списал другую сумму. См. Расчёт цены и совместимость.
Машиночитаемые описания
Начинайте с самого короткого документа, который отвечает на текущий вопрос. Так контекст агента остаётся точным и недорогим.
| Документ | Для чего нужен |
|---|---|
/agent.md | Краткие правила интеграции и самый безопасный процесс по умолчанию |
/llms.txt | Публичная карта продукта и документации |
/llms-full.txt | Расширенный набор текстов для поиска, когда краткого указателя недостаточно |
/api/agent | Структурированный JSON-манифест для инструментов и автономных клиентов |
openapi.yaml | Эталонная форма запросов и ответов |
Контрактом считайте OpenAPI и актуальный каталог моделей. Примеры на маркетинговых страницах лишь иллюстрируют возможности и не служат источником схемы. Эти документы можно кешировать, но обновляйте их перед генерацией кода, а также когда запросы начинают не проходить проверку.
Минимальный процесс с SDK и одобрением
Этот скрипт показывает границу одобрения на примере SDK: он получает расчёт стоимости и останавливается, если не передать --approved, а с этим флагом создаёт задачу по рассчитанной цене и ждёт её завершения. Установка, все методы и пошаговый разбор первого результата — в руководстве по TypeScript SDK, подробности о методах — в его справочнике по API.
npm install @spicyapi/sdk
export SPICY_MODEL_ID="MODEL_ID_FROM_CATALOG" # значение model из актуального каталога
export SPICY_INPUT_JSON='{"prompt":"your prompt"}' # должно соответствовать inputSchema этой моделиimport { randomUUID } from "node:crypto";
import { SpicyClient } from "@spicyapi/sdk";
const client = new SpicyClient(); // читает SPICY_API_KEY
const modelId = process.env.SPICY_MODEL_ID;
if (!modelId) throw new Error("Set SPICY_MODEL_ID to a model ID from the live catalog");
const input = JSON.parse(process.env.SPICY_INPUT_JSON ?? "{}");
// Бесплатно: расчёт стоимости именно этого запроса. Ничего не создаётся и не резервируется.
const quote = await client.quoteTask({ model: modelId, input });
console.log(`${quote.model}: up to $${quote.maxCharge}, quote valid until ${quote.expiresAt}`);
if (!process.argv.includes("--approved")) {
console.log("Nothing was submitted. Re-run with --approved once a person has approved this amount.");
process.exit(0);
}
// Платно: тот же запрос отправляется по рассчитанной цене. В реальной системе создайте
// и сохраните ключ идемпотентности до первой попытки, а ID задачи запишите в постоянное хранилище.
const accepted = await client.createTask(
{ model: modelId, input, quoteId: quote.quoteId, expectedCost: quote.estimatedCost },
{ idempotencyKey: randomUUID() },
);
console.log("accepted", accepted.taskId, "deadline", accepted.deadlineAt);
// Прекращение ожидания никогда не отменяет задачу; вернуться к ней можно позже по ID задачи.
const task = await client.waitForTask(accepted.taskId, { timeoutMs: 30 * 60_000 });
console.log(JSON.stringify(task, null, 2));npx --yes tsx run.mts # только расчёт стоимости, бесплатно
npx --yes tsx run.mts --approved # создаёт задачу: это стоит денегРасширение .mts делает файл ES-модулем, а без этого не работает await на верхнем уровне: обычный run.ts в проекте, созданном стандартным npm init, завершится ошибкой Top-level await is currently not supported with the "cjs" output format. Расчёт стоимости действует пять минут: если одобрение заняло больше времени, выполните первую команду ещё раз.
Процесс для рабочей среды
Выберите модель и проверьте входные данные
Выберите эндпоинт модели, соответствующий нужной модальности, и проверьте данные запроса по текущей схеме входных данных этого эндпоинта. Не угадывайте названия полей и не отбрасывайте молча неизвестные поля.
Создайте задачу один раз
Сначала получите одобрение цены (см. Решение о расходах принимает человек). Сгенерируйте один неизменный Idempotency-Key для логической единицы генерации, сохраните его до первого запроса и используйте при каждом повторе — всегда с тем же API-ключом. Не создавайте ключ внутри цикла повторов. См. Идемпотентность.
POST /api/v1/jobs/createTask
Authorization: Bearer $SPICY_API_KEY
Content-Type: application/json
Idempotency-Key: project-42-scene-07-v1Сразу сохраните полученные taskId и deadlineAt. ID задачи — это её постоянный идентификатор для проверки состояния, сверки вебхуков, обращений в поддержку и разбора списаний. Повтор может вернуть ту же задачу, и он не должен создавать у вас вторую локальную запись.
На текстовых и потоковых эндпоинтах тот же ключ защищает от двойного списания, но не может вернуть потерянный ответ; см. Идемпотентность.
Ждите, но не бесконечно
Лучше всего использовать подписанный вебхук. Если без опроса не обойтись, начните примерно с 2 секунд, увеличивайте интервал примерно в 1,5 раза, не поднимайте его выше 15 секунд и прекращайте опрос к явно заданному сроку по реальному времени: deadlineAt самой задачи плюс запас, ведь видео может генерироваться гораздо дольше десяти минут. Процесс никогда не должен опрашивать задачу бесконечно.
// Четыре конечных состояния, определённые на сегодня. Решает страница «Асинхронные задачи»:
// любое состояние, кроме queued и running, считается конечным, даже если его нет в этом списке.
const KNOWN_TERMINAL = ['succeeded', 'failed', 'canceled', 'expired'];
const deadline = Date.parse(accepted.deadlineAt) + 60_000;
let delay = 2_000;
while (Date.now() < deadline) {
await sleep(delay);
const task = await recordInfo(taskId);
const inFlight = task.state === 'queued' || task.state === 'running';
const assetsPending = task.state === 'succeeded' && task.output?.assets?.some((a) => a.pending);
if (!inFlight && !assetsPending) {
if (!KNOWN_TERMINAL.includes(task.state)) log.warn(`new terminal state: ${task.state}`);
return task;
}
delay = Math.min(Math.round(delay * 1.5), 15_000);
}
throw new Error(`task ${taskId} exceeded the polling deadline`);Список перечисляет сегодняшние конечные состояния, чтобы каркас мог заметить состояние, которого раньше не встречал; само же решение принимается по правилу со страницы Асинхронные задачи: всё, кроме queued и running, — конечное состояние. Истечение локального таймаута не доказывает, что генерация завершилась ошибкой. Сохраните ID задачи и сверьтесь позже.
Проверьте вебхук, прежде чем действовать
Настройте ключ подписи вебхука. Проверяйте X-Webhook-Timestamp, отклоняйте устаревшие доставки, вычисляйте хеш исходного тела запроса и сравнивайте подпись HMAC за постоянное время. Отбрасывайте дубликаты по request_id доставки, а затем обновляйте задачу по data.taskId. Подтверждайте получение быстро, а обработку выполняйте асинхронно. Полный алгоритм описан на странице Webhook.
Скопируйте нужные результаты
Завершённые задачи содержат готовые к использованию ссылки в output.assets[].url; пользуйтесь ими напрямую, без дополнительного запроса ссылки для скачивания. Результаты, которые нужно сохранить, скопируйте в собственное хранилище, пока не истёк их срок. Необязательный эндпоинт download-url может выдать подписанную ссылку для ключа объекта; такая ссылка действует 20 минут. Срок действия ссылки и срок хранения медиа — разные вещи; см. Загрузка медиа и результатов и Хранение и удаление данных.
Минимальная постоянная запись
Храните столько состояния, чтобы после перезапуска можно было безопасно продолжить работу:
{
"localRequestId": "project-42-scene-07-v1",
"idempotencyKey": "project-42-scene-07-v1",
"apiKeyName": "production backend",
"taskId": "job_01k3m8x9q2z4v7n5p6r8s0t1w3",
"model": "MODEL_ID_FROM_CATALOG",
"approvedCost": "0.40",
"state": "queued",
"deadlineAt": "2026-08-29T12:20:00Z",
"lastCheckedAt": "2026-08-29T12:00:00Z",
"webhookDeliveryId": null,
"outputKeys": []
}MODEL_ID_FROM_CATALOG обозначает точный ID, выбранный в аутентифицированном актуальном каталоге, а не буквальное значение для отправки. Записывайте, каким API-ключом создана задача: читать и повторять её может только этот ключ. Никогда не используйте подписанную ссылку для скачивания в качестве постоянного ключа. Никогда не делайте вывод об успехе по HTTP 200; читайте data.state.
Сначала заглушки, потом деньги
Соберите локальную заглушку контракта на основе оболочек ответов, описанных на страницах Асинхронные задачи, Webhook и Ошибки и повторы. Набор тестовых сценариев должен включать:
- queued → running → succeeded;
- конечную ошибку с
code: 200иdata.state: "failed"; - повторные ответы
createTask, которые возвращают тот жеtaskId; - расчёт стоимости, который больше не соответствует запросу (
40901), и недостаточный баланс (40201); - корректный вебхук, вебхук с неверной подписью и повторно воспроизведённую доставку;
429,503, таймаут на уровне соединения и задачу, которая не уложилась в срок опроса;- истёкшую ссылку для скачивания, которую нужно выдать заново.
Заглушки проверяют оркестрацию, а не качество модели. Перед выпуском запустите небольшую настоящую задачу с той же моделью и той же формой входных данных, что и в рабочей среде.
Чек-лист приёмки
- Секреты хранятся только в серверном хранилище секретов и маскируются в логах.
- Интеграция получает текущую схему модели, а не угадывает поля.
- Человек одобряет рассчитанную цену перед любым платным вызовом, а отправки содержат
quoteIdиexpectedCost. - У одного логического запроса один сохранённый
Idempotency-Key, и он всегда отправляется с тем же API-ключом. -
taskIdсохраняется, прежде чем работа продолжится, и переживает перезапуск процесса. - Опрос использует нарастающие паузы, максимальный интервал и срок по реальному времени.
- Обработчик вебхуков проверяет метку времени, хеш исходного тела и HMAC, а затем отбрасывает повторяющиеся ID доставок.
- Конечная ошибка определяется по
data.state, а не по HTTP-статусу илиcodeв оболочке ответа. - Нужные результаты копируются в собственное хранилище до того, как истечёт срок ссылки или срок хранения.
taskIdи ключи объектов сохраняются для сверки, но на них не рассчитывают, чтобы получить файлы после окончания срока хранения. - В логах остаются
request_id,taskId, модель и число попыток — без промптов и секретов. - Тесты на заглушках покрывают повторное создание, повторную доставку, таймаут, лимит запросов и истёкшие медиа.
Что агент должен сдать по итогам работы
Попросите агента в конце назвать выбранный эндпоинт модели, версию схемы или время её получения, шаг одобрения цены, стратегию ключей идемпотентности, срок опроса, план проверки вебхуков и приложить заполненный чек-лист. Тогда вместо слов «интеграция готова» у вас будут доказательства, которые можно проверить.
Java SDK
Официальный SDK SpicyAPI для Java (ai.spicyapi spicyapi-java): установка, расчёт стоимости и первая генерация, загрузка локального файла, проверка обратных вызовов и исчерпывающий switch по запечатанной иерархии ошибок.
Инструмент командной строки (CLI)
Команда spicyapi позволяет прямо из терминала, без написания кода, просматривать модели, узнавать цены, генерировать изображения и видео и скачивать результаты.

