opencode
opencode can use any provider that speaks the OpenAI Chat Completions shape. MUSCLE Flex by Adhibita serves it at /v1/chat/completions. opencode keeps running its tools on your machine; Flex routes the model requests.
Before you start
You need:
- an accepted MUSCLE Flex invitation and a funded service balance;
- a Flex API key, created on the API keys page of the portal;
- the Flex base URL from your invitation. This page writes it as
<FLEX_BASE_URL>: the scheme and host only, without a trailing/v1.
The key check below reads both values from your shell:
bash
export FLEX_BASE_URL="<FLEX_BASE_URL>"
export MUSCLE_FLEX_API_KEY="<FLEX_API_KEY>"Configure muscle/auto as the model id; auto is accepted as a short form of it. Flex chooses the route for each request, so the model field does not select a model. The model names that compatible clients send on their own are routed the same way. See The model id.
Check that opencode is installed with opencode --version.
Configure
Add a provider to opencode.json in the project root, or to ~/.config/opencode/opencode.json for every project. Merge it with any providers you already have:
json
{
"$schema": "https://opencode.ai/config.json",
"provider": {
"muscle-flex": {
"npm": "@ai-sdk/openai-compatible",
"name": "MUSCLE Flex",
"options": {
"baseURL": "<FLEX_BASE_URL>/v1",
"apiKey": "{env:MUSCLE_FLEX_API_KEY}"
},
"models": {
"auto": {
"id": "muscle/auto",
"name": "Flex auto"
}
}
}
},
"model": "muscle-flex/auto"
}baseURLends in/v1. The provider package appends/chat/completions.{env:MUSCLE_FLEX_API_KEY}reads the key from your shell, so the file holds no secret.muscle-flex/autois opencode's name for the model: provider id, then model key. The request itself carriesmuscle/auto.
Context size
opencode uses the model's context size to decide when to compact a long session. To give it one, read the advertised context_length for muscle/auto:
bash
curl -s "$FLEX_BASE_URL/v1/models" \
-H "Authorization: Bearer $MUSCLE_FLEX_API_KEY"Then add "limit": { "context": <CONTEXT_LENGTH>, "output": <MAX_OUTPUT> } to the auto model entry, with the reported value and the output budget you want per turn.
Verify
1. Check the key
This read-only call confirms the base URL and the key before you change the agent:
bash
curl -i "$FLEX_BASE_URL/v1/account" \
-H "Authorization: Bearer $MUSCLE_FLEX_API_KEY"A 200 response returns your account summary, including available credits. A 401 means the key is missing, mistyped or revoked.
Every Flex response carries an X-Request-Id header. Keep it when you contact support: it is how a single request is found.
2. Run one tool call
From a small project:
bash
opencode run --model muscle-flex/auto "List the files in this folder, then read the README and summarize it in one sentence."opencode should read the files and print a one-sentence summary.
Troubleshooting
- The provider or model is missing. Check that the JSON parses and that the
modelvalue matches the provider id and model key. Restart opencode after editing the file. 401. The key variable is not set in the shell that launched opencode.404. Check thatbaseURLdoes not double the path (…/v1/v1). It is<FLEX_BASE_URL>with a single/v1added.
Responses you may see
| Status | Meaning | What to do |
|---|---|---|
401 | The key is missing, mistyped or revoked. | Check where the agent reads the key from. Create a new key in the portal if needed. |
402 | Your balance or spend cap does not cover the request. | Add credits, then retry. |
403 | The account is suspended, or the request is not allowed. | Contact support with the X-Request-Id. |
404 model_not_found | The agent sent a model id that Flex does not accept. | Set the agent's model to muscle/auto. Retrying unchanged fails again. |
429 | A rate limit was reached. | Wait for the number of seconds in Retry-After (a few seconds when it is absent), then retry. |
400 unsupported_field | The agent sent a field or tool that Flex does not offer yet. | Find the field in the compatibility matrix and turn that option off. |
400 unsupported_content | The conversation carries an image or audio part, which Flex does not support yet. | Start a new conversation without the image, and turn off the agent's image input. |
502, 503 or 504 | No eligible route could serve the request at that moment, or it timed out. | Retry later. If it persists, contact support with the X-Request-Id. |
503 feature_unavailable | No route offers what the request needs, or the conversation is too long for every route. | Start a new conversation or lower the agent's output limit. Retrying unchanged fails again. |
The API reference describes each error code and what to do about it.
Agents rarely show response headers. When a request fails inside an agent, note the time, the agent version and the error text for support.