Thêm một provider tương thích OpenAI tùy chỉnh vào OpenCode.

Updated 2026-07-29

OpenCode đọc provider tùy chỉnh thẳng từ opencode.json. Khai báo một khối provider với package @ai-sdk/openai-compatible, trỏ options.baseURL vào https://api.apisrouter.com/v1, và mọi model bạn liệt kê đều chọn được trong picker /models dưới một key.

Câu trả lời nhanh: một khối provider trong opencode.json.

OpenCode hỗ trợ provider tương thích OpenAI tùy chỉnh ngay từ đầu. Thêm một entry provider vào opencode.json với npm đặt là "@ai-sdk/openai-compatible", đặt options.baseURL thành https://api.apisrouter.com/v1, đọc key từ một biến môi trường bằng template {env:...}, và liệt kê các model id bạn muốn dưới models. Sau đó đặt field model cấp cao nhất thành "apisrouter/<model-id>" và OpenCode định tuyến toàn bộ vòng lặp agent qua gateway. Đây là đường provider tùy chỉnh có tài liệu trong docs của OpenCode, không phải một wrapper hay fork. File cấu hình nằm ở gốc project của bạn (opencode.json) hoặc toàn cục tại ~/.config/opencode/opencode.json, và hai file được merge với nhau, nên khối provider có thể khai báo một lần và tái dùng qua mọi repo.

{
  "$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"
}

Cách OpenCode phân giải provider và model.

OpenCode (anomalyco trên GitHub, một trong những agent lập trình terminal được star nhiều nhất với khoảng 186K star) xây lớp provider của nó trên Vercel AI SDK. Field npm trong một khối provider đặt tên package SDK nào OpenCode nạp để nói chuyện với provider đó: "@ai-sdk/openai-compatible" nói giao thức /v1/chat/completions chuẩn, trong khi "@ai-sdk/openai" nói giao thức /v1/responses của OpenAI. Một gateway đa vendor phục vụ chat completions, nên openai-compatible là package đúng; chọn "@ai-sdk/openai" đối với một endpoint chat-completions là cách phổ biến nhất khiến cài đặt này hỏng. Model được định vị theo cặp provider/model. Provider id là bất kỳ key nào bạn chọn trong khối provider ("apisrouter" ở trên), và model id là key bên trong map models, nên model mặc định trở thành "apisrouter/claude-sonnet-4-6". Mọi thứ bạn khai báo xuất hiện trong picker /models bên trong TUI, chuyển đổi được giữa phiên. Một hành vi đáng ghi nhớ: với provider tùy chỉnh, map models là một allowlist. Provider tích hợp sẵn đi kèm một catalog đã biết, nhưng OpenCode không thể tự liệt kê model của một endpoint tùy chỉnh, nên chỉ những id bạn khai báo tường minh mới gọi được. Khi endpoint phía sau baseURL phục vụ id Claude, GPT, DeepSeek, và Kimi cạnh nhau, khai báo mỗi entry cho mỗi model biến picker thành một bảng chuyển mạch đa vendor đằng sau một key duy nhất.

Cài đặt đầy đủ: cấu hình toàn cục, cấu hình project, giới hạn theo từng model.

Bố cục gọn gàng là khai báo provider một lần trong cấu hình toàn cục tại ~/.config/opencode/opencode.json và chỉ giữ các lựa chọn theo từng repo (model nào, agent nào) trong opencode.json của mỗi project. OpenCode merge các file cấu hình thay vì thay thế chúng, nên file project vẫn nhỏ gọn và khối provider không bao giờ bị lặp lại. Template {env:APISROUTER_API_KEY} phân giải lúc nạp từ môi trường, giữ key ngoài mọi file có thể bị commit. Export nó từ shell profile của bạn để mọi phiên terminal khởi chạy OpenCode đều thấy nó. Mỗi entry model cũng chấp nhận một object limit với trần token context và output. Khai báo chúng quan trọng hơn vẻ ngoài: OpenCode dùng con số context để quyết định khi nào một phiên cần được tóm tắt, nên một model context dài khai báo mà không có limit sẽ bị đối xử thận trọng hơn mức cần thiết. Đặt limit.context theo đúng những gì model thực sự hỗ trợ và các phiên dài sẽ được nén muộn hơn thay vì sớm hơn.

{
  "$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"
}

Chọn model và small_model.

Workflow thực tế là giữ slot main ở model bạn tin tưởng cho việc chỉnh sửa và xoay các ứng viên qua các phiên thực thay vì benchmark: một buổi chiều diff thực trên chính codebase của bạn cho biết nhiều hơn một bảng xếp hạng. Định tuyến qua một endpoint biến mỗi ứng viên thành một thay đổi một dòng, và góc nhìn sử dụng theo từng key hiển thị mỗi thử nghiệm thực sự tốn bao nhiêu.

  • model dẫn dắt vòng lặp agent chính: đọc file, lên kế hoạch chỉnh sửa, viết diff, chạy tool. Slot này thấy context dài nhất và làm công việc kỹ thuật thực sự, nên một model lập trình flagship (claude-sonnet-4-6, claude-opus-4-7, gpt-5.5) thuộc về đây.
  • small_model xử lý các tác vụ nhẹ như tạo tiêu đề phiên. Nó chạy thường xuyên nhưng không bao giờ gánh việc code, nên một id nhanh, giá rẻ là hình dạng đúng; không có lý do gì để đốt token flagship cho tiêu đề.
  • Các id tinh chỉnh cho code như gpt-5.6-sol và kimi-k2.7-code đáng khai báo ngay cả khi không phải mặc định của bạn: chuyển sang chúng cho một phiên nặng refactor chỉ là một lựa chọn trong /models, không phải một chỉnh sửa cấu hình.
  • Vì cả hai slot đều nhận chuỗi provider/model cùng một khối provider, slot main và small có thể đến từ các vendor khác nhau trong cùng một phiên, điều mà không key đơn vendor nào cho phép.

Trả theo mức sử dụng · thấp hơn giá chính thức

Selected models are priced below official list prices. Exact input, output, cache, and per-request prices are shown for each model.

Mô hìnhGiá chính thứcGiá của chúng tôi
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

Các kiểu lỗi đặc thù của provider tùy chỉnh trong OpenCode.

Sai package SDK. "@ai-sdk/openai" gửi POST tới /v1/responses; một gateway chat-completions trả lời route đó bằng một lỗi. Nếu request đầu tiên của bạn thất bại với một lỗi dạng giao thức hoặc route thay vì lỗi xác thực, kiểm tra field npm có đúng chính xác là "@ai-sdk/openai-compatible" không. Model vắng mặt trong picker. Model provider tùy chỉnh chỉ tồn tại nếu được khai báo; một lỗi gõ trong key models, hoặc một id bạn tưởng đã thêm nhưng chưa thêm, đơn giản là không xuất hiện trong /models. Id là các chuỗi chính xác bao gồm hậu tố phiên bản, và danh sách /v1/models của gateway là nguồn chân lý để sao chép. {env:...} không phân giải được. Template phân giải từ môi trường của tiến trình đã khởi chạy OpenCode. Một key export trong một terminal không tới được một instance OpenCode khởi chạy từ terminal khác hoặc từ một launcher desktop chưa bao giờ source profile của bạn. Đặt export trong shell profile, không phải một phiên tạm thời. Bất ngờ từ merge cấu hình. Vì cấu hình toàn cục và project được merge, một opencode.json project đặt model về một provider khác sẽ âm thầm ghi đè default toàn cục của bạn, và một khối provider còn sót lại từ một project cũ có thể che khuất kỳ vọng. Khi định tuyến trông sai, đọc cả hai file trước khi nghi ngờ gateway hành xử sai. baseURL không có /v1. SDK gắn thêm các đường dẫn route như /chat/completions vào bất cứ base nào bạn cung cấp, nên https://api.apisrouter.com/v1 là đúng và host trần thì không. Một thất bại dạng kết nối hoặc 404 trên một cấu hình vốn đúng gần như luôn là do điều này.

Ai định tuyến OpenCode qua một gateway.

  • Lập trình viên sống trong TUI cả ngày và muốn Claude, GPT, và Kimi trong một picker /models thay vì duy trì credential provider riêng cho mỗi vendor.
  • Kỹ sư so sánh model lập trình trên công việc thực. Mỗi ứng viên là một entry đã khai báo và một lựa chọn trong picker; so sánh từng phiên không cần tài khoản mới.
  • Đội chuẩn hóa một secret duy nhất. Một APISROUTER_API_KEY trong tài liệu onboarding thay thế một danh sách key theo từng vendor, và mức dùng theo từng key hiển thị ai chi tiêu gì.
  • Người dùng ghép một model main flagship với một small_model giá rẻ từ một vendor khác, điều mà cấu hình đơn vendor không thể biểu đạt.
  • Lập trình viên không có quyền truy cập billing của một vendor cụ thể. Truy cập dựa trên nạp tiền không yêu cầu thẻ loại bỏ phụ thuộc đăng ký theo từng provider.

Xác minh endpoint và debug phiên đầu tiên.

Trước khi bắt đầu một phiên, liệt kê những gì gateway phục vụ. Các id trả về bởi /v1/models chính xác là các chuỗi mà map models của bạn phải khớp. Các thất bại phiên đầu tiên nhất quán. Lỗi 401 nghĩa là APISROUTER_API_KEY không hiển thị với tiến trình OpenCode; echo biến đó trong cùng terminal bạn khởi chạy. Một lỗi model-not-found từ gateway nghĩa là key đã khai báo không khớp một id được phục vụ, bao gồm hậu tố phiên bản. Nếu provider không xuất hiện chút nào, hãy kiểm tra JSON, vì một dấu phẩy thừa hay dấu ngoặc đặt sai chỗ làm cả file không đọc được và OpenCode rơi về default. Một khi request chạy trôi chảy, console APIsRouter hiển thị model theo từng request, số lượng token, và chi tiêu. Agent lập trình là khối lượng công việc context dài, nhiều lượt, và thấy phiên nào và model nào tiêu tốn token là cách bạn quyết định slot main có xứng đáng với giá của nó hay không.

curl -s https://api.apisrouter.com/v1/models \
  -H "Authorization: Bearer $APISROUTER_API_KEY" | head -50

Câu hỏi thường gặp

OpenCode có thể dùng model Claude, GPT, và Kimi qua một provider tùy chỉnh không?

Có. Một provider tùy chỉnh chỉ là một baseURL cộng một allowlist model. Khi endpoint phục vụ nhiều vendor, khai báo một entry cho mỗi id và mọi model đã khai báo xuất hiện trong picker /models dưới cùng provider và key, chuyển đổi được giữa phiên.

API key nằm ở đâu trong opencode.json?

Trong options.apiKey dùng template môi trường, ví dụ "{env:APISROUTER_API_KEY}". Template phân giải lúc nạp nên key thực không bao giờ nằm trong file cấu hình. Export biến đó từ shell profile của bạn để mọi terminal khởi chạy OpenCode kế thừa nó.

Khối provider nên nằm trong cấu hình toàn cục hay cấu hình project?

Toàn cục, tại ~/.config/opencode/opencode.json. OpenCode merge các file cấu hình, nên khai báo provider một lần ở toàn cục và chỉ đặt lựa chọn model theo từng project giữ repo sạch khỏi việc lắp ráp credential và tránh các khối provider trùng lặp trôi dạt khỏi nhau.

Vì sao model của tôi không xuất hiện trong picker /models?

Model provider tùy chỉnh phải được khai báo tường minh; OpenCode không thể tự liệt kê một endpoint tùy chỉnh. Kiểm tra map models có chứa đúng chuỗi id, bao gồm hậu tố phiên bản, và sao chép id từ response /v1/models của gateway thay vì gõ theo trí nhớ.

Khác biệt giữa @ai-sdk/openai-compatible và @ai-sdk/openai ở đây là gì?

@ai-sdk/openai-compatible nói /v1/chat/completions, giao thức mà các gateway đa vendor phục vụ. @ai-sdk/openai nói giao thức /v1/responses của OpenAI. Với APIsRouter, dùng @ai-sdk/openai-compatible; package kia sẽ gửi POST tới một route gateway không phục vụ cho mục đích này.

Giới hạn context đã khai báo có thực sự quan trọng không?

Có. OpenCode dùng limit.context để quyết định khi nào một phiên cần nén. Không khai báo limit trên một model context dài nghĩa là phiên bị tóm tắt sớm hơn cần thiết, nên hãy đặt limit.context và limit.output theo đúng những gì model thực sự hỗ trợ.