# Connect the OpenHands agent to Router One through its OpenAI-compatible provider

> Markdown mirror of https://router.one/integrations/openhands for AI assistants and crawlers. Router One is an OpenAI-compatible LLM API gateway.
> Last updated: 2026-09-07

OpenHands is an open-source software-development agent with a terminal UI, a headless mode for CI, and a Docker-based GUI server. It runs its own tool loop and pays for every step through whichever LLM you configure. Its model layer is LiteLLM, so an OpenAI-compatible gateway is a documented target: enter an openai/-prefixed model ID and the Router One base URL once, and each agent step, including the memory condenser's summaries, becomes a traced request on one key. This guide covers the OpenHands CLI Settings screen, the LLM_* environment variables for headless and container runs, and which endpoint each model family actually reaches.

## Install the CLI and open the LLM settings in Advanced mode

Install the CLI with uv tool install openhands --python 3.12 (Python 3.12 or newer is required) or the official install script. The first run opens the LLM settings; later, press Ctrl+P and choose Settings. Switch Settings Mode from Basic to Advanced: Basic mode only offers a provider and model picker with no Base URL field, so it always calls the vendor directly. Advanced mode requires both Custom Model and Base URL, and it saves the Custom Model string exactly as typed, without adding a provider prefix. Enter openai/ followed by the exact catalog ID, the /v1 base URL, and a dedicated Router One key:

`openhands-settings`

```text
# OpenHands CLI → Ctrl+P → Settings → Settings Mode: Advanced
Custom Model:  openai/<exact-model-id-from-/models>
Base URL:      https://api.router.one/v1
API Key:       sk-your-router-one-key
# Saved to ~/.openhands/agent_settings.json as llm.model / llm.base_url / llm.api_key
```

## Configure OpenHands to use the Router One base URL

For headless runs, CI jobs, or a container with no saved settings, export the three LLM_* variables and start OpenHands with --override-with-envs. Without that flag the CLI prints a warning and ignores them; with it, the values override ~/.openhands/agent_settings.json for that run only and are never written to disk. When no settings file exists yet, LLM_API_KEY and LLM_MODEL are mandatory, and LLM_BASE_URL is what sends the run to Router One instead of the vendor default. Both the agent and the memory condenser use the overridden model:

`openhands-headless.sh`

```bash
# Headless / CI / container run: the values apply only with --override-with-envs
export LLM_BASE_URL=https://api.router.one/v1
export LLM_API_KEY=sk-your-router-one-key
export LLM_MODEL=openai/<exact-model-id-from-/models>

openhands --override-with-envs --headless -t "List the test commands in this repo"
```

## Which endpoint each model ID reaches

LiteLLM reads the leading openai/ as an instruction: call this base URL with the OpenAI protocol. It strips that first segment and sends the remainder as the model field, so the safe form is openai/ plus the full catalog ID, which already carries its own vendor segment; the OpenHands docs describe this openai/<proxy-prefix>/<model-name> form for proxies. Which path is used depends on the model string: OpenHands routes IDs containing gpt-5 through the Responses API and everything else through Chat Completions, unless LiteLLM model metadata or a capability override says otherwise. Router One serves /v1/responses natively for GPT-family IDs, so the same /v1 base URL is correct for both. On the Responses path OpenHands sends store: false, a reasoning effort of high by default, and asks for encrypted reasoning content; confirm in the trace that the first GPT step completes before relying on it.

| Custom Model / LLM_MODEL | Model field OpenHands sends | Request path |
| --- | --- | --- |
| openai/anthropic/claude-sonnet-5 | anthropic/claude-sonnet-5 (first openai/ removed) | /v1/chat/completions |
| openai/google/gemini-3.5-flash, openai/grok-4.6 | The catalog ID after the prefix | /v1/chat/completions |
| openai/openai/gpt-5.5 | openai/gpt-5.5 (GPT-5-family IDs use the Responses path) | /v1/responses |

## Every step carries tools; the condenser is a second caller

OpenHands sends its terminal and file-editing tool definitions with native function calling on every step, so there is no tool-free plain-text request from the agent: choose a model whose detail page lists tool calling on the endpoint from the table above. Memory condensation, enabled by default, builds a second LLM client from the same model, key, and base URL and sends summary requests of its own, which appear as separate lines in the trace. The sandbox, command execution, and the agent loop are application-side: Router One records each model call, its tokens, cost, and status, and does not run the agent. OpenHands' own cost figures come from LiteLLM's price table and its optional input_cost_per_token and output_cost_per_token fields, so treat them as estimates and reconcile against the trace. One task can issue dozens of requests, so give OpenHands a dedicated key with a maxSpend cap; the key is stored in plain text in agent_settings.json.

## Which model ID should OpenHands send?

Copy the exact model ID from /models, preserving case, hyphens, and version suffixes; do not substitute a display name. Open its detail page and match the supported API endpoints, context window, and capabilities such as tool calling to the provider and features selected in OpenHands. A catalog listing does not mean the client can use every feature of that model. Give each tool a dedicated API key with a maxSpend cap.

## Which API protocol is OpenHands using?

OpenAI-compatible describes an interface format; it does not make Chat Completions (/v1/chat/completions), Responses (/v1/responses), and Anthropic Messages (/v1/messages) interchangeable. Check the installed client version, provider configuration, and actual request path against the model detail page and API compatibility fact sheet. A successful plain-text chat does not establish support for hosted tools, conversation state, or file-editing features.

## Verify the OpenHands call in your request trace

Send a simple text request from OpenHands, then match its trace in Dashboard → Logs by time, model, and request_id: tokens, cost, latency, and status. Next, test streaming, tool calls, and multi-turn history separately. For failures, retain the actual request path, full error message, and request_id. If there is no matching log, check client configuration and connectivity before attributing the error to the gateway or upstream.

## FAQ

### Why put openai/ in front of an ID that already starts with anthropic/ or openai/?

The two prefixes mean different things. The first openai/ is a LiteLLM routing instruction that OpenHands requires in Advanced mode and strips before sending; the anthropic/ or openai/ inside the catalog ID is part of the model name Router One expects. Writing openai/gpt-5.5 would send the bare gpt-5.5, which Router One may accept as an alias, but openai/openai/gpt-5.5 sends the exact catalog ID and is the form to keep. The same rule applies in the Custom Model field and in LLM_MODEL.

### Do I have to export the LLM_* variables every time?

No. Values saved from the Settings screen live in ~/.openhands/agent_settings.json and are reused on every start. The environment variables are a one-off override that only takes effect with --override-with-envs; without the flag, OpenHands warns that they are set but ignored. The Docker command in the OpenHands install docs mounts ~/.openhands into the container, so settings saved on the host apply there as well.

### What about openhands serve, Agent Canvas, and OpenHands Cloud?

The GUI server started by openhands serve has the same three fields under Settings → LLM after enabling Advanced: Custom Model with the provider prefix, Base URL, and API Key. Agent Canvas keeps them in an LLM profile's Advanced tab, using the openai/<model-id> form its docs give for OpenAI-compatible servers; the base URL must be reachable from its backend. OpenHands Cloud and the ACP agents that Agent Canvas can attach, such as Claude Code or Codex, use their own authentication and model settings, so this guide does not apply to them.

### Which models can OpenHands use through the gateway?

Choose a current catalog model that supports both the endpoint and the features OpenHands uses. Check /models and the model detail page for the exact ID, current rates, and capabilities; a family name such as GPT or Claude is not a compatibility guarantee. Seeing a model in the picker confirms discovery, so verify an actual request too.

### Models are listed, but requests fail with 400 or 404. What should I check?

Record the actual request path and error message, then check the exact model ID. A 400 can indicate invalid parameters, unsupported tools, or a model/endpoint mismatch; a 404 can indicate an incorrect path or missing resource, so it does not by itself establish that a model was retired. If the error says must be called via, use the named endpoint or select a model supported on the current endpoint. Do not add or remove /v1 or /chat/completions across all clients indiscriminately.

### Does this work from Mainland China?

Yes. The gateway is reachable from Mainland China without a VPN, and the configuration is identical to the global setup.

### How do I debug a 401/402/403/429?

Match the request and error message in Dashboard → Logs. For 401, check whether the key was sent and is valid; for 402, check wallet balance and maxSpend; for 403, check key permissions and access restrictions. For 429, distinguish request/token limits from upstream throttling using the error details. Keep the request_id and follow the error-codes reference.

## See also

- All integration guides: https://router.one/integrations
- Debug API errors in OpenHands: https://router.one/llm-api-error-codes
- API compatibility: endpoints and supported features: https://router.one/facts/api-compatibility.md
- Responses API setup and limits: https://router.one/codex-responses-api
- NextChat setup: https://router.one/integrations/nextchat
- CrewAI setup: https://router.one/integrations/crewai
- Aider setup: https://router.one/integrations/aider
- Cline setup: https://router.one/integrations/cline
- One gateway behind every coding tool: https://router.one/use-cases/ai-coding-tools
- OpenHands docs: OpenAI-compatible proxies: https://docs.openhands.dev/openhands/usage/llms/openai-llms
- OpenHands docs: CLI command reference and LLM_* variables: https://docs.openhands.dev/openhands/usage/cli/command-reference
- OpenHands docs: LLM settings: https://docs.openhands.dev/openhands/usage/settings/llm-settings
- What the gateway layer does: https://router.one/llm-api-gateway
- OpenAI-compatible API: https://router.one/openai-compatible-api
- API docs: https://router.one/docs
- Canonical page: https://router.one/integrations/openhands
- Models and per-model token rates: https://router.one/models (markdown: https://router.one/models.md)
- Pricing: https://router.one/pricing
- API docs (markdown): https://router.one/docs.md
- Company facts: https://router.one/facts/company.md
