Manage AI provider API keys and models. Auto-discover models, track quota exhaustion across agents, and auto-switch on failure. Use when: adding API key, checking model availability, viewing exhausted models, syncing configs, or when a model returns 403/billing/quota errors. Triggers on: "add API key", "new account key", "model used up", "switch model", "check models", "reset models", "quota exhausted", "billing error", "403 error", "insufficient balance", "模型额度", "key用完了", "换模型", "添加key", "额度用完", "余额不足".
Install
npx skillscat add jeouly3-bot/openclaw-provider-manager Install via the SkillsCat registry.
Provider Manager — Agent Decision Tree
This document is your operating manual. Follow the decision trees below to manage API keys, models, and quota for your user. All commands use {baseDir} to refer to the directory where this skill is installed.
Communication principle: When you need to ask the user a question or report a result, use whatever communication channel is available to you (chat UI, messaging app, webhook, etc.). This skill does not prescribe any specific channel — you decide based on your own capabilities.
1. Installation
How to install this skill
# Clone into your skills directory
git clone https://github.com/jeouly3-bot/openclaw-provider-manager.git {skillsDir}/openclaw-provider-manager
# Install dependencies
cd {skillsDir}/openclaw-provider-manager && npm installVerify installation
node {baseDir}/scripts/registry.js --helpIf this prints the help text, installation is successful.
2. First Run — Auto-Configuration
When this skill is loaded for the first time, follow this sequence:
START
│
├─ Run: node {baseDir}/scripts/health-check.js
│
├─ IF exit code = 0 AND status = "healthy"
│ └─ Registry exists and has available models. Ready to use.
│
├─ IF exit code = 0 AND status = "no-registry"
│ ├─ No registry found. First-time setup needed.
│ ├─ ASK USER: "I need an API key to get started. Which provider are you using?"
│ ├─ Offer choices: bailian, deepseek, zhipu, kimi, openai, siliconflow, custom
│ ├─ ASK USER: "Please provide your API key for {provider}."
│ ├─ Run: node {baseDir}/scripts/registry.js add-key \
│ │ --provider {provider} --key {user_key} --label "{agent_name}"
│ ├─ IF success:
│ │ └─ Tell user: "Added key and discovered N models. Ready to use."
│ └─ IF failure:
│ └─ Tell user the error message. Ask them to verify the key.
│
├─ IF exit code = 0 AND status = "warning"
│ ├─ Some models are exhausted but others remain.
│ ├─ Tell user: "{summary}" (from health-check output)
│ └─ ASK USER: "Would you like to add a new key or reset exhausted models with a new account?"
│
└─ IF exit code = 0 AND status = "critical"
├─ ALL text models exhausted. Cannot make API calls.
├─ Tell user: "All text models are exhausted. I need a new API key to continue."
├─ ASK USER: "Please provide a new API key. Is this from a new account (fresh quota)?"
├─ IF new account:
│ ├─ Run: node {baseDir}/scripts/registry.js reset --provider {provider}
│ └─ Run: node {baseDir}/scripts/registry.js add-key \
│ --provider {provider} --key {new_key} --label "{agent_name}"
└─ IF same account, different key:
└─ Run: node {baseDir}/scripts/registry.js add-key \
--provider {provider} --key {new_key} --label "{agent_name}"3. When a Model Returns 403 / Billing Error / Quota Exhausted
When you receive ANY of these errors from an API call:
- HTTP 403
- "billing error"
- "insufficient balance"
- "insufficient quota"
- "quota exhausted"
- "rate limit" (persistent, not transient)
- "API key has run out of credits"
Follow this sequence:
ERROR DETECTED: {provider}/{model} returned {error}
│
├─ Step 1: Mark the model as exhausted
│ Run: node {baseDir}/scripts/registry.js mark-exhausted \
│ --provider {provider} --model {model} --by {your_agent_name}
│
├─ Step 2: Get the next available model
│ Run: node {baseDir}/scripts/registry.js next-model \
│ --provider {provider} --type text
│ ├─ IF success (returns JSON with model field):
│ │ ├─ Parse the output JSON: { "model": "new-model-id", "type": "text" }
│ │ ├─ Step 3: Sync configuration
│ │ │ Run: node {baseDir}/scripts/sync-config.js \
│ │ │ --format gateway --config {config_path} \
│ │ │ --provider {provider}
│ │ └─ Step 4: Retry the original API call with the new model.
│ │ Tell user: "Model {old_model} exhausted. Switched to {new_model}."
│ │
│ └─ IF failure (no available models):
│ ├─ ALL models for this provider are exhausted.
│ ├─ Tell user: "All models for {provider} are exhausted. I need a new API key."
│ ├─ ASK USER: "Please provide a new key. Is this a new account?"
│ ├─ IF new account:
│ │ ├─ Run: node {baseDir}/scripts/registry.js reset --provider {provider}
│ │ └─ Run: node {baseDir}/scripts/registry.js add-key \
│ │ --provider {provider} --key {new_key} --label "{agent_name}"
│ └─ IF same account:
│ └─ Run: node {baseDir}/scripts/registry.js add-key \
│ --provider {provider} --key {new_key} --label "{agent_name}"
│
└─ After adding new key, retry the original API call.Important notes on exhaustion
- Exhausted models are permanently marked until a
resetis performed. resetshould ONLY be used when the user provides keys from a new account with fresh quota.- Adding a new key from the same account does NOT reset exhaustion — the models remain exhausted because the quota is shared across keys on the same account.
4. Health Check (Proactive Monitoring)
Run the health check periodically or when you suspect quota issues:
node {baseDir}/scripts/health-check.js [--registry <path>]The output is JSON:
{
"status": "healthy|warning|critical|no-registry",
"summary": "human-readable summary",
"total_models": 190,
"available": 118,
"exhausted": 72,
"by_type": {
"text": { "total": 95, "available": 55, "exhausted": 40 }
},
"recently_exhausted": [
{ "model": "qwen3.5-plus", "exhausted_at": "...", "by": "小艺" }
],
"action_required": "description of what needs to happen, or null"
}Status thresholds
| Status | Condition | Action |
|---|---|---|
healthy |
< 25% text models exhausted | No action needed |
warning |
25% – 99% text models exhausted | Inform user, suggest adding a new key |
critical |
100% text models exhausted | Must get new key before any API calls |
no-registry |
Registry file not found | Run first-time setup (Section 2) |
Decision tree for health check results
HEALTH CHECK RESULT
│
├─ healthy → No action. Continue normally.
│
├─ warning → Tell user: "{summary}. Consider adding a new API key."
│
├─ critical → Tell user: "All text models exhausted. Provide a new key to continue."
│ Follow the key-addition flow in Section 3.
│
└─ no-registry → Follow first-run setup in Section 2.5. Adding a New API Key (User-Initiated)
When a user says they want to add a key (unprompted by an error):
USER WANTS TO ADD A KEY
│
├─ ASK USER: "Which provider? (bailian / deepseek / zhipu / kimi / openai / siliconflow / custom)"
├─ ASK USER: "Please provide the API key."
├─ IF custom: ASK USER: "What is the base URL? (e.g., https://your-api.com/v1)"
│
├─ Run: node {baseDir}/scripts/registry.js add-key \
│ --provider {provider} --key {key} --label "{agent_name}" \
│ [--base-url {url}]
│
├─ IF success:
│ └─ Tell user: "Key added. Discovered N models."
└─ IF failure:
└─ Tell user the error. Common issues:
- Key already registered
- Network error reaching provider API
- Invalid key format6. Checking Status (User-Initiated)
When a user asks about model availability or status:
# Full status
node {baseDir}/scripts/registry.js status
# Status for one provider
node {baseDir}/scripts/registry.js status --provider bailian
# Health summary (JSON)
node {baseDir}/scripts/health-check.jsPresent the results in a readable format to the user.
7. Resetting Exhausted Models
Only reset when the user confirms they have a new account with fresh quota:
node {baseDir}/scripts/registry.js reset --provider {provider}Never reset automatically. Always confirm with the user first.
8. Supported Providers
| ID | Name | Base URL |
|---|---|---|
bailian |
阿里云百炼 (DashScope) | https://dashscope.aliyuncs.com/compatible-mode/v1 |
deepseek |
DeepSeek | https://api.deepseek.com/v1 |
zhipu |
智谱AI (Zhipu) | https://open.bigmodel.cn/api/paas/v4 |
kimi |
Kimi / 月之暗面 | https://api.moonshot.cn/v1 |
openai |
OpenAI | https://api.openai.com/v1 |
siliconflow |
SiliconFlow | https://api.siliconflow.cn/v1 |
custom |
Custom | User-specified --base-url |
All providers use the OpenAI-compatible API standard (GET /v1/models).
9. Multi-Agent Shared Registry
Multiple agents can share one registry file. Set the path via:
- Environment variable:
PROVIDER_REGISTRY_PATH=/shared/.provider-registry.json - CLI flag:
--registry /shared/.provider-registry.json
When one agent marks a model exhausted, all other agents see it on their next read. File-locking ensures safe concurrent writes.
10. Blacklist Management
Some models have no free quota. Manage the blacklist:
# Add to blacklist
node {baseDir}/scripts/registry.js blacklist-add --model "model-name"
# Remove from blacklist
node {baseDir}/scripts/registry.js blacklist-remove --model "model-name"Blacklisted models are excluded from discovery and will never be selected by next-model.