| name | opencode-litellm-maas |
| description | Configure OpenCode with LiteLLM proxy for Huawei Cloud MaaS models with latency-based routing and fallbacks. Covers venv setup, config generation, opencode integration, and startup script. |
| license | MIT |
| compatibility | opencode |
| metadata | {"audience":"infrastructure-engineers","workflow":"opencode-litellm-maas"} |
OpenCode + LiteLLM Proxy for Huawei Cloud MaaS
Set up OpenCode to use LiteLLM proxy as a unified gateway to Huawei Cloud ModelArts MaaS models. The proxy provides latency-based routing across model groups with automatic fallbacks, so OpenCode always gets a working model without hardcoding a single endpoint.
Rules
- ALWAYS use a Python 3.12 venv — Python 3.14+ breaks
orjson which litellm[proxy] depends on. Use uv to manage the venv if the system Python is too new.
- NEVER hardcode
MAAS_API_KEY in config.yaml — use os.environ/MAAS_API_KEY so the key stays in env vars only.
- NEVER expose
MAAS_API_KEY in logs — LiteLLM logs may contain request details. Keep the key out of shell history by sourcing env scripts instead of passing it inline.
- ALWAYS kill existing LiteLLM on port 4000 before starting — stale processes cause "address already in use" errors.
- Use
setsid + disown to daemonize LiteLLM — nohup alone may die when the parent shell exits. setsid creates a new session group so the proxy survives.
- Health check via
/v1/models with auth header — the /health endpoint returns 500 on some LiteLLM versions even when the proxy is fully functional. /v1/models with Authorization: Bearer <master_key> is the reliable check.
- Preserve existing
opencode.json MCP config — only replace the provider section. Never overwrite MCP server definitions (terraform, playwright, hcloud, etc.).
Prerequisites
| Requirement | Details |
|---|
| Python 3.12+ | 3.14+ is NOT supported (orjson build fails). Install via uv if needed. |
uv (recommended) or pip | For venv + package management. uv handles Python version downloads automatically. |
MAAS_API_KEY | Huawei Cloud ModelArts API key (same account as your Huawei Cloud console). |
opencode | Installed globally (npm install -g opencode or equivalent). |
lsof | For port checking in the startup script. Usually pre-installed on Linux. |
curl | For health checks. Pre-installed on most systems. |
Minimum resources: 512 MB RAM, 200 MB disk (for venv + litellm packages).
Available MaaS Models (July 2026)
| Model | Context | Max Output | Deep Thinking | Cost Tier |
|---|
| DeepSeek-V3.1-Terminus | 128K | 32K | Configurable | $ |
| DeepSeek-V3 | 128K | 64K | No | $ |
| DeepSeek-V3.2 | 160K | 32K | Configurable | $$ |
| DeepSeek-V4-Flash | 1M | 128K | Configurable | $$$ |
| GLM-5.2 | 198K | 128K | Configurable | $$$ |
| GLM-5.1 | 198K | 128K | Configurable | $$$$ |
| GLM-5 | 198K | 64K | Configurable | $$$$ |
| DeepSeek-V4-Pro | 1M | 128K | Configurable | $$$$$ |
| DeepSeek-R1 | 128K | 32K | Always active | $$$$$ |
All MaaS models tolerate reasoning_content in history, so they are mutually compatible in fallback chains (unlike Groq/Cerebras which break on thinking tokens).
Routing Groups
| Group | Fallback Chain | Use Case | Alias |
|---|
economy | V3.1-Terminus → V3 → V3.2 | Simple tasks, minimize cost | cheap |
fast | V3.1-Terminus → V3.2 → GLM-5.2 | Quick edits, simple questions | — |
coding | V4-Flash → GLM-5.2 → V3.2 | General coding (default) | default |
coding-heavy | V4-Pro → GLM-5.2 → V4-Flash | Complex refactors, architecture | heavy |
reasoning | R1 → GLM-5.1 → V4-Pro | Deep reasoning | — |
Cross-group fallbacks:
economy → fast → coding
fast → coding
coding → fast
coding-heavy → coding → fast
reasoning → coding-heavy
Workflow
Step 1: CHECK PREREQUISITES
Verify Python, uv/pip, and opencode are available:
python3 --version
which opencode
which uv || which pip3
If system Python is 3.14+, install uv to manage a 3.12 venv:
curl -LsSf https://astral.sh/uv/install.sh | sh
Step 2: CREATE VENV & INSTALL LITELLM
~/.local/bin/uv venv ~/litellm-env --python 3.12
~/.local/bin/uv pip install 'litellm[proxy]' --python ~/litellm-env/bin/python
python3.12 -m venv ~/litellm-env
source ~/litellm-env/bin/activate
pip install 'litellm[proxy]'
Verify:
source ~/litellm-env/bin/activate
python -c "import litellm; print('litellm OK')"
which litellm
Step 3: CREATE CONFIG DIRECTORY & FILES
mkdir -p ~/litellm
3a. ~/litellm/config.yaml
Create the LiteLLM proxy config with all MaaS models organized by routing group:
model_list:
- model_name: economy
litellm_params:
model: custom_openai/deepseek-v3.1-terminus
api_base: https://api-ap-southeast-1.modelarts-maas.com/openai/v1
api_key: os.environ/MAAS_API_KEY
- model_name: economy
litellm_params:
[, ]
[]
[]
[, ]
[]
3b. ~/litellm/init_litellm_env.sh
Exports the MaaS API key. Replace the placeholder with your actual key.
#!/bin/bash
export MAAS_API_KEY="<YOUR_MAAS_API_KEY>"
chmod +x ~/litellm/init_litellm_env.sh
3c. ~/litellm/init_opencode_env.sh
Sets environment variables so OpenCode talks to the local LiteLLM proxy instead of any direct provider:
#!/bin/bash
source ~/litellm/init_litellm_env.sh
export LITELLM_MASTER_KEY="sk-123456"
export OPENAI_API_KEY="$LITELLM_MASTER_KEY"
export OPENAI_BASE_URL="http://127.0.0.1:4000"
export API_TIMEOUT_MS=600000
unset ANTHROPIC_API_KEY ANTHROPIC_BASE_URL ANTHROPIC_AUTH_TOKEN 2>/dev/null || true
chmod +x ~/litellm/init_opencode_env.sh
Step 4: CONFIGURE OPENCODE
Edit ~/.opencode/opencode.json. Preserve the existing mcp section — only replace the provider section.
Replace any existing provider (e.g. huawei-maas) with the litellm provider:
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"...": "keep existing MCP servers unchanged"
},
"provider": {
"litellm": {
"npm": "@ai-sdk/openai-compatible",
"name": "LiteLLM Proxy (MaaS)",
"options": {
"baseURL": "http://127.0.0.1:4000",
"apiKey": "sk-123456"
},
"models": {
"economy": {
"name": "Economy (V3.1-Terminus → V3 → V3.2) — min cost",
"limit": { "context": 160000,
Step 5: CREATE STARTUP SCRIPT
Create ~/start_opencode.sh — a simple script that kills any stale proxy, starts LiteLLM, waits for it to be ready, then launches OpenCode:
#!/bin/bash
set -euo pipefail
LITELLM_DIR="$HOME/litellm"
LITELLM_ENV="$HOME/litellm-env"
LITELLM_PORT=4000
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
info() { echo -e "${GREEN}[INFO]${NC} $*"; }
warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
error() { echo -e "${RED}[ERROR]${NC} $*"; exit 1; }
PID=$(lsof -ti :$LITELLM_PORT 2>/dev/null || true)
if [[ -n "$PID" ]]; then
warn "Killing LiteLLM on port $LITELLM_PORT (PID: $PID)..."
kill -9 $PID 2>/dev/null || true
sleep 1
PID2=$(lsof -ti :$LITELLM_PORT 2>/dev/null || true)
[[ -n "$PID2" ]] && error "Cannot free port $LITELLM_PORT"
info "Port freed"
else
info "Port free"
info
setsid litellm --config --port \
> 2>&1 &
info
info
i $( 1 30);
curl -sf -H >/dev/null 2>&1;
info
1
! curl -sf -H >/dev/null 2>&1;
error
info
opencode
chmod +x ~/start_opencode.sh
Step 6: VERIFY
Start the proxy manually and confirm it works:
source ~/litellm-env/bin/activate
source ~/litellm/init_litellm_env.sh
setsid litellm --config ~/litellm/config.yaml --port 4000 > ~/litellm/proxy.log 2>&1 &
disown
curl -s -H "Authorization: Bearer sk-123456" http://127.0.0.1:4000/v1/models | python3 -m json.tool | head -20
Expected output: a JSON list with 17 model IDs including economy, fast, coding, coding-heavy, reasoning, and all individual model names.
Generated Files
~/litellm/
config.yaml # LiteLLM proxy config (MaaS-only, routing + fallbacks)
init_litellm_env.sh # Exports MAAS_API_KEY
init_opencode_env.sh # Sets OPENAI_API_KEY/BASE_URL to local proxy
proxy.log # LiteLLM proxy log (created at runtime)
~/litellm-env/ # Python 3.12 venv with litellm[proxy]
~/start_opencode.sh # One-command startup: kill stale → start proxy → launch opencode
~/.opencode/
opencode.json # OpenCode config (litellm provider + MCP servers)
Daily Usage
~/start_opencode.sh
source ~/litellm/init_opencode_env.sh
opencode
Troubleshooting
| Problem | Solution |
|---|
orjson build fails | System Python is 3.14+. Use uv venv --python 3.12 to get a compatible venv. |
| Proxy dies when shell closes | Use setsid + disown instead of nohup alone. |
/health returns 500 | This is a known LiteLLM quirk. Use /v1/models with auth header for health checks. |
| "address already in use" | Kill stale process: kill $(lsof -ti :4000) |
| Model not found in cost map | Harmless warning — LiteLLM defaults cost to 0 for custom models. |
MAAS_API_KEY not set | Source init_litellm_env.sh before starting the proxy. |
| OpenCode uses wrong provider | Ensure opencode.json has litellm as the only provider, and env vars point to localhost:4000. |
tail -f ~/litellm/proxy.log
curl -s -H "Authorization: Bearer sk-123456" http://127.0.0.1:4000/v1/models
curl -s -H "Authorization: Bearer sk-123456" http://127.0.0.1:4000/v1/models | python3 -m json.tool
kill $(lsof -ti :4000)
~/start_opencode.sh