Додайте кастомного OpenAI-сумісного провайдера в OpenCode.
Updated 2026-07-29
OpenCode зчитує кастомних провайдерів напряму з opencode.json. Оголосіть блок provider з пакетом @ai-sdk/openai-compatible, спрямуйте options.baseURL на https://api.apisrouter.com/v1, і кожна модель, яку ви перелічите, стає доступною для вибору в пікері /models під одним ключем.
Коротка відповідь: один блок provider в opencode.json.
OpenCode нативно підтримує кастомних OpenAI-сумісних провайдерів. Додайте запис provider у opencode.json з npm, встановленим на "@ai-sdk/openai-compatible", встановіть options.baseURL на https://api.apisrouter.com/v1, зчитуйте ключ зі змінної середовища через шаблон {env:...} і перелічіть потрібні ID моделей під models. Тоді встановіть поле model верхнього рівня на "apisrouter/<model-id>", і OpenCode маршрутизує весь цикл агента через шлюз. Це задокументований шлях кастомного провайдера в документації OpenCode, а не обгортка чи форк. Файл конфігурації живе або в корені вашого проєкту (opencode.json), або глобально в ~/.config/opencode/opencode.json, і обидва об'єднуються, тож блок provider можна оголосити один раз і повторно використовувати в кожному репозиторії.
{
"$schema": "https://opencode.ai/config.json",
"provider": {
"apisrouter": {
"npm": "@ai-sdk/openai-compatible",
"name": "APIsRouter",
"options": {
"baseURL": "https://api.apisrouter.com/v1",
"apiKey": "{env:APISROUTER_API_KEY}"
},
"models": {
"claude-sonnet-4-6": { "name": "Claude Sonnet 4.6" }
}
}
},
"model": "apisrouter/claude-sonnet-4-6"
}Як OpenCode визначає провайдерів і моделі.
OpenCode (anomalyco на GitHub, один з найбільш «зіркових» термінальних агентів для кодування — приблизно 186 тис. зірок) будує свій шар провайдерів на Vercel AI SDK. Поле npm у блоці provider називає, який пакет SDK завантажує OpenCode для спілкування з цим провайдером: "@ai-sdk/openai-compatible" говорить стандартним протоколом /v1/chat/completions, тоді як "@ai-sdk/openai" говорить протоколом /v1/responses від OpenAI. Мультипостачальницький шлюз обслуговує chat completions, тож openai-compatible — правильний пакет; вибір "@ai-sdk/openai" проти ендпоінта chat-completions — найпоширеніший спосіб, яким це налаштування ламається. Моделі адресуються як пари provider/model. ID провайдера — це той ключ, який ви обрали в блоці provider ("apisrouter" вище), а ID моделі — це ключ всередині карти models, тож типова модель стає "apisrouter/claude-sonnet-4-6". Усе, що ви оголосили, з'являється в пікері /models всередині TUI, з можливістю перемикання посеред сесії. Одна поведінка, яку варто засвоїти: для кастомних провайдерів карта models — це allowlist. Вбудовані провайдери постачаються з відомим каталогом, але OpenCode не може самостійно перерахувати моделі кастомного ендпоінта, тож адресовані лише ті ID, які ви явно оголосили. Коли ендпоінт за baseURL обслуговує ID Claude, GPT, DeepSeek і Kimi поряд, оголошення по одному запису на модель перетворює пікер на мультипостачальницьку комутаційну панель за одним ключем.
Повне налаштування: глобальна конфігурація, конфігурація проєкту, ліміти для кожної моделі.
Чистий підхід — оголосити провайдера один раз у глобальній конфігурації в ~/.config/opencode/opencode.json і тримати лише вибори для кожного репозиторію (яка модель, які агенти) у opencode.json кожного проєкту. OpenCode об'єднує файли конфігурації, а не замінює їх, тож файл проєкту лишається крихітним, а блок provider ніколи не дублюється. Шаблон {env:APISROUTER_API_KEY} розв'язується під час завантаження зі середовища, що тримає ключ поза будь-яким файлом, який може потрапити в коміт. Експортуйте його з профілю вашого shell, щоб кожна сесія термінала, яка запускає OpenCode, могла його бачити. Кожен запис моделі також приймає об'єкт limit зі стелями токенів для контексту і виводу. Їхнє оголошення важливіше, ніж здається: OpenCode використовує число контексту, щоб вирішити, коли сесії потрібне резюмування, тож модель з довгим контекстом, оголошена без лімітів, обробляється консервативніше, ніж мала б. Встановіть limit.context на те, що модель насправді підтримує, і довгі сесії стискатимуться пізніше, а не раніше.
{
"$schema": "https://opencode.ai/config.json",
"provider": {
"apisrouter": {
"npm": "@ai-sdk/openai-compatible",
"name": "APIsRouter",
"options": {
"baseURL": "https://api.apisrouter.com/v1",
"apiKey": "{env:APISROUTER_API_KEY}"
},
"models": {
"claude-opus-4-7": { "name": "Claude Opus 4.7", "limit": { "context": 200000, "output": 32000 } },
"claude-sonnet-4-6": { "name": "Claude Sonnet 4.6", "limit": { "context": 200000, "output": 64000 } },
"gpt-5.5": { "name": "GPT-5.5" },
"gpt-5.6-sol": { "name": "GPT-5.6 Sol" },
"kimi-k2.7-code": { "name": "Kimi K2.7 Code" }
}
}
},
"model": "apisrouter/claude-sonnet-4-6",
"small_model": "apisrouter/kimi-k2.7-code"
}Вибір model і small_model.
Практичний робочий процес — тримати основний слот на моделі, якій ви довіряєте для редагувань, і ротувати кандидатів через реальні сесії, а не бенчмарки: пообіддя реальних diff-ів проти вашої власної кодової бази скаже вам більше, ніж будь-який рейтинг. Маршрутизація через один ендпоінт робить кожного кандидата зміною в один рядок, а погляд на використання за ключем показує, скільки насправді коштував кожен експеримент.
- model керує основним циклом агента: читання файлів, планування редагувань, написання diff-ів, запуск інструментів. Цей слот бачить найдовші контексти і виконує реальну інженерну роботу, тож саме тут місце передовій моделі для кодування (claude-sonnet-4-6, claude-opus-4-7, gpt-5.5).
- small_model обробляє легкі завдання на кшталт генерації назв сесій. Спрацьовує часто, але ніколи не несе роботу з кодування, тож правильна форма — швидкий, недорогий ID; немає причин палити передові токени на назви.
- Налаштовані під код ID на кшталт gpt-5.6-sol і kimi-k2.7-code варто оголошувати, навіть якщо вони не типові для вас: перемикання на них для сесії, насиченої рефакторингом, — це один вибір у /models, а не редагування конфігурації.
- Оскільки обидва слоти приймають рядки provider/model проти того самого блоку provider, основний і малий слоти можуть надходити від різних постачальників в одній сесії — те, що не дозволяє жоден ключ одного постачальника.
Оплата за фактом · нижче офіційних цін
Selected models are priced below official list prices. Exact input, output, cache, and per-request prices are shown for each model.
| Модель | Офіційна ціна | Наша ціна |
|---|---|---|
| Claude Sonnet 4.6 | $3.00 / $15.00 per M | $2.40 / $12.00 per M |
| Claude Opus 4.7 | $5.00 / $25.00 per M | $4.00 / $20.00 per M |
| GPT-5.5 | $5.00 / $30.00 per M | $4.00 / $24.00 per M |
| GPT-5.6 Sol | $5.00 / $30.00 per M | $4.00 / $24.00 per M |
| Kimi K2.7 Code | $0.95 / $4.00 per M | $1.00 / $4.00 per M |
Специфічні для кастомних провайдерів OpenCode режими збоїв.
Неправильний пакет SDK. "@ai-sdk/openai" надсилає POST на /v1/responses; шлюз chat-completions відповідає на цей маршрут помилкою. Якщо перший запит провалюється з помилкою у формі протоколу чи маршруту, а не помилкою автентифікації, перевірте, чи поле npm говорить точно "@ai-sdk/openai-compatible". Модель відсутня в пікері. Моделі кастомного провайдера існують лише якщо оголошені; помилка в написанні ключа models чи ID, який ви припустили, але так і не додали, просто не з'являється в /models. ID — це точні рядки, включно з суфіксами версій, а список /v1/models шлюзу — джерело істини, з якого варто копіювати. Нерозв'язаний {env:...}. Шаблон розв'язується із середовища процесу, який запустив OpenCode. Ключ, експортований в одному терміналі, не досягає інстанції OpenCode, запущеної з іншого термінала чи з десктопного лаунчера, який ніколи не завантажував ваш профіль. Розмістіть export у профілі shell, а не в одноразовій сесії. Несподіванки об'єднання конфігурацій. Оскільки глобальна конфігурація і конфігурація проєкту об'єднуються, opencode.json проєкту, що встановлює model на іншого провайдера, тихо перевизначає ваш глобальний типовий варіант, а забутий блок provider у старому проєкті може перекрити очікування. Коли маршрутизація виглядає неправильно, прочитайте обидва файли, перш ніж припускати, що шлюз поводиться неправильно. baseURL без /v1. SDK дописує шляхи маршрутів на кшталт /chat/completions до будь-якого base, який ви задаєте, тож https://api.apisrouter.com/v1 правильний, а голий хост — ні. Збій з'єднання чи у формі 404 в іншому правильній конфігурації майже завжди саме через це.
Хто маршрутизує OpenCode через шлюз.
- Розробники, які цілий день живуть у TUI і хочуть мати Claude, GPT і Kimi в одному пікері /models, замість того щоб підтримувати окремі облікові дані провайдера для кожного постачальника.
- Інженери, що порівнюють моделі для кодування на реальній роботі. Кожен кандидат — це один оголошений запис і один вибір у пікері; порівняння сесія за сесією не потребує нових акаунтів.
- Команди, що стандартизують один секрет. Єдиний APISROUTER_API_KEY в документації онбордингу замінює чек-лист ключів для кожного постачальника, а використання за ключем показує, хто скільки витрачає.
- Користувачі, що поєднують передову основну модель з недорогою small_model від іншого постачальника — те, що не можуть виразити конфігурації одного постачальника.
- Розробники без доступу до білінгу певного постачальника. Доступ на основі поповнення без вимоги картки прибирає залежність від реєстрації в кожного провайдера.
Перевірте ендпоінт і налагодьте першу сесію.
Перед початком сесії перегляньте, що обслуговує шлюз. ID, повернуті /v1/models, — це точно ті рядки, яким мають відповідати ключі вашої карти models. Збої першої сесії послідовні. 401 означає, що APISROUTER_API_KEY не був видимий процесу OpenCode; виконайте echo для змінної в тому самому терміналі, з якого запускаєте. Помилка «модель не знайдено» від шлюзу означає, що оголошений ключ не збігається з обслуговуваним ID, включно з суфіксами версій. Якщо провайдер взагалі не з'являється, перевірте JSON, оскільки зайва кома чи неправильно розміщена дужка робить весь файл нечитабельним, і OpenCode повертається до значень за замовчуванням. Щойно запити почнуть проходити, консоль APIsRouter показує модель на кожен запит, кількість токенів і витрати. Агенти для кодування — це навантаження з довгим контекстом і багатьма ходами, і бачення того, які сесії та моделі споживають токени, — це спосіб вирішити, чи виправдовує основний слот свою ціну.
curl -s https://api.apisrouter.com/v1/models \
-H "Authorization: Bearer $APISROUTER_API_KEY" | head -50Поширені запитання
Чи може OpenCode використовувати моделі Claude, GPT і Kimi через одного кастомного провайдера?
Так. Кастомний провайдер — це просто baseURL плюс allowlist моделей. Коли ендпоінт обслуговує кількох постачальників, оголосіть один запис на ID, і кожна оголошена модель з'являється в пікері /models під тим самим провайдером і ключем, з можливістю перемикання посеред сесії.
Куди йде API-ключ в opencode.json?
В options.apiKey за допомогою шаблону середовища, наприклад "{env:APISROUTER_API_KEY}". Шаблон розв'язується під час завантаження, тож буквальний ключ ніколи не сидить у файлі конфігурації. Експортуйте змінну з профілю вашого shell, щоб кожен термінал, який запускає OpenCode, її успадковував.
Чи має блок provider жити в глобальній конфігурації чи конфігурації проєкту?
У глобальній, в ~/.config/opencode/opencode.json. OpenCode об'єднує файли конфігурації, тож оголошення провайдера один раз глобально і встановлення лише вибору моделі для кожного проєкту тримає репозиторії вільними від «сантехніки» облікових даних і уникає розбіжностей між дубльованими блоками.
Чому моя модель не з'являється в пікері /models?
Моделі кастомного провайдера мають бути оголошені явно; OpenCode не може перерахувати кастомний ендпоінт. Перевірте, чи карта models містить точний рядок ID, включно з суфіксами версій, і копіюйте ID з відповіді /v1/models шлюзу, а не вводьте їх з пам'яті.
У чому різниця між @ai-sdk/openai-compatible і @ai-sdk/openai тут?
@ai-sdk/openai-compatible говорить /v1/chat/completions — протоколом, який обслуговують мультипостачальницькі шлюзи. @ai-sdk/openai говорить протоколом /v1/responses від OpenAI. Для APIsRouter використовуйте @ai-sdk/openai-compatible; інший пакет надсилатиме POST на маршрут, який шлюз не обслуговує для цієї мети.
Чи справді мають значення оголошені ліміти контексту?
Так. OpenCode використовує limit.context, щоб вирішити, коли сесії потрібне стиснення. Залишення лімітів неоголошеними для моделі з довгим контекстом означає, що сесії резюмуються раніше, ніж потрібно, тож встановлюйте limit.context і limit.output на те, що модель справді підтримує.