# AgentAPI — полная документация > AgentAPI — единый шлюз к 300+ AI-моделям (OpenAI, Anthropic, Google и другие) с API, совместимым с OpenAI. Один ключ, базовый URL https://api.agentapi.ru/v1/ai, оплата в рублях по факту токенов. Все страницы https://agentapi.ru/docs в порядке оглавления, у каждой указан её адрес. --- URL: https://agentapi.ru/docs # AgentAPI AgentAPI — единый шлюз к 300+ AI-моделям. Один ключ, один базовый URL, оплата в рублях. API совместим с форматом OpenAI, поэтому большинство существующих клиентов, SDK и плагинов для редакторов работают без изменений в коде — достаточно поменять `base_url` и ключ. ## Что нужно знать сразу | | | |---|---| | **Base URL** | `https://api.agentapi.ru/v1/ai` | | **Аутентификация** | `x-api-key: agentapi-…` или `Authorization: Bearer agentapi-…` | | **Формат ключа** | `agentapi-` + 48 hex-символов | | **Форматы API** | OpenAI Chat Completions, OpenAI Responses, Anthropic Messages, Embeddings | | **Модели** | формат `провайдер/модель` — `openai/gpt-4.1`, `anthropic/claude-3.5-sonnet` | | **Оплата** | предоплаченный баланс в рублях, списание по факту токенов | | **Swagger** | [api.agentapi.ru/v1/docs](https://api.agentapi.ru/v1/docs) | > Обратите внимание на сегмент `/ai` в базовом URL — он обязателен. > `https://agentapi.ru/v1` (без `api.` и без `/ai`) не существует: основной домен отдаёт сайт. ## Быстрый старт ```bash curl https://api.agentapi.ru/v1/ai/chat/completions \ -H "x-api-key: agentapi-ВАШ_КЛЮЧ" \ -H "Content-Type: application/json" \ -d '{ "model": "openai/gpt-4.1", "messages": [{"role": "user", "content": "Привет!"}] }' ``` Подробнее — [Быстрый старт](https://agentapi.ru/docs/quickstart). ## Контракт запроса ```mermaid flowchart TD A["POST /v1/ai/chat/completions
ключ + model + messages"] --> B{"stream?"} B -- "нет" --> C["200 · application/json
текст в choices.message.content"] B -- "да" --> D["200 · text/event-stream
SSE-кадры, финал DONE"] A -.-> E["401 · проблема с ключом"] A -.-> F["400 · параметры или баланс"] A -.-> G["429 · превышен лимит запросов"] A -.-> H["502 · модель недоступна"] ``` Что важно учесть на стороне клиента: - **Ключ передаётся заголовком** — `x-api-key` или `Authorization: Bearer`, оба варианта равнозначны. См. [Аутентификация](https://agentapi.ru/docs/authentication). - **Ключ показывается один раз** при создании и не может быть восстановлен. См. [API-ключи](https://agentapi.ru/docs/api-keys). - **Стриминг завершается литералом `data: [DONE]`.** Ошибка, случившаяся после начала потока, приходит отдельным кадром при уже отданном статусе 200 — проверяйте поле `error` в каждом кадре. - **Расход списывается с баланса в рублях по факту использованных токенов.** См. [Биллинг](https://agentapi.ru/docs/billing). ## Совместимость Один и тот же аккаунт и ключ работают через четыре формата запроса: | Формат | Эндпоинт | Кому подходит | |---|---|---| | OpenAI Chat Completions | [`POST /v1/ai/chat/completions`](https://agentapi.ru/docs/endpoints/chat-completions) | OpenAI SDK, Continue, Cline, Roo Code, LangChain | | Anthropic Messages | [`POST /v1/ai/messages`](https://agentapi.ru/docs/endpoints/messages) | Anthropic SDK и клиенты Claude | | OpenAI Responses | [`POST /v1/ai/responses`](https://agentapi.ru/docs/endpoints/responses) | клиенты на Responses API | | Embeddings | [`POST /v1/ai/embeddings`](https://agentapi.ru/docs/endpoints/embeddings) | векторный поиск, RAG | Настройка редакторов и плагинов: [Continue](https://agentapi.ru/docs/integrations/continue) · [Cline](https://agentapi.ru/docs/integrations/cline) · [Roo Code](https://agentapi.ru/docs/integrations/roo-code) · [Claude Code](https://agentapi.ru/docs/integrations/claude-code) · [SDK и curl](https://agentapi.ru/docs/integrations/sdk) ## Дальше 1. [Быстрый старт](https://agentapi.ru/docs/quickstart) — первый запрос за 5 минут. 2. [API-ключи](https://agentapi.ru/docs/api-keys) — как создать, где хранить, как отозвать. 3. [Аутентификация](https://agentapi.ru/docs/authentication) — заголовки и ошибки 401. 4. [Модели](https://agentapi.ru/docs/models) — какие слаги использовать. 5. [Ошибки и лимиты](https://agentapi.ru/docs/errors) — коды ответов и rate limit. 6. [Известные ограничения](https://agentapi.ru/docs/limitations) — что пока не поддерживается. --- URL: https://agentapi.ru/docs/quickstart # Быстрый старт От регистрации до первого ответа модели — пять минут. ## 1. Пополните баланс API-ключ нельзя создать при нулевом балансе — попытка вернёт `403 Insufficient balance to create an API key`. Пополните счёт в [профиле](https://agentapi.ru/profile): минимальная сумма — 100 ₽. ## 2. Создайте ключ В профиле откройте раздел «Ваши API ключи» → «Создать ключ» → задайте имя. Ключ вида `agentapi-1f3c…` показывается **один раз** — сразу скопируйте его. Восстановить его потом невозможно: если ключ потерян, удалите его и создайте новый. Подробнее — [API-ключи](https://agentapi.ru/docs/api-keys). ## 3. Первый запрос ```bash curl https://api.agentapi.ru/v1/ai/chat/completions \ -H "x-api-key: agentapi-ВАШ_КЛЮЧ" \ -H "Content-Type: application/json" \ -d '{ "model": "openai/gpt-4.1", "messages": [ {"role": "user", "content": "Назови три факта о Байкале"} ] }' ``` Ответ: ```json { "id": "gen-1753600000-Xf4KpQ2mNvR", "object": "chat.completion", "created": 1753600000, "model": "openai/gpt-4.1", "choices": [ { "index": 0, "message": { "role": "assistant", "content": "1. Байкал — самое глубокое озеро в мире (1642 м)…" }, "finish_reason": "stop" } ], "usage": { "prompt_tokens": 18, "completion_tokens": 96, "total_tokens": 114 } } ``` Поле `usage` показывает израсходованные токены. Списание с баланса идёт в рублях — см. [Биллинг](https://agentapi.ru/docs/billing). ## 4. Подключите SDK AgentAPI совместим с OpenAI SDK. Важно: `base_url` — это `…/v1/ai`, **без** `/chat/completions` (SDK добавит путь сам). ```python from openai import OpenAI client = OpenAI( api_key="agentapi-ВАШ_КЛЮЧ", base_url="https://api.agentapi.ru/v1/ai", ) completion = client.chat.completions.create( model="openai/gpt-4.1", messages=[{"role": "user", "content": "Привет!"}], ) print(completion.choices[0].message.content) ``` ```typescript import OpenAI from "openai"; const client = new OpenAI({ apiKey: "agentapi-ВАШ_КЛЮЧ", baseURL: "https://api.agentapi.ru/v1/ai", }); const completion = await client.chat.completions.create({ model: "openai/gpt-4.1", messages: [{ role: "user", content: "Привет!" }], }); console.log(completion.choices[0].message.content); ``` Отдельный заголовок `x-api-key` при работе через SDK не нужен: параметр `apiKey` отправляет `Authorization: Bearer …`, и это принимается. ## 5. Настройте редактор Тот же ключ работает в плагинах VS Code: - [Continue](https://agentapi.ru/docs/integrations/continue) — чат, автодополнение, embeddings - [Cline](https://agentapi.ru/docs/integrations/cline) — агент, правящий файлы - [Roo Code](https://agentapi.ru/docs/integrations/roo-code) — форк Cline с режимами - [Claude Code](https://agentapi.ru/docs/integrations/claude-code) — через Anthropic-совместимый эндпоинт ## Частые ошибки на старте | Симптом | Причина | |---|---| | `404 Not Found` | В URL нет сегмента `/ai` либо используется `agentapi.ru` вместо `api.agentapi.ru` | | Путь вида `…/chat/completions/chat/completions` | В `base_url` передан полный путь до эндпоинта, а не `…/v1/ai` | | `401 Invalid API key format` | Ключ не начинается с `agentapi-` (например, вставлен ключ OpenAI) | | `400 Negative or zero balance` | Нулевой или отрицательный баланс — пополните счёт | | `404` от провайдера на валидном ключе | Неверный слаг модели: нужен `openai/gpt-4.1`, а не `gpt-4.1` | Полный список — [Ошибки и лимиты](https://agentapi.ru/docs/errors). --- URL: https://agentapi.ru/docs/api-keys # API-ключи ## Формат ``` agentapi-4e1d1cb6e9a2bf62c8a70f5d3b19e84c7a25f0d6b8e34179 └───┬───┘└──────────────────────┬──────────────────────┘ префикс 48 hex-символов ``` Полная длина — 57 символов. Регулярное выражение для валидации: ``` ^agentapi-[0-9a-f]{48}$ ``` Ключ, не начинающийся с `agentapi-`, отклоняется с `401 Invalid API key format`. ## Жизненный цикл 1. **Создание** — требует положительного баланса и уникального имени в рамках аккаунта. 2. **Показ.** Ключ отдаётся в ответе **один раз**. Сохраните его сразу. 3. **Использование** — заголовком `x-api-key` или `Authorization: Bearer`. 4. **Отключение** (`active: false`) — обратимо, ключ перестаёт работать до включения обратно. 5. **Удаление** — необратимо. Что из этого следует на практике: - **Просмотреть существующий ключ невозможно** — ни через интерфейс, ни через API. Доступен только `postfix`, последние 4 символа, чтобы отличать ключи друг от друга в списке. - **Ключ нельзя восстановить.** Если он утерян — удалите его и создайте новый. - **Удаление необратимо.** Приложения, использующие этот ключ, немедленно получат 401. ## Управление через интерфейс Раздел «Ваши API ключи» в [профиле](https://agentapi.ru/profile): создание, просмотр списка, включение/отключение, удаление. ## Управление через API Эти эндпоинты относятся к внутреннему API и требуют **JWT-авторизации пользователя** (не ключа `agentapi-*`). Базовый URL — `https://api.agentapi.ru`, без префикса `/v1`. JWT передаётся как `Authorization: Bearer ` либо в cookie `x-token`. ### Создать ключ ``` POST /api-key/create ``` ```bash curl https://api.agentapi.ru/api-key/create \ -H "Authorization: Bearer $JWT" \ -H "Content-Type: application/json" \ -d '{"apiKeyName": "My App Key"}' ``` Ответ: ```json { "key": "agentapi-4e1d1cb6e9a2bf62c8a70f5d3b19e84c7a25f0d6b8e34179", "hashed": "9f2b7c4e8a1d5f3b6c9e2a7d4f1b8c5e3a6d9f2b7c4e8a1d5f3b6c9e2a7d4f1b", "postfix": "4179" } ``` `key` возвращается только в этом ответе. | Код | Причина | |---|---| | 403 | `Insufficient balance to create an API key` — баланс ≤ 0 | | 404 | `API Key name already exists for this user` — имя занято | | 404 | `User not found` | ### Список ключей ``` GET /api-key ``` ```json { "message": "Returns all apiKeys", "apiKeys": [ { "id": "3f1a8c02-5b7e-4d61-9a3c-8e2f5d7b1c40", "apiKeyName": "My App Key", "postfix": "4179", "active": true, "createdAt": "2026-07-20T11:04:18.512Z" } ] } ``` Сам ключ и служебные поля в этом ответе не возвращаются — только метаданные. ### Отключить или включить ключ ``` PATCH /api-key/update-activity/:id ``` ```bash curl -X PATCH https://api.agentapi.ru/api-key/update-activity/3f1a8c02-5b7e-4d61-9a3c-8e2f5d7b1c40 \ -H "Authorization: Bearer $JWT" \ -H "Content-Type: application/json" \ -d '{"active": false}' ``` Отключённый ключ отдаёт `401 Invalid or inactive API key`. Обратимо: тем же запросом с `"active": true`. ### Удалить ключ ``` DELETE /api-key/:id ``` Ответ — строка `Removed API key #`. Необратимо. ## Ограничения У ключей **нет** скоупов, ограничений по моделям, лимитов расхода и срока жизни — только флаг `active`. Разделение прав между ключами не поддерживается: любой активный ключ имеет полный доступ к API в рамках баланса аккаунта. Rate limit также **не привязан к ключу** — он считается по IP-адресу, см. [Ошибки и лимиты](https://agentapi.ru/docs/errors). ## Рекомендации по безопасности - Храните ключ в переменных окружения или менеджере секретов, не в репозитории. - Ключ даёт прямой доступ к балансу аккаунта — утечка приводит к расходу средств. - Создавайте отдельные ключи под окружения (`dev`, `staging`, `prod`), чтобы отзыв одного не ломал остальные. - Не используйте ключ в браузерном или мобильном коде: он будет виден пользователю. Проксируйте запросы через свой бэкенд. - При подозрении на утечку — удалите ключ; отключения флагом недостаточно, если ключ скомпрометирован. --- URL: https://agentapi.ru/docs/authentication # Аутентификация Все эндпоинты инференса требуют API-ключ. Поддерживаются два заголовка — используйте любой. ## Вариант 1: `x-api-key` Основной вариант платформы. ```bash curl https://api.agentapi.ru/v1/ai/chat/completions \ -H "x-api-key: agentapi-ВАШ_КЛЮЧ" \ -H "Content-Type: application/json" \ -d '{"model":"openai/gpt-4.1","messages":[{"role":"user","content":"Привет!"}]}' ``` ## Вариант 2: `Authorization: Bearer` Именно этот заголовок отправляют OpenAI SDK и большинство плагинов для редакторов, поэтому они работают без дополнительной настройки заголовков. ```bash curl https://api.agentapi.ru/v1/ai/chat/completions \ -H "Authorization: Bearer agentapi-ВАШ_КЛЮЧ" \ -H "Content-Type: application/json" \ -d '{"model":"openai/gpt-4.1","messages":[{"role":"user","content":"Привет!"}]}' ``` Значение после `Bearer ` должно быть самим ключом `agentapi-*`. Передавать здесь JWT пользователя нельзя — эндпоинты инференса принимают только API-ключи. ## Приоритет заголовков Если присланы оба заголовка, используется **`x-api-key`**; `Authorization` игнорируется. Дублировать их не нужно — при работе через SDK достаточно штатного параметра `apiKey`. ## Порядок проверок Ключ проходит проверки в этом порядке, и первая неудачная возвращает 401: 1. Заголовок присутствует → иначе `API key is required in x-api-key or Authorization header` 2. Ключ начинается с `agentapi-` → иначе `Invalid API key format` 3. Ключ существует и активен → иначе `Invalid or inactive API key` 4. Ключ связан с существующим пользователем → иначе `API key not found` Формат ответа: ```json { "statusCode": 401, "message": "Invalid or inactive API key", "error": "Unauthorized" } ``` ## CORS Для внешнего API (`/v1*`) CORS открыт: разрешённые заголовки — `Content-Type`, `Authorization`, `x-token`, `x-api-key`. Технически это позволяет обращаться к API прямо из браузера, но **так делать не нужно**: ключ станет доступен любому пользователю страницы, а вместе с ним — и баланс аккаунта. Проксируйте запросы через свой сервер. ## Внутреннее API Управление аккаунтом (`/api-key/*`, `/billing/*`, `/user/*`, `/stats/*`) использует не API-ключ, а **JWT** — в заголовке `Authorization: Bearer ` либо в cookie `x-token`. Эти эндпоинты живут на том же хосте, но без префикса `/v1`. | | Инференс | Управление аккаунтом | |---|---|---| | Префикс | `/v1/ai/*` | без префикса | | Учётные данные | ключ `agentapi-*` | JWT пользователя | | Заголовок | `x-api-key` или `Authorization: Bearer` | `Authorization: Bearer` или cookie `x-token` | --- URL: https://agentapi.ru/docs/models # Модели ## Формат идентификатора Модель задаётся слагом в формате `провайдер/модель`: ``` openai/gpt-4.1 anthropic/claude-3.5-sonnet google/gemini-2.0-flash deepseek/deepseek-chat ``` Слаг без префикса провайдера (`gpt-4.1`) невалиден и приведёт к ошибке от провайдера. Актуальные слаги смотрите в каталоге [Модели](https://agentapi.ru/models) на сайте. ## Список моделей ``` GET https://api.agentapi.ru/models ``` Эндпоинт публичный — ключ не требуется. Обратите внимание: он **без префикса `/v1`**. | Параметр | Тип | По умолчанию | Описание | |---|---|---|---| | `q` | string | — | Поиск по названию или слагу | | `limit` | number | 10 | Размер страницы | | `page` | number | 1 | Номер страницы | | `order` | string | — | Сортировка (см. ниже) | Значения `order`: `newest`, `most-popular`, `top-weekly`, `pricing-low-to-high`, `pricing-high-to-low`, `context-high-to-low`, `latency-low-to-high`, `throughput-high-to-low`. ```bash curl "https://api.agentapi.ru/models?q=claude&limit=2&order=newest" ``` ```json { "data": [ { "id": "anthropic/claude-3.5-sonnet", "name": "Anthropic: Claude 3.5 Sonnet", "context_length": 200000, "pricing": { "prompt": "0.000003", "completion": "0.000015" }, "architecture": { "input_modalities": ["text", "image"], "output_modalities": ["text"] } } ], "total": 14, "total_pages": 7 } ``` Поле `pricing` — справочные тарифы модели за токен. Итоговое списание с баланса идёт в рублях, см. [Биллинг](https://agentapi.ru/docs/billing). ## Чего в этом списке нет - **Embedding-модели отфильтрованы.** Всё, что отдаёт `embeddings` в `output_modalities`, из выдачи исключается. Названия для [эндпоинта embeddings](https://agentapi.ru/docs/endpoints/embeddings) берите из документации провайдера. - **Эндпоинта `GET /v1/ai/models` не существует.** Плагины, которые подтягивают список моделей автоматически, покажут пустой список — слаг нужно вводить руками. Это отражено в инструкциях по [интеграциям](https://agentapi.ru/docs/integrations/continue). ## Выбор модели по умолчанию Поле `model` необязательно, но полагаться на это не стоит: без явного указания выбор модели остаётся на стороне провайдера, а в статистику расходов запрос попадёт под служебным именем. Всегда указывайте `model` явно. ## Fallback при отказе Вместо одной модели можно передать приоритетный список — если первая недоступна, используется следующая: ```json { "models": ["openai/gpt-4.1", "anthropic/claude-3.5-sonnet", "deepseek/deepseek-chat"], "messages": [{"role": "user", "content": "Привет!"}] } ``` Модель, которая фактически ответила, возвращается в поле `model`. ## Предпочтения провайдера Один и тот же слаг может обслуживаться разными хостингами. Порядок можно задать: ```json { "model": "openai/gpt-4.1", "messages": [{"role": "user", "content": "Привет!"}], "provider": { "order": ["openai", "azure"], "allow_fallbacks": true } } ``` --- URL: https://agentapi.ru/docs/endpoints/chat-completions # Chat Completions ``` POST https://api.agentapi.ru/v1/ai/chat/completions ``` Основной эндпоинт. Совместим с OpenAI Chat Completions API, включая стриминг и вызов инструментов. ## Параметры Принимаются оба варианта написания: `max_tokens` и `maxTokens`, `top_p` и `topP` и так далее. Если указаны оба — приоритет у camelCase. | Параметр | Тип | Описание | |---|---|---| | `messages` | array | **Обязательный.** Массив сообщений диалога | | `model` | string | Слаг модели, например `openai/gpt-4.1` | | `models` | string[] | Список моделей для fallback-роутинга: при отказе первой берётся следующая | | `temperature` | number | 0–2. Выше — разнообразнее | | `max_tokens` | number | ≥ 1. Лимит генерируемых токенов | | `max_completion_tokens` | number | ≥ 1. Альтернатива `max_tokens` | | `top_p` | number | 0–1. Nucleus sampling | | `frequency_penalty` | number | −2…2. Штраф за частоту повторов | | `presence_penalty` | number | −2…2. Штраф за повторное появление | | `stop` | string \| string[] | Стоп-последовательности | | `stream` | boolean | Включить SSE-стриминг | | `seed` | number | Сид для воспроизводимости | | `response_format` | object | Например `{"type": "json_object"}` | | `tools` | array | Определения инструментов (function calling) | | `tool_choice` | string \| object | `auto`, `none`, `required` или конкретный инструмент | | `logit_bias` | object | Смещения вероятностей по id токенов | | `logprobs` | boolean | Возвращать логарифмы вероятностей | | `top_logprobs` | number | 0–20 | | `user` | string | Идентификатор конечного пользователя | | `session_id` | string | ≤ 128 символов. Группировка запросов | | `metadata` | object | Произвольные строковые пары для трекинга | | `provider` | object | Предпочтения роутинга, например `{"order": ["openai"]}` | | `plugins` | array | Дополнительные плагины, например веб-поиск | | `reasoning` | boolean \| object | Настройка reasoning. `true` эквивалентно `{"effort": "medium"}` | | `stream_options` | object | `{"include_usage": true}` — добавить `usage` в поток | ### Сообщения | Поле | Тип | Описание | |---|---|---| | `role` | string | `system`, `user`, `assistant` или `tool` | | `content` | string | Текст сообщения | | `tool_call_id` | string | Для роли `tool` — id вызова, на который отвечаем | | `tool_calls` | array | Для роли `assistant` — вызовы инструментов | > `content` принимает только строку. Массивы блоков (`[{"type": "image_url", …}]`) > отклоняются с 400 — мультимодальный ввод пока не поддерживается, см. > [Ограничения](https://agentapi.ru/docs/limitations). ## Пример запроса ```bash curl https://api.agentapi.ru/v1/ai/chat/completions \ -H "x-api-key: agentapi-ВАШ_КЛЮЧ" \ -H "Content-Type: application/json" \ -d '{ "model": "openai/gpt-4.1", "messages": [ {"role": "system", "content": "Отвечай кратко."}, {"role": "user", "content": "Что такое CAP-теорема?"} ], "temperature": 0.3, "max_tokens": 200 }' ``` ```typescript import OpenAI from "openai"; const client = new OpenAI({ apiKey: process.env.AGENTAPI_KEY, baseURL: "https://api.agentapi.ru/v1/ai", }); const completion = await client.chat.completions.create({ model: "openai/gpt-4.1", messages: [ { role: "system", content: "Отвечай кратко." }, { role: "user", content: "Что такое CAP-теорема?" }, ], temperature: 0.3, max_tokens: 200, }); console.log(completion.choices[0].message.content); console.log(completion.usage); ``` ```python import os from openai import OpenAI client = OpenAI( api_key=os.environ["AGENTAPI_KEY"], base_url="https://api.agentapi.ru/v1/ai", ) completion = client.chat.completions.create( model="openai/gpt-4.1", messages=[ {"role": "system", "content": "Отвечай кратко."}, {"role": "user", "content": "Что такое CAP-теорема?"}, ], temperature=0.3, max_tokens=200, ) print(completion.choices[0].message.content) ``` ## Ответ ```json { "id": "gen-1753600412-8Kd2nRxVqLm", "object": "chat.completion", "created": 1753600412, "model": "openai/gpt-4.1", "choices": [ { "index": 0, "message": { "role": "assistant", "content": "CAP-теорема утверждает, что распределённая система не может одновременно гарантировать согласованность (Consistency), доступность (Availability) и устойчивость к разделению сети (Partition tolerance) — при разделении приходится выбирать между C и A." }, "finish_reason": "stop" } ], "usage": { "prompt_tokens": 24, "completion_tokens": 71, "total_tokens": 95 } } ``` | Поле | Описание | |---|---| | `id` | Идентификатор генерации | | `object` | Всегда `chat.completion` | | `created` | Unix-время | | `model` | Фактически использованная модель (может отличаться при fallback) | | `choices[].finish_reason` | `stop`, `length`, `tool_calls`, `content_filter` | | `usage` | Израсходованные токены | Списание с баланса идёт в рублях — см. [Биллинг](https://agentapi.ru/docs/billing). ## Стриминг Передайте `"stream": true`. Ответ приходит как `text/event-stream`. ```bash curl -N https://api.agentapi.ru/v1/ai/chat/completions \ -H "x-api-key: agentapi-ВАШ_КЛЮЧ" \ -H "Content-Type: application/json" \ -d '{ "model": "openai/gpt-4.1", "messages": [{"role": "user", "content": "Считай до трёх"}], "stream": true }' ``` Поток кадров: ``` data: {"id":"gen-1753600500-Qm4","object":"chat.completion.chunk","created":1753600500,"model":"openai/gpt-4.1","choices":[{"index":0,"delta":{"role":"assistant","content":""}}]} data: {"id":"gen-1753600500-Qm4","object":"chat.completion.chunk","created":1753600500,"model":"openai/gpt-4.1","choices":[{"index":0,"delta":{"content":"Один"}}]} data: {"id":"gen-1753600500-Qm4","object":"chat.completion.chunk","created":1753600500,"model":"openai/gpt-4.1","choices":[{"index":0,"delta":{"content":", два"}}]} data: {"id":"gen-1753600500-Qm4","object":"chat.completion.chunk","created":1753600500,"model":"openai/gpt-4.1","choices":[{"index":0,"delta":{"content":", три."},"finish_reason":"stop"}]} data: {"id":"gen-1753600500-Qm4","object":"chat.completion.chunk","created":1753600500,"model":"openai/gpt-4.1","choices":[],"usage":{"prompt_tokens":12,"completion_tokens":8,"total_tokens":20}} data: [DONE] ``` Особенности: - Последний кадр перед `[DONE]` содержит `usage` — он запрашивается всегда, даже если вы не передали `stream_options`. - Признак конца потока — литерал `data: [DONE]`. - Ошибка **посреди** потока приходит кадром `data: {"error":{"message":…}}`, при том что HTTP-статус уже 200 (заголовки отправлены до начала генерации). Обрабатывайте поле `error` в каждом кадре, а не только код ответа. ## Вызов инструментов ```bash curl https://api.agentapi.ru/v1/ai/chat/completions \ -H "x-api-key: agentapi-ВАШ_КЛЮЧ" \ -H "Content-Type: application/json" \ -d '{ "model": "openai/gpt-4.1", "messages": [{"role": "user", "content": "Какая погода в Иркутске?"}], "tools": [{ "type": "function", "function": { "name": "get_weather", "description": "Текущая погода в городе", "parameters": { "type": "object", "properties": { "city": {"type": "string", "description": "Название города"} }, "required": ["city"] } } }], "tool_choice": "auto" }' ``` Ответ: ```json { "id": "gen-1753600730-Zt9", "object": "chat.completion", "created": 1753600730, "model": "openai/gpt-4.1", "choices": [ { "index": 0, "message": { "role": "assistant", "content": null, "tool_calls": [ { "index": 0, "id": "call_9fK2mQ", "type": "function", "function": { "name": "get_weather", "arguments": "{\"city\":\"Иркутск\"}" } } ] }, "finish_reason": "tool_calls" } ], "usage": {"prompt_tokens": 68, "completion_tokens": 19, "total_tokens": 87} } ``` Результат возвращается сообщением с ролью `tool`: ```json { "model": "openai/gpt-4.1", "messages": [ {"role": "user", "content": "Какая погода в Иркутске?"}, {"role": "assistant", "content": null, "tool_calls": [ {"index": 0, "id": "call_9fK2mQ", "type": "function", "function": {"name": "get_weather", "arguments": "{\"city\":\"Иркутск\"}"}} ]}, {"role": "tool", "tool_call_id": "call_9fK2mQ", "content": "{\"temp_c\": -3, \"sky\": \"снег\"}"} ] } ``` Имена свойств внутри `tools[].function.parameters` (JSON Schema) и ключи `metadata` передаются без изменений. ## Fallback-роутинг Вместо одной модели можно передать список — при отказе используется следующая: ```json { "models": ["openai/gpt-4.1", "anthropic/claude-3.5-sonnet"], "messages": [{"role": "user", "content": "Привет!"}] } ``` Фактически ответившая модель указана в поле `model` ответа. ## Коды ошибок | Код | Причина | |---|---| | 400 | Невалидные параметры или нулевой баланс | | 401 | Ключ отсутствует, неверного формата, отключён или не найден | | 429 | Превышен rate limit | | 502 | Ошибка провайдера. Тело: `{"message": "…"}` | Подробнее — [Ошибки и лимиты](https://agentapi.ru/docs/errors). --- URL: https://agentapi.ru/docs/endpoints/messages # Messages (формат Anthropic) ``` POST https://api.agentapi.ru/v1/ai/messages ``` Эндпоинт принимает запросы в формате Anthropic Messages API и отдаёт настоящие Anthropic-ответы, включая корректный SSE с событиями `message_start`, `content_block_delta` и `message_stop`. Внутри запрос транслируется в вызов провайдера и обратно. > **Про путь.** Обратите внимание: эндпоинт — `/v1/ai/messages`, а не `/v1/messages`. > Клиенты, которые жёстко дописывают `/v1/messages` к базовому URL, требуют отдельной > настройки — см. [Claude Code](https://agentapi.ru/docs/integrations/claude-code). ## Параметры | Параметр | Тип | Описание | |---|---|---| | `messages` | array | **Обязательный.** Сообщения с ролями `user` / `assistant` | | `model` | string | Слаг модели, например `anthropic/claude-3.5-sonnet` | | `max_tokens` | number | Лимит генерации | | `system` | string | Системная инструкция (отдельным полем, не сообщением) | | `temperature` | number | 0–1 | | `top_p` | number | Nucleus sampling | | `top_k` | number | Ограничение выборки по top-k | | `stop_sequences` | string[] | Принимается, но **не применяется**, см. [Ограничения](https://agentapi.ru/docs/limitations) | | `stream` | boolean | Включить SSE | | `tools` | array | Инструменты в формате Anthropic: `{name, description, input_schema}` | | `tool_choice` | object | Управление выбором инструмента | | `thinking` | object | `{"type": "enabled", "budget_tokens": 2048}` | | `metadata` | object | Произвольные метаданные | Обратите внимание: здесь параметры именно в snake_case (`max_tokens`, `top_p`) — как в оригинальном Anthropic API. ## Пример запроса ```bash curl https://api.agentapi.ru/v1/ai/messages \ -H "x-api-key: agentapi-ВАШ_КЛЮЧ" \ -H "Content-Type: application/json" \ -d '{ "model": "anthropic/claude-3.5-sonnet", "max_tokens": 300, "system": "Отвечай кратко и по делу.", "messages": [ {"role": "user", "content": "Чем отличается mutex от semaphore?"} ] }' ``` ## Ответ ```json { "id": "msg_7c1f9e2a-4b83-4d51-9f26-1a8e5d3c7b40", "type": "message", "role": "assistant", "model": "anthropic/claude-3.5-sonnet", "content": [ { "type": "text", "text": "Mutex допускает владение только одним потоком и требует освобождения тем же потоком. Semaphore — это счётчик, разрешающий одновременный доступ N потокам." } ], "stop_reason": "end_turn", "stop_sequence": null, "usage": { "input_tokens": 21, "output_tokens": 58 } } ``` | Поле | Описание | |---|---| | `id` | Формат `msg_` | | `type` | Всегда `message` | | `content[]` | Блоки: `text`, `thinking`, `tool_use` | | `stop_reason` | `end_turn`, `max_tokens`, `tool_use`, `stop_sequence` | | `usage` | `input_tokens` / `output_tokens` — терминология Anthropic | ## Стриминг С `"stream": true` приходит SSE с **именованными** событиями (в отличие от Chat Completions, где события безымянные): ``` event: message_start data: {"type":"message_start","message":{"id":"msg_7c1f9e2a","type":"message","role":"assistant","model":"anthropic/claude-3.5-sonnet","content":[],"stop_reason":null,"usage":{"input_tokens":21,"output_tokens":0}}} event: content_block_start data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}} event: content_block_delta data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Mutex"}} event: content_block_delta data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" допускает"}} event: content_block_stop data: {"type":"content_block_stop","index":0} event: message_delta data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"output_tokens":58}} event: message_stop data: {"type":"message_stop"} ``` Типы дельт: | `delta.type` | Когда | |---|---| | `text_delta` | Обычный текст | | `thinking_delta` | Блок размышлений при включённом `thinking` | | `input_json_delta` | Аргументы инструмента приходят по частям | Ошибка посреди потока: ``` event: error data: {"type":"error","error":{"type":"api_error","message":"..."}} ``` ## Инструменты Формат Anthropic — `input_schema` вместо `parameters`: ```json { "model": "anthropic/claude-3.5-sonnet", "max_tokens": 512, "messages": [{"role": "user", "content": "Погода в Иркутске?"}], "tools": [ { "name": "get_weather", "description": "Текущая погода в городе", "input_schema": { "type": "object", "properties": {"city": {"type": "string"}}, "required": ["city"] } } ] } ``` Ответ содержит блок `tool_use`: ```json { "id": "msg_2d5a8f31-9c74-4e60-b1a3-6f9d2c8e5b17", "type": "message", "role": "assistant", "content": [ { "type": "tool_use", "id": "toolu_01A9F2", "name": "get_weather", "input": {"city": "Иркутск"} } ], "stop_reason": "tool_use", "usage": {"input_tokens": 64, "output_tokens": 22} } ``` ## Режим размышлений ```json { "model": "anthropic/claude-3.5-sonnet", "max_tokens": 2048, "thinking": {"type": "enabled", "budget_tokens": 1024}, "messages": [{"role": "user", "content": "Реши: 17 × 23 без калькулятора"}] } ``` В ответе появится блок `{"type": "thinking", "thinking": "…"}` перед текстовым блоком. ## Коды ошибок | Код | Причина | |---|---| | 400 | Невалидные параметры или нулевой баланс | | 401 | Проблема с ключом | | 429 | Rate limit | | 502 | Ошибка провайдера | --- URL: https://agentapi.ru/docs/endpoints/responses # Responses (OpenAI Responses API) ``` POST https://api.agentapi.ru/v1/ai/responses ``` Формат OpenAI Responses API: вместо массива `messages` передаётся `input`, а системная инструкция — отдельным полем `instructions`. > **Стриминг не поддерживается.** Параметр `stream` принимается, но игнорируется — > ответ всегда приходит целиком. Если нужен поток, используйте > [Chat Completions](https://agentapi.ru/docs/endpoints/chat-completions) или > [Messages](https://agentapi.ru/docs/endpoints/messages). ## Параметры Здесь параметры в snake_case — как в оригинальном API. | Параметр | Тип | Описание | |---|---|---| | `input` | string \| array | **Основной ввод.** Текст или массив элементов | | `model` | string | Слаг модели | | `instructions` | string | Системная инструкция | | `max_output_tokens` | number | Лимит генерации | | `temperature` | number | 0–2 | | `top_p` | number | Nucleus sampling | | `frequency_penalty` | number | −2…2 | | `presence_penalty` | number | −2…2 | | `tools` | array | Инструменты в формате `{type, name, description, parameters}` | | `tool_choice` | string \| object | Управление выбором инструмента | | `previous_response_id` | string | Связывание с предыдущим ответом | | `reasoning` | object | Настройка reasoning | | `session_id` | string | Группировка запросов | | `metadata` | object | Метаданные | | `provider` | object | Предпочтения роутинга | | `plugins` | array | Дополнительные плагины | | `user` | string | Идентификатор конечного пользователя | | `stream` | boolean | Принимается, но не действует | ## Пример запроса ```bash curl https://api.agentapi.ru/v1/ai/responses \ -H "x-api-key: agentapi-ВАШ_КЛЮЧ" \ -H "Content-Type: application/json" \ -d '{ "model": "openai/gpt-4.1", "instructions": "Ты лаконичный ассистент.", "input": "Перечисли три принципа SOLID", "max_output_tokens": 200 }' ``` ## Ответ ```json { "id": "resp_6a2f9c14", "object": "response", "created_at": 1753601180, "model": "openai/gpt-4.1", "status": "completed", "output": [ { "type": "message", "role": "assistant", "content": [ { "type": "output_text", "text": "1. Single Responsibility — у класса одна причина для изменения.\n2. Open/Closed — открыт для расширения, закрыт для модификации.\n3. Liskov Substitution — подтип заменяет базовый тип без нарушения контракта." } ] } ], "usage": { "input_tokens": 19, "output_tokens": 74, "total_tokens": 93 } } ``` Текст лежит в `output[0].content[0].text` — глубже, чем в Chat Completions. Терминология токенов — `input_tokens` / `output_tokens`. ## Инструменты В отличие от Chat Completions, описание инструмента здесь плоское — без вложенного объекта `function`: ```json { "model": "openai/gpt-4.1", "input": "Погода в Иркутске?", "tools": [ { "type": "function", "name": "get_weather", "description": "Текущая погода в городе", "parameters": { "type": "object", "properties": {"city": {"type": "string"}}, "required": ["city"] } } ] } ``` ## Коды ошибок | Код | Причина | |---|---| | 400 | Невалидные параметры или нулевой баланс | | 401 | Проблема с ключом | | 429 | Rate limit | | 502 | Ошибка провайдера | --- URL: https://agentapi.ru/docs/endpoints/embeddings # Embeddings ``` POST https://api.agentapi.ru/v1/ai/embeddings ``` Векторные представления текста — для семантического поиска, RAG и кластеризации. Совместим с OpenAI Embeddings API. ## Параметры | Параметр | Тип | Описание | |---|---|---| | `input` | string \| string[] | **Обязательный.** Текст или массив текстов | | `model` | string | **Обязательный.** Модель с поддержкой embeddings, например `openai/text-embedding-3-small` | | `encoding_format` | string | `float` (по умолчанию) или `base64` | | `dimensions` | number | Размерность вектора, если модель это поддерживает | | `input_type` | string | Подсказка типа входа: `query` или `document` | | `user` | string | Идентификатор конечного пользователя | | `provider` | object | Предпочтения роутинга | > В отличие от остальных эндпоинтов, здесь **строгая валидация**: неизвестные поля > вызывают `400`. Поддерживаются оба написания — `encoding_format` и `encodingFormat`, > `input_type` и `inputType`. ## Пример запроса ```bash curl https://api.agentapi.ru/v1/ai/embeddings \ -H "x-api-key: agentapi-ВАШ_КЛЮЧ" \ -H "Content-Type: application/json" \ -d '{ "model": "openai/text-embedding-3-small", "input": "Байкал — самое глубокое озеро в мире" }' ``` ```python from openai import OpenAI client = OpenAI( api_key="agentapi-ВАШ_КЛЮЧ", base_url="https://api.agentapi.ru/v1/ai", ) result = client.embeddings.create( model="openai/text-embedding-3-small", input=["Первый документ", "Второй документ"], ) for item in result.data: print(item.index, len(item.embedding)) ``` ## Ответ ```json { "id": "emb-1753601440-Lp7", "object": "list", "model": "openai/text-embedding-3-small", "data": [ { "object": "embedding", "index": 0, "embedding": [-0.0142, 0.0318, -0.0071, 0.0455, "…ещё 1532 значения"] } ], "usage": { "prompt_tokens": 11, "total_tokens": 11 } } ``` При массиве на входе элементы `data` идут в том же порядке, а `index` соответствует позиции во входном массиве. ## Пакетная обработка Передавайте массив вместо отдельных запросов — это быстрее и дешевле по накладным расходам: ```json { "model": "openai/text-embedding-3-small", "input": [ "Первый документ", "Второй документ", "Третий документ" ] } ``` ## Уменьшение размерности Некоторые модели позволяют сократить вектор — меньше памяти в векторной базе при небольшой потере качества: ```json { "model": "openai/text-embedding-3-small", "input": "Текст", "dimensions": 512 } ``` ## Rate limit Этот эндпоинт **исключён из общего ограничения** запросов в минуту — пакетная индексация не упирается в лимит. Ограничением остаётся баланс аккаунта. ## Коды ошибок | Код | Причина | |---|---| | 400 | Отсутствует `model`/`input`, неизвестное поле, или нулевой баланс | | 401 | Проблема с ключом | | 502 | Ошибка провайдера, либо модель не поддерживает embeddings | Модели с поддержкой embeddings **не отображаются** в общем списке [`GET /models`](https://agentapi.ru/docs/models) — он их отфильтровывает. Названия берите из документации провайдера. --- URL: https://agentapi.ru/docs/integrations/continue # Continue (VS Code / JetBrains) [Continue](https://continue.dev) — открытый ассистент для VS Code и JetBrains: чат, автодополнение и правки в редакторе. Поддерживает провайдер `openai` с произвольным `apiBase`, поэтому AgentAPI подключается без плагинов и прокси. ## Какой эндпоинт для какой роли ```mermaid flowchart LR subgraph IDE["Continue в редакторе"] C1["Чат"] C2["Автодополнение
(tab)"] C3["@codebase
индексация"] C4["Rerank"] end C1 --> E1["POST /v1/ai/chat/completions"] C2 --> E1 C3 --> E2["POST /v1/ai/embeddings"] C4 -.->|"не поддерживается"| X["нет эндпоинта rerank"] E1 --> A["api.agentapi.ru"] E2 --> A ``` ## Настройка Откройте `~/.continue/config.yaml` (в новых версиях — кнопка настроек в панели Continue). ```yaml name: AgentAPI version: 1.0.0 schema: v1 models: - name: GPT-4.1 provider: openai model: openai/gpt-4.1 apiBase: https://api.agentapi.ru/v1/ai apiKey: agentapi-ВАШ_КЛЮЧ roles: - chat - edit - apply - name: Claude 3.5 Sonnet provider: openai model: anthropic/claude-3.5-sonnet apiBase: https://api.agentapi.ru/v1/ai apiKey: agentapi-ВАШ_КЛЮЧ roles: - chat - edit - name: Автодополнение provider: openai model: openai/gpt-4.1-mini apiBase: https://api.agentapi.ru/v1/ai apiKey: agentapi-ВАШ_КЛЮЧ roles: - autocomplete - name: Embeddings provider: openai model: openai/text-embedding-3-small apiBase: https://api.agentapi.ru/v1/ai apiKey: agentapi-ВАШ_КЛЮЧ roles: - embed ``` Три обязательных момента: 1. **`provider: openai`** — именно `openai`, даже для моделей Claude или Gemini: AgentAPI отдаёт OpenAI-совместимый формат для всех моделей. 2. **`apiBase` заканчивается на `/v1/ai`** — без `/chat/completions`. Continue допишет путь сам. 3. **`model` — полный слаг** с префиксом провайдера: `openai/gpt-4.1`, не `gpt-4.1`. ### Старый формат `config.json` Если у вас версия с JSON-конфигом: ```json { "models": [ { "title": "GPT-4.1", "provider": "openai", "model": "openai/gpt-4.1", "apiBase": "https://api.agentapi.ru/v1/ai", "apiKey": "agentapi-ВАШ_КЛЮЧ" } ], "tabAutocompleteModel": { "title": "Автодополнение", "provider": "openai", "model": "openai/gpt-4.1-mini", "apiBase": "https://api.agentapi.ru/v1/ai", "apiKey": "agentapi-ВАШ_КЛЮЧ" }, "embeddingsProvider": { "provider": "openai", "model": "openai/text-embedding-3-small", "apiBase": "https://api.agentapi.ru/v1/ai", "apiKey": "agentapi-ВАШ_КЛЮЧ" } } ``` ## Индексация проекта (`@codebase`) Роль `embed` из конфига выше включает семантический поиск по коду. Эндпоинт embeddings **не подпадает под rate limit**, поэтому первичная индексация большого репозитория не упирается в ограничение запросов — но токены оплачиваются, так что для крупных монорепозиториев оцените стоимость заранее. ## Параметры генерации Ограничения задаются как обычно и **применяются**: ```yaml models: - name: GPT-4.1 provider: openai model: openai/gpt-4.1 apiBase: https://api.agentapi.ru/v1/ai apiKey: agentapi-ВАШ_КЛЮЧ defaultCompletionOptions: temperature: 0.2 maxTokens: 2048 ``` ## Что не заработает | Возможность | Причина | |---|---| | Выпадающий список моделей | Внешнего `GET /v1/ai/models` нет — модели описываются в конфиге вручную | | Rerank-модели | Эндпоинта переранжирования у AgentAPI нет. Не указывайте роль `rerank` | | Прикрепление изображений в чате | `content` принимает только строку, см. [Ограничения](https://agentapi.ru/docs/limitations) | ## Диагностика | Симптом | Что проверить | |---|---| | `404` в логах Continue | В `apiBase` пропущен `/ai`, либо указан `agentapi.ru` вместо `api.agentapi.ru` | | Путь `…/chat/completions/chat/completions` | В `apiBase` записан полный путь эндпоинта | | `401 Invalid API key format` | В `apiKey` не ключ `agentapi-*` | | `400 Negative or zero balance` | Пустой баланс — пополните счёт | | `502` при валидном ключе | Неверный слаг модели — проверьте в каталоге [Моделей](https://agentapi.ru/models) | Логи: **Output → Continue** в панели VS Code. --- URL: https://agentapi.ru/docs/integrations/cline # Cline (VS Code) [Cline](https://github.com/cline/cline) — автономный агент в VS Code: читает и правит файлы, запускает команды в терминале. Поддерживает провайдер «OpenAI Compatible», через него и подключается AgentAPI. ## Настройка 1. Установите расширение **Cline** из Marketplace. 2. Откройте панель Cline → значок настроек (⚙). 3. Заполните поля: | Поле | Значение | |---|---| | **API Provider** | `OpenAI Compatible` | | **Base URL** | `https://api.agentapi.ru/v1/ai` | | **API Key** | `agentapi-ВАШ_КЛЮЧ` | | **Model ID** | `anthropic/claude-3.5-sonnet` | Base URL заканчивается на `/v1/ai` — Cline сам добавляет `/chat/completions`. Model ID вводится вручную полным слагом: список моделей автоматически не подгружается, так как внешнего `GET /v1/ai/models` у AgentAPI нет. ## Выбор модели Cline ведёт длинные многоходовые диалоги с большим контекстом (содержимое файлов, история вызовов инструментов), поэтому расход токенов заметно выше, чем в обычном чате. Разумные варианты: | Модель | Когда | |---|---| | `anthropic/claude-3.5-sonnet` | Базовый выбор: хорошо следует инструкциям агента | | `openai/gpt-4.1` | Альтернатива с большим контекстом | | `deepseek/deepseek-chat` | Существенно дешевле для простых задач | Проверяйте расход в [статистике](https://agentapi.ru/docs/billing) после первых сессий. ## Настройка контекста В расширенных настройках Cline стоит задать: - **Max output tokens** — ограничивает длину одного ответа; параметр доходит до API и применяется. - **Auto-approve** — держите выключенным, пока не убедитесь в поведении модели: агент исполняет команды в терминале. ## Про вызов инструментов Cline описывает инструменты текстом системного промпта и разбирает ответ модели сам, не полагаясь на native function calling. Поэтому агентный цикл работает на любой достаточно сильной модели. ## Что учесть | Особенность | Следствие | |---|---| | Нет списка моделей | Model ID вводится руками | | Изображения в контексте | Не поддерживаются: `content` принимает только строку (см. [Ограничения](https://agentapi.ru/docs/limitations)) | | Rate limit по IP | 60 запросов в минуту на IP. Активный агентный цикл может упереться — при 429 подождите минуту | ## Диагностика | Симптом | Что проверить | |---|---| | `404 Not Found` | В Base URL пропущен `/ai` или указан не тот хост | | `401 Invalid API key format` | Ключ должен начинаться с `agentapi-` | | `400 Negative or zero balance` | Пополните баланс | | `502` | Неверный Model ID — сверьтесь с каталогом [Моделей](https://agentapi.ru/models) | | `429` | Лимит 60 запросов/минуту по IP | --- URL: https://agentapi.ru/docs/integrations/roo-code # Roo Code (VS Code) [Roo Code](https://github.com/RooCodeInc/Roo-Code) — форк Cline с режимами работы (Code, Architect, Ask, Debug) и возможностью назначить разную модель каждому режиму. Подключается через провайдер «OpenAI Compatible». ## Настройка 1. Установите расширение **Roo Code** из Marketplace. 2. Панель Roo Code → ⚙ → **Providers**. 3. Заполните: | Поле | Значение | |---|---| | **API Provider** | `OpenAI Compatible` | | **Base URL** | `https://api.agentapi.ru/v1/ai` | | **API Key** | `agentapi-ВАШ_КЛЮЧ` | | **Model** | `anthropic/claude-3.5-sonnet` | Base URL — до `/v1/ai`, без `/chat/completions`. Модель вводится вручную полным слагом. ## Разные модели под разные режимы Главное преимущество Roo Code — можно не платить за флагманскую модель там, где хватает дешёвой. Создайте несколько профилей конфигурации (**Providers → +**), в каждом тот же Base URL и ключ, но своя модель, и назначьте профиль режиму: | Режим | Что делает | Разумная модель | |---|---|---| | **Code** | Пишет и правит код | `anthropic/claude-3.5-sonnet` | | **Architect** | Планирует, не трогая файлы | `openai/gpt-4.1` | | **Ask** | Отвечает на вопросы по коду | `deepseek/deepseek-chat` | | **Debug** | Ищет причину ошибки | `anthropic/claude-3.5-sonnet` | ## Индексация кодовой базы Если включаете семантический поиск, укажите там же embedding-модель: | Поле | Значение | |---|---| | **Embedding Provider** | `OpenAI Compatible` | | **Base URL** | `https://api.agentapi.ru/v1/ai` | | **API Key** | `agentapi-ВАШ_КЛЮЧ` | | **Model** | `openai/text-embedding-3-small` | Эндпоинт embeddings не лимитируется по числу запросов, но токены оплачиваются — для больших репозиториев оцените стоимость заранее. ## Что учесть | Особенность | Следствие | |---|---| | Нет списка моделей | Слаг вводится вручную — внешнего `GET /v1/ai/models` нет | | Изображения | Не поддерживаются, см. [Ограничения](https://agentapi.ru/docs/limitations) | | Rate limit | 60 запросов/минуту **по IP**, общий для всех профилей и ключей | ## Диагностика | Симптом | Что проверить | |---|---| | `404` | Пропущен `/ai` в Base URL или неверный хост | | `401` | Ключ не начинается с `agentapi-` | | `400 Negative or zero balance` | Пустой баланс | | `502` | Неверный слаг модели | | `429` | Лимит по IP — подождите минуту | --- URL: https://agentapi.ru/docs/integrations/claude-code # Claude Code и Anthropic SDK AgentAPI отдаёт Anthropic-совместимый эндпоинт [`POST /v1/ai/messages`](https://agentapi.ru/docs/endpoints/messages) с настоящим Anthropic SSE. Но путь содержит сегмент `/ai`, и это создаёт нюанс, который надо понимать до настройки. ## Почему нельзя просто подменить base URL Anthropic SDK и Claude Code дописывают к базовому URL фиксированный путь `/v1/messages`. Нужный адрес — `/v1/**ai**/messages`, где лишний сегмент стоит **посередине**. Подставить его через базовый URL невозможно: ```mermaid flowchart TD A["ANTHROPIC_BASE_URL=
https://api.agentapi.ru"] --> A1["→ /v1/messages"] --> A2["404 ❌"] B["ANTHROPIC_BASE_URL=
https://api.agentapi.ru/ai"] --> B1["→ /ai/v1/messages"] --> B2["404 ❌"] C["Нужно попасть в"] --> C1["/v1/ai/messages ✅"] ``` Поэтому ниже — три рабочих варианта в порядке простоты. ## Вариант 1: прямые HTTP-запросы (работает сразу) Если вы пишете код сами, а не подключаете готовый клиент, — просто вызывайте эндпоинт по полному пути. Никаких обходных путей не нужно. ```bash curl https://api.agentapi.ru/v1/ai/messages \ -H "x-api-key: agentapi-ВАШ_КЛЮЧ" \ -H "Content-Type: application/json" \ -d '{ "model": "anthropic/claude-3.5-sonnet", "max_tokens": 300, "system": "Отвечай кратко.", "messages": [{"role": "user", "content": "Привет!"}] }' ``` ```python import os, requests response = requests.post( "https://api.agentapi.ru/v1/ai/messages", headers={"x-api-key": os.environ["AGENTAPI_KEY"]}, json={ "model": "anthropic/claude-3.5-sonnet", "max_tokens": 300, "messages": [{"role": "user", "content": "Привет!"}], }, timeout=120, ) data = response.json() print(data["content"][0]["text"]) ``` Формат ответа — [Messages](https://agentapi.ru/docs/endpoints/messages). ## Вариант 2: Anthropic SDK с явным путём SDK можно оставить ради типов и обработки ошибок, обойдя сборку пути через низкоуровневый `post`: ```typescript import Anthropic from "@anthropic-ai/sdk"; import type { Message } from "@anthropic-ai/sdk/resources/messages"; const client = new Anthropic({ apiKey: process.env.AGENTAPI_KEY, baseURL: "https://api.agentapi.ru", }); // Путь указывается целиком, поэтому `/v1/messages` не подставляется автоматически. const message = await client.post("/v1/ai/messages", { body: { model: "anthropic/claude-3.5-sonnet", max_tokens: 300, messages: [{ role: "user", content: "Привет!" }], }, }); console.log(message.content); ``` ```python import os from anthropic import Anthropic client = Anthropic( api_key=os.environ["AGENTAPI_KEY"], base_url="https://api.agentapi.ru", ) message = client.post( "/v1/ai/messages", body={ "model": "anthropic/claude-3.5-sonnet", "max_tokens": 300, "messages": [{"role": "user", "content": "Привет!"}], }, cast_to=object, ) print(message) ``` Штатные вызовы `client.messages.create(...)` при этом **не** заработают — они собирают путь сами. Учтите и то, что `post` — низкоуровневый метод: его сигнатура может меняться между версиями SDK. ## Вариант 3: Claude Code через локальный прокси Claude Code настраивается только переменной `ANTHROPIC_BASE_URL` и жёстко дописывает `/v1/messages`, поэтому напрямую подключить его нельзя. Нужен локальный прокси, переписывающий путь. Минимальный вариант на Node.js (без зависимостей): ```javascript // agentapi-proxy.mjs — запуск: node agentapi-proxy.mjs import { createServer } from "node:http"; const UPSTREAM = "https://api.agentapi.ru"; const API_KEY = process.env.AGENTAPI_KEY; if (!API_KEY) throw new Error("Задайте AGENTAPI_KEY"); createServer(async (req, res) => { // /v1/messages -> /v1/ai/messages, остальное проксируем как есть. const path = req.url.startsWith("/v1/messages") ? req.url.replace("/v1/messages", "/v1/ai/messages") : req.url; const chunks = []; for await (const chunk of req) chunks.push(chunk); const upstream = await fetch(`${UPSTREAM}${path}`, { method: req.method, headers: { "content-type": "application/json", "x-api-key": API_KEY, }, body: chunks.length ? Buffer.concat(chunks) : undefined, }); res.writeHead(upstream.status, { "content-type": upstream.headers.get("content-type") ?? "application/json", "cache-control": "no-cache", }); // Ответ может быть SSE, поэтому передаём его потоком, а не целиком. if (upstream.body) { for await (const chunk of upstream.body) res.write(chunk); } res.end(); }).listen(8787, () => console.log("Прокси: http://localhost:8787")); ``` Запуск: ```bash export AGENTAPI_KEY=agentapi-ВАШ_КЛЮЧ node agentapi-proxy.mjs ``` В другом терминале: ```bash export ANTHROPIC_BASE_URL=http://localhost:8787 export ANTHROPIC_AUTH_TOKEN=agentapi-ВАШ_КЛЮЧ export ANTHROPIC_MODEL=anthropic/claude-3.5-sonnet claude ``` Прокси слушает только localhost и подставляет ключ сам — не публикуйте его в сеть. ### Альтернатива на LiteLLM Если прокси уже есть в инфраструктуре, тот же результат даёт [LiteLLM](https://docs.litellm.ai): ```yaml # litellm-config.yaml — запуск: litellm --config litellm-config.yaml model_list: - model_name: claude-3.5-sonnet litellm_params: model: openai/anthropic/claude-3.5-sonnet api_base: https://api.agentapi.ru/v1/ai api_key: os.environ/AGENTAPI_KEY ``` Здесь используется OpenAI-совместимый эндпоинт, который подставляется базовым URL без проблем, а Anthropic-формат для клиента обеспечивает сам LiteLLM. ## Что было бы правильным решением Нюанс с путём — следствие того, что внешний модуль смонтирован как `/v1` + контроллер `ai`. Достаточно добавить алиас `POST /v1/messages` на тот же обработчик, и Claude Code с Anthropic SDK заработают без прокси. Сейчас такого алиаса нет — если он важен для вашего сценария, напишите на [agent@agentapi.ru](mailto:agent@agentapi.ru). ## Диагностика | Симптом | Причина | |---|---| | `404` на `/v1/messages` | Ожидаемо: правильный путь — `/v1/ai/messages` | | `401 Invalid API key format` | В `ANTHROPIC_AUTH_TOKEN` не ключ `agentapi-*` | | Claude Code не видит модель | В `ANTHROPIC_MODEL` нужен полный слаг: `anthropic/claude-3.5-sonnet` | | `400 Negative or zero balance` | Пополните баланс | --- URL: https://agentapi.ru/docs/integrations/sdk # SDK и прямые запросы AgentAPI совместим с OpenAI Chat Completions, поэтому подходит любой клиент, который позволяет задать base URL. Ключевое правило одно. > **Base URL — `https://api.agentapi.ru/v1/ai`.** > Без `/chat/completions` на конце: SDK добавляет путь сам. Если передать полный путь, > запрос уйдёт на `…/v1/ai/chat/completions/chat/completions` и вернёт 404. ## OpenAI SDK (TypeScript) ```bash npm install openai ``` ```typescript import OpenAI from "openai"; const client = new OpenAI({ apiKey: process.env.AGENTAPI_KEY, baseURL: "https://api.agentapi.ru/v1/ai", }); const completion = await client.chat.completions.create({ model: "openai/gpt-4.1", messages: [{ role: "user", content: "Привет!" }], max_tokens: 500, }); console.log(completion.choices[0].message.content); ``` Стриминг: ```typescript const stream = await client.chat.completions.create({ model: "openai/gpt-4.1", messages: [{ role: "user", content: "Расскажи о Байкале" }], stream: true, }); for await (const chunk of stream) { process.stdout.write(chunk.choices[0]?.delta?.content ?? ""); } ``` ## OpenAI SDK (Python) ```bash pip install openai ``` ```python import os from openai import OpenAI client = OpenAI( api_key=os.environ["AGENTAPI_KEY"], base_url="https://api.agentapi.ru/v1/ai", ) completion = client.chat.completions.create( model="openai/gpt-4.1", messages=[{"role": "user", "content": "Привет!"}], max_tokens=500, ) print(completion.choices[0].message.content) print(completion.usage.total_tokens, completion.usage.prompt_tokens) ``` Стриминг: ```python stream = client.chat.completions.create( model="openai/gpt-4.1", messages=[{"role": "user", "content": "Расскажи о Байкале"}], stream=True, ) for chunk in stream: delta = chunk.choices[0].delta.content if delta: print(delta, end="", flush=True) ``` ## Vercel AI SDK ```bash npm install ai @ai-sdk/openai-compatible ``` ```typescript import { createOpenAICompatible } from "@ai-sdk/openai-compatible"; import { streamText } from "ai"; const agentapi = createOpenAICompatible({ name: "agentapi", baseURL: "https://api.agentapi.ru/v1/ai", apiKey: process.env.AGENTAPI_KEY, }); const result = streamText({ model: agentapi("openai/gpt-4.1"), prompt: "Объясни event loop в двух абзацах", }); for await (const chunk of result.textStream) { process.stdout.write(chunk); } ``` ## LangChain ```python from langchain_openai import ChatOpenAI llm = ChatOpenAI( model="openai/gpt-4.1", api_key="agentapi-ВАШ_КЛЮЧ", base_url="https://api.agentapi.ru/v1/ai", ) print(llm.invoke("Привет!").content) ``` Embeddings для векторного поиска: ```python from langchain_openai import OpenAIEmbeddings embeddings = OpenAIEmbeddings( model="openai/text-embedding-3-small", api_key="agentapi-ВАШ_КЛЮЧ", base_url="https://api.agentapi.ru/v1/ai", ) vector = embeddings.embed_query("Байкал") print(len(vector)) ``` ## Go ```bash go get github.com/sashabaranov/go-openai ``` ```go package main import ( "context" "fmt" "os" openai "github.com/sashabaranov/go-openai" ) func main() { config := openai.DefaultConfig(os.Getenv("AGENTAPI_KEY")) config.BaseURL = "https://api.agentapi.ru/v1/ai" client := openai.NewClientWithConfig(config) resp, err := client.CreateChatCompletion( context.Background(), openai.ChatCompletionRequest{ Model: "openai/gpt-4.1", Messages: []openai.ChatCompletionMessage{ {Role: openai.ChatMessageRoleUser, Content: "Привет!"}, }, }, ) if err != nil { fmt.Printf("Ошибка: %v\n", err) return } fmt.Println(resp.Choices[0].Message.Content) } ``` ## Без SDK: fetch ```typescript const response = await fetch( "https://api.agentapi.ru/v1/ai/chat/completions", { method: "POST", headers: { "x-api-key": process.env.AGENTAPI_KEY!, "Content-Type": "application/json", }, body: JSON.stringify({ model: "openai/gpt-4.1", messages: [{ role: "user", content: "Привет!" }], }), }, ); if (!response.ok) { throw new Error(`AgentAPI ${response.status}: ${await response.text()}`); } const data = await response.json(); console.log(data.choices[0].message.content); ``` Ручной разбор SSE: ```typescript const response = await fetch( "https://api.agentapi.ru/v1/ai/chat/completions", { method: "POST", headers: { "x-api-key": process.env.AGENTAPI_KEY!, "Content-Type": "application/json", }, body: JSON.stringify({ model: "openai/gpt-4.1", messages: [{ role: "user", content: "Привет!" }], stream: true, }), }, ); const reader = response.body!.getReader(); const decoder = new TextDecoder(); let buffer = ""; while (true) { const { done, value } = await reader.read(); if (done) break; buffer += decoder.decode(value, { stream: true }); const lines = buffer.split("\n"); // Последняя строка может быть неполной — оставляем её в буфере. buffer = lines.pop() ?? ""; for (const line of lines) { if (!line.startsWith("data: ")) continue; const payload = line.slice(6); if (payload === "[DONE]") continue; const chunk = JSON.parse(payload); // Ошибки приходят внутри потока при статусе 200. if (chunk.error) throw new Error(chunk.error.message); process.stdout.write(chunk.choices[0]?.delta?.content ?? ""); } } ``` ## Что стоит помнить | | | |---|---| | Слаг модели | С префиксом провайдера: `openai/gpt-4.1`, не `gpt-4.1` | | Заголовок | `apiKey` в SDK уходит как `Authorization: Bearer` — этого достаточно | | Расход | Токены — в `usage` ответа, рублёвые списания — в [транзакциях](https://agentapi.ru/docs/billing) | | Ошибки | Не в OpenAI-формате `{error: {type, code}}` — см. [Ошибки](https://agentapi.ru/docs/errors) | | Изображения | Не поддерживаются, см. [Ограничения](https://agentapi.ru/docs/limitations) | --- URL: https://agentapi.ru/docs/errors # Ошибки и лимиты ## Формат ошибок Большинство ошибок приходят в стандартном формате: ```json { "statusCode": 401, "message": "Invalid or inactive API key", "error": "Unauthorized" } ``` Ошибки валидации содержат массив в `message`: ```json { "statusCode": 400, "message": [ "temperature must not be greater than 2", "messages should not be empty" ], "error": "Bad Request" } ``` > Формат отличается от OpenAI: ответ **не** обёрнут в объект `error` с полями > `type` и `code`. Библиотеки, ожидающие OpenAI-формат ошибок, покажут сообщение, > но не смогут разобрать его тип. ## Коды ответов ### 400 — Bad Request | Сообщение | Причина | |---|---| | `Negative or zero balance. Available: 0.00 RUB. Please top up your account.` | Баланс исчерпан. Пополните счёт в [профиле](https://agentapi.ru/profile) | | массив сообщений валидации | Параметр вне допустимого диапазона или отсутствует обязательное поле | | `content must be a string` | Передан массив блоков в `content` — мультимодальный ввод не поддерживается | | `property X should not exist` | Неизвестное поле в запросе к `/v1/ai/embeddings` (там строгая валидация) | Баланс проверяется **до** отправки запроса провайдеру. Он может стать отрицательным после списания за уже выполненный запрос — блокируется только следующий. ### 401 — Unauthorized | Сообщение | Причина | |---|---| | `API key is required in x-api-key or Authorization header` | Заголовок не передан | | `Invalid API key format` | Ключ не начинается с `agentapi-` | | `Invalid or inactive API key` | Ключ не найден или отключён (`active = false`) | | `API key not found` | Ключ не связан с пользователем | ### 403 — Forbidden `Insufficient balance to create an API key` — при попытке создать ключ с нулевым балансом. ### 404 — Not Found Чаще всего означает **неверный URL**, а не отсутствующий ресурс: | Что запрошено | Проблема | |---|---| | `https://agentapi.ru/v1/...` | Основной домен отдаёт сайт. Нужен `api.agentapi.ru` | | `https://api.agentapi.ru/v1/chat/completions` | Пропущен сегмент `/ai` | | `https://api.agentapi.ru/v1/messages` | Правильный путь — `/v1/ai/messages` | ### 429 — Too Many Requests ```json { "statusCode": 429, "message": "ThrottlerException: Too Many Requests" } ``` ### 502 — Bad Gateway Ошибка на стороне провайдера. Формат **отличается** от остальных — без поля `statusCode`: ```json { "message": "Provider returned error: model not found" } ``` Типичные причины: неверный слаг модели, модель временно недоступна, запрос отклонён провайдером. Для устойчивости используйте [fallback-роутинг](https://agentapi.ru/docs/models) через `models[]`. ### Ошибки внутри стрима Если генерация оборвалась после начала стриминга, HTTP-статус уже равен 200 — заголовки отправлены до первого токена. Ошибка приходит кадром: ``` data: {"error":{"message":"..."}} ``` Для формата Anthropic — именованным событием: ``` event: error data: {"type":"error","error":{"type":"api_error","message":"..."}} ``` Поэтому проверяйте поле `error` в каждом кадре, а не только код ответа. > Сейчас в теле такого кадра сообщение может сериализоваться как пустой объект > (`{"error":{"message":{}}}`) — см. [Ограничения](https://agentapi.ru/docs/limitations). ## Rate limit | | | |---|---| | Лимит | 60 запросов за 60 секунд | | Ключ подсчёта | **IP-адрес**, не API-ключ | | Исключение | `POST /v1/ai/embeddings` — не лимитируется | Важные следствия: - Лимит считается по IP, поэтому несколько приложений с одного сервера (или из-за одного NAT) расходуют **общий** лимит, даже с разными ключами. - Разные ключи одного аккаунта не дают независимых лимитов. - Стриминговый запрос — это один запрос независимо от длительности. Ограничения на количество токенов в минуту нет: фактический потолок — баланс аккаунта и лимиты самого провайдера. ## Рекомендации по обработке | Код | Стратегия | |---|---| | 400 (баланс) | Не повторять. Уведомить о пополнении | | 400 (валидация) | Не повторять. Исправить запрос | | 401 | Не повторять. Проверить ключ | | 429 | Повтор с экспоненциальной задержкой | | 502 | Повтор 1–2 раза; при повторе — сменить модель через `models[]` | Пример повторов только для восстановимых ошибок: ```typescript async function withRetry(fn: () => Promise, attempts = 3): Promise { for (let i = 0; i < attempts; i++) { try { return await fn(); } catch (error) { const status = (error as { status?: number }).status; // Повторяем только то, что может пройти со второй попытки. if (status !== 429 && status !== 502) throw error; if (i === attempts - 1) throw error; await new Promise((r) => setTimeout(r, 2 ** i * 1000)); } } throw new Error("unreachable"); } ``` --- URL: https://agentapi.ru/docs/billing # Биллинг Модель оплаты — предоплаченный баланс в рублях. Списание происходит по факту использованных токенов, без подписок и минимальных платежей. ## Как считается стоимость Оплачивается фактическое использование: и входные, и выходные токены. Стоимость зависит от выбранной модели — тарифы указаны в каталоге [Моделей](https://agentapi.ru/models). Списание происходит в рублях после выполнения запроса. Точную сумму по каждому запросу видно в [транзакциях](#транзакции). ## Сколько израсходовал запрос Количество токенов приходит в поле `usage` ответа: ```json { "usage": { "prompt_tokens": 24, "completion_tokens": 71, "total_tokens": 95 } } ``` При стриминге `usage` приходит в последнем кадре перед `data: [DONE]`. Рублёвую сумму списания смотрите в транзакциях — она появляется там после запроса. ## Списание при стриминге Стриминг не ждёт расчёта: токены отдаются клиенту сразу, а списание происходит по завершении генерации. Если клиент оборвал соединение до конца ответа, запрос может остаться несписанным. ## Баланс ``` GET https://api.agentapi.ru/billing/balance ``` Требует JWT (не API-ключ), см. [Аутентификация](https://agentapi.ru/docs/authentication). ```bash curl https://api.agentapi.ru/billing/balance \ -H "Authorization: Bearer $JWT" ``` ```json { "balance": 1500.5 } ``` Баланс проверяется перед каждым запросом: при `balance <= 0` приходит `400 Negative or zero balance`. Баланс может уйти в минус после списания за уже выполненный запрос — блокируется только следующий. ## Транзакции ``` GET https://api.agentapi.ru/billing/transactions?limit=50&offset=0 ``` ```json { "transactions": [ { "id": "8c3f1a95-2d47-4e18-b6a0-9f5e2c7d3b81", "type": "debit", "amount": "0.035000", "currency": "RUB", "description": "Chat completion: openai/gpt-4.1", "promptTokens": 24, "completionTokens": 71, "totalTokens": 95, "model": "openai/gpt-4.1", "createdAt": "2026-07-27T09:15:42.108Z" } ], "total": 428 } ``` Тип `debit` — списание за использование, `credit` — пополнение. Поле `amount` — сумма в рублях, `model` — модель, за которую списано. ## Статистика ``` GET https://api.agentapi.ru/billing/stats?startDate=2026-07-01&endDate=2026-07-27 ``` ```json { "totalSpent": 214.87, "totalRequests": 1043, "averageCost": 0.206 } ``` Расход по дням: ``` GET https://api.agentapi.ru/stats/usage?period=30d ``` `period` — `7d`, `30d` или `90d`. ```json { "summary": { "totalTokens": 1842905, "totalCost": 214.87, "currency": "RUB", "period": "30d" }, "daily": [ { "date": "2026-07-26", "tokens": 84120, "cost": 9.74, "requests": 47 }, { "date": "2026-07-27", "tokens": 12508, "cost": 1.43, "requests": 9 } ] } ``` За всё время: ``` GET https://api.agentapi.ru/stats/lifetime ``` ```json { "totalTokens": 14820355, "totalCost": 1734.02 } ``` Статистика агрегируется **по аккаунту**. Разбивки по отдельным ключам нет — если нужно разделять расходы по проектам, используйте поле `metadata` или `session_id` в запросах и считайте на своей стороне. ## Пополнение Через интерфейс [профиля](https://agentapi.ru/profile) (YooKassa). Лимиты — от 100 ₽ до 100 000 ₽ за платёж. Пополнение необходимо и для **создания** ключа: при нулевом балансе создание вернёт `403 Insufficient balance to create an API key`. ## Как сократить расходы - **Выбирайте модель под задачу.** Разница в цене между флагманскими и компактными моделями — порядок и больше. Цены за токен видны в каталоге [Моделей](https://agentapi.ru/models). - **Ограничивайте `max_tokens`.** Оплачивается и ввод, и вывод. - **Следите за длиной контекста.** В многоходовом диалоге вся история пересылается заново на каждом шаге — обрезайте старые сообщения. - **Прогоните репрезентативные запросы** и посмотрите транзакции и статистику, прежде чем выводить фичу в продакшн. --- URL: https://agentapi.ru/docs/limitations # Известные ограничения Список того, что сейчас работает не так, как можно ожидать от OpenAI-совместимого API. Написан честно, чтобы вы не отлаживали чужие баги как свои. ## Мультимодальный ввод не поддерживается Поле `content` в сообщении принимает **только строку**. Массив блоков, которым OpenAI передаёт изображения, отклоняется валидацией: ```json { "messages": [{ "role": "user", "content": [ {"type": "text", "text": "Что на картинке?"}, {"type": "image_url", "image_url": {"url": "data:image/png;base64,..."}} ] }] } ``` ```json { "statusCode": 400, "message": ["content must be a string"], "error": "Bad Request" } ``` Следствие: vision-возможности недоступны даже у моделей, которые их поддерживают, а плагины с прикреплением скриншотов (Cline, Roo Code, Continue) не смогут отправить изображение. **Обходного пути на стороне API нет.** Описывайте изображение текстом либо распознавайте его отдельным сервисом. ## `/v1/ai/responses` не умеет стриминг Параметр `stream` принимается без ошибки, но **игнорируется** — ответ всегда приходит целиком. Клиент, ожидающий поток, будет ждать полной генерации. Для стриминга используйте [Chat Completions](https://agentapi.ru/docs/endpoints/chat-completions) или [Messages](https://agentapi.ru/docs/endpoints/messages). ## `stop_sequences` в `/v1/ai/messages` не применяется Поле парсится и проходит валидацию, но до провайдера не доходит — генерация не остановится на указанной последовательности. Обход: используйте `stop` в [Chat Completions](https://agentapi.ru/docs/endpoints/chat-completions), где параметр работает, либо обрезайте ответ на своей стороне. ## Путь Anthropic-эндпоинта нестандартный Эндпоинт находится по адресу `/v1/ai/messages`, а не `/v1/messages`. Клиенты, жёстко дописывающие `/v1/messages` к базовому URL (Claude Code, `client.messages.create()` в Anthropic SDK), напрямую не подключаются. Рабочие варианты описаны в [Claude Code и Anthropic SDK](https://agentapi.ru/docs/integrations/claude-code). ## Нет списка моделей во внешнем API Эндпоинта `GET /v1/ai/models` не существует. Плагины и клиенты, подтягивающие модели автоматически, покажут пустой список — слаг вводится вручную. Список моделей доступен через `GET /models` (без префикса `/v1`, ключ не требуется), но этот путь не соответствует ожиданиям OpenAI-клиентов. См. [Модели](https://agentapi.ru/docs/models). ## Ошибка внутри стрима приходит пустой Если генерация оборвалась после начала стриминга, кадр с ошибкой может не содержать текста сообщения: ``` data: {"error":{"message":{}}} ``` Причина — сериализация объекта ошибки. HTTP-статус при этом уже 200, поскольку заголовки отправлены до первого токена. Практический вывод: проверяйте **наличие** поля `error` в кадрах и не рассчитывайте на информативный текст. Причину смотрите по коду ответа при повторе того же запроса без `stream`. ## Формат ошибок отличается от OpenAI Ответ не обёрнут в объект `error` с полями `type` и `code`: ```json { "statusCode": 401, "message": "Invalid or inactive API key", "error": "Unauthorized" } ``` Ошибки провайдера (502) приходят в третьем формате — вообще без `statusCode`: ```json { "message": "Provider returned error: model not found" } ``` Библиотеки, разбирающие OpenAI-формат ошибок, покажут текст, но не определят тип. См. [Ошибки и лимиты](https://agentapi.ru/docs/errors). ## Rate limit считается по IP 60 запросов в минуту привязаны к IP-адресу, **не** к API-ключу. Следствия: - Несколько сервисов за одним NAT или на одном сервере делят общий лимит. - Создание дополнительных ключей не увеличивает пропускную способность. - Ограничение нельзя поднять на уровне аккаунта. Исключение — `POST /v1/ai/embeddings`, он не лимитируется. ## Статистика только по аккаунту Расходы агрегируются по пользователю; разбивки по отдельным ключам нет. Чтобы разделять затраты по проектам, передавайте `session_id` или `metadata` в запросах и считайте на своей стороне. ## Rerank не поддерживается Эндпоинта переранжирования нет. В Continue и Roo Code не назначайте роль `rerank`. --- Если какое-то из ограничений блокирует ваш сценарий — напишите на [agent@agentapi.ru](mailto:agent@agentapi.ru).