Connecting OpenHands
OpenHands takes a custom provider through a small form. The four values to enter, and how to check them before you save.
OpenHands is an agent, so it needs a provider it can drive with tools and streaming. ZYRAXON serves both, which makes it a drop-in custom provider: four fields in a form, no code.
The four fields
| Field | Value | Why |
|---|---|---|
| Name (Optional) | zyraxon | |
| Custom Model | openai/zyraxon-codex | Copy this exactly, openai/ included. OpenHands routes the model through LiteLLM, which refuses an id with no provider prefix — that is the "LLM Provider NOT provided" error. |
| Base URL | https://zyraxonai.lovable.app/api/public/zyraxon/v1 | Copy this exactly, including /v1 at the end. |
| API Key | zyraxon | Any non-empty value, unless the operator set ZYRAXON_PROVIDER_KEY. |
Name is only a label for the provider entry. Custom Model must be an id the endpoint serves — zyraxon-codex is a safe default, and https://zyraxonai.lovable.app/api/public/zyraxon/v1/models lists all ten.Steps
- 01Open OpenHands and go to Settings, then the LLM (model / provider) section.
- 02Turn Advanced on at the top of the page. This matters: the Base URL field only takes effect in Advanced mode. In the simple form OpenHands ignores it and sends the request to OpenAI instead — which is what produces
401 Incorrect API key provided: zyraxon. - 03Choose Custom Model.
- 04For Custom Model, copy
openai/zyraxon-codexexactly. Theopenai/prefix is what LiteLLM reads to pick a handler; without it OpenHands fails before it calls us, withLLM Provider NOT provided. - 05For Base URL, copy
https://zyraxonai.lovable.app/api/public/zyraxon/v1exactly. If this box is missing, Advanced is not on yet. - 06For API Key, use any non-empty value —
zyraxonhere. - 07Press Save Changes, then start a conversation.
The form, as text
Name (Optional) zyraxon Custom Model openai/zyraxon-codex Base URL https://zyraxonai.lovable.app/api/public/zyraxon/v1 API Key zyraxon
/ to choose a handler. A bare id fails with LLM Provider NOT provided before it ever calls us, so the value to enter is openai/zyraxon-codex.The "LLM Provider NOT provided" error
This is the most common failure, and it happens entirely on the OpenHands side — our endpoint is never reached, so nothing here can fix it. The model string needs a provider prefix.
If OpenHands reports: litellm.BadRequestError: LLM Provider NOT provided. You passed model=zyraxon-codex the Custom Model field is missing its provider prefix. OpenHands routes the model through LiteLLM, which reads the text before the first "/" to choose a handler and refuses a bare id — it never reaches us. Add the prefix: Custom Model: openai/zyraxon-codex The endpoint accepts both spellings, so this works with no other change: zyraxon-codex openai/zyraxon-codex zyraxon/zyraxon-codex zyraxon/codex If your version reads the model from the environment instead of the form: export LLM_MODEL="openai/zyraxon-codex" export LLM_BASE_URL="https://zyraxonai.lovable.app/api/public/zyraxon/v1" export LLM_API_KEY="zyraxon"
Verify before you save
Both calls below are cheap and prove different things: the first that the base URL serves a model list, the second that a turn actually completes.
# The model list is what the form needs to resolve the model id.
curl -s https://zyraxonai.lovable.app/api/public/zyraxon/v1/models | jq -r '.data[].id'
# A one-shot turn proves the URL and key are right. Both spellings work here.
curl -s https://zyraxonai.lovable.app/api/public/zyraxon/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer zyraxon" \
-d '{"model":"openai/zyraxon-codex","messages":[{"role":"user","content":"ping"}]}' \
| jq -r '.choices[0].message.content'Turn Advanced on — the Base URL only works there
OpenHands has two settings screens. The simple one has a Provider connection dropdown and no Base URL box; the Advanced toggle at the top reveals one. If you fill the simple form, OpenHands ignores your Base URL and sends the turn to OpenAI itself.
OpenHands has two modes, and the Base URL only works in one of them.
Simple form: there is a "Provider connection" dropdown, no Base URL box
-> OpenHands sends the turn to OpenAI itself
-> "401 Incorrect API key provided: zyraxon"
Advanced: a Base URL box appears
-> OpenHands sends the turn to whatever that box says
Turn "Advanced" on at the top of the LLM settings page before you fill
anything in. The Base URL box appears once it is on.When a turn fails
| Symptom | Cause | Fix |
|---|---|---|
401 Incorrect API key provided | This message is OpenAI's, so the request never reached us — OpenHands used its default URL because Advanced mode was off and your Base URL was ignored. | Turn Advanced on, then set Base URL to the value above. |
LLM Provider NOT provided | OpenHands routed the model through LiteLLM, which needs a provider/model string. | Put openai/ in front of the model: openai/zyraxon-codex. Or set LLM_MODEL="openai/zyraxon-codex" for the OpenHands process. |
Unknown model | The model id is not in the list the base URL serves. | Use an id from https://zyraxonai.lovable.app/api/public/zyraxon/v1/models. |
401 authentication_error (type authentication_error) | This one is ours: the deployment requires a provider key and yours is wrong or missing. | Send the key the operator gave you as the API Key field. |
503 upstream_gate | The upstream free tier refused this network. | Call from another network, or ask the operator to set OPENCODE_ZEN_API_KEY. |
503 overloaded | At capacity; the request was shed rather than queued. | Honour Retry-After and retry with backoff. |
platform.openai.com — that means the request went to OpenAI, not to us. Ours carries type: "authentication_error" in the JSON body. Only the second is about your key.zyraxon-codex, openai/zyraxon-codex, zyraxon/zyraxon-codex and zyraxon/codex all resolve to the same model, so you do not have to know which spelling your version of OpenHands wants.