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

FieldValueWhy
Name (Optional)zyraxon
Custom Modelopenai/zyraxon-codexCopy 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 URLhttps://zyraxonai.lovable.app/api/public/zyraxon/v1Copy this exactly, including /v1 at the end.
API KeyzyraxonAny non-empty value, unless the operator set ZYRAXON_PROVIDER_KEY.
ℹ
Name is optional; the model id is not
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

  1. 01Open OpenHands and go to Settings, then the LLM (model / provider) section.
  2. 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.
  3. 03Choose Custom Model.
  4. 04For Custom Model, copy openai/zyraxon-codex exactly. The openai/ prefix is what LiteLLM reads to pick a handler; without it OpenHands fails before it calls us, with LLM Provider NOT provided.
  5. 05For Base URL, copy https://zyraxonai.lovable.app/api/public/zyraxon/v1 exactly. If this box is missing, Advanced is not on yet.
  6. 06For API Key, use any non-empty value — zyraxon here.
  7. 07Press Save Changes, then start a conversation.

The form, as text

text
Name (Optional)   zyraxon
Custom Model      openai/zyraxon-codex
Base URL          https://zyraxonai.lovable.app/api/public/zyraxon/v1
API Key           zyraxon
⚠
Copy the Custom Model exactly, `openai/` included
OpenHands routes the model through LiteLLM, which reads the text before the first / 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.

text
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.

bash
# 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.

⚠
Turn Advanced on before you fill anything in
The Base URL box appears only once Advanced is on. If your screen shows a "Provider connection: None" dropdown instead of a Base URL field, Advanced is off.
text
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

SymptomCauseFix
401 Incorrect API key providedThis 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 providedOpenHands 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 modelThe 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_gateThe upstream free tier refused this network.Call from another network, or ask the operator to set OPENCODE_ZEN_API_KEY.
503 overloadedAt capacity; the request was shed rather than queued.Honour Retry-After and retry with backoff.
★
Tell the two 401s apart
OpenAI's 401 says "Incorrect API key provided" and names 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.
✓
The model id is tolerant on purpose
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.
★
The same fields work in any agent
OpenHands is one host. Any agent with a *custom provider* or *OpenAI-compatible* option takes the same four values, so this page is the template for the whole class.