Skip to main content
Run a local Agent Server when you want a backend process to host OpenHands conversations over HTTP and WebSocket. This is the simplest setup for testing Agent Canvas-style backends, local integrations, and client-server SDK applications.

Install

Create a Python environment and install the server package and its SDK dependencies:
uv venv
source .venv/bin/activate
uv pip install -U \
  openhands-sdk \
  openhands-tools \
  openhands-workspace \
  openhands-agent-server
If you are working from the OpenHands/software-agent-sdk repository, see Agent Server Package § Install for the uv-based setup.

Start Without Authentication

For local development on your own machine, start the server on loopback:
python -m openhands.agent_server --host 127.0.0.1 --port 8000
Verify that it is running:
curl http://127.0.0.1:8000/health
Open the API docs at http://127.0.0.1:8000/docs. If SESSION_API_KEY (legacy alias) or OH_SESSION_API_KEYS_* is already set in your shell, the server will require that key for /api/* requests. Unset those variables for unauthenticated local-only testing.
This unauthenticated mode is only appropriate for local development. Do not bind an unauthenticated server to a public or shared network interface.

Start With an API Key

Set a session API key before starting the server:
export OH_SESSION_API_KEYS_0="$(openssl rand -hex 32)"
export OH_SECRET_KEY="$(openssl rand -hex 32)"

python -m openhands.agent_server --host 127.0.0.1 --port 8000
Requests to /api/* must include the session key. This request returns the conversation count when the key is accepted:
curl \
  -H "X-Session-API-Key: $OH_SESSION_API_KEYS_0" \
  http://127.0.0.1:8000/api/conversations/count
OH_SECRET_KEY encrypts sensitive values stored with conversations, including LLM API keys and secrets. Keep it stable across restarts. If it changes, previously encrypted values cannot be restored.

Connect From the SDK

Use Workspace(host=..., api_key=...) to connect SDK code to the server:
import os

from pydantic import SecretStr

from openhands.sdk import Conversation, LLM, Workspace
from openhands.tools.preset.default import get_default_agent


llm = LLM(
    model=os.environ.get("LLM_MODEL", "anthropic/claude-sonnet-4-5-20250929"),
    api_key=SecretStr(os.environ["LLM_API_KEY"]),
)
agent = get_default_agent(llm=llm, cli_mode=True)  # disable browser-automation tools

workspace = Workspace(
    host="http://127.0.0.1:8000",
    api_key=os.environ["OH_SESSION_API_KEYS_0"],
    working_dir="workspace/project",
)

conversation = Conversation(agent=agent, workspace=workspace)
conversation.send_message("Create a NOTES.md file with three facts about this project.")
conversation.run()
conversation.close()
If the server was started without OH_SESSION_API_KEYS_0, remove the api_key=... argument. The working_dir value is relative to the server’s process working directory. See Runtime Files for the default directory layout.

Connect From Another Service

For a non-SDK backend service, pass the session API key as X-Session-API-Key:
curl \
  -H "X-Session-API-Key: $OH_SESSION_API_KEYS_0" \
  -H "Content-Type: application/json" \
  http://127.0.0.1:8000/api/conversations/count
Keep the Agent Server bound to 127.0.0.1 when the backend runs on the same machine. If the backend runs on another host, use a private network or reverse proxy, enable TLS, and restrict network access to trusted callers. For CORS configuration and running directly from a checkout of OpenHands/software-agent-sdk, see the Agent Server Package page.

Ready-to-Run Example

The example starts a local Agent Server subprocess, waits for it to become healthy, connects with Workspace(host=...), and runs a RemoteConversation. You can run the example code as-is.
The model name should follow the LiteLLM convention: provider/model_name (e.g., anthropic/claude-sonnet-4-5-20250929, openai/gpt-4o). The LLM_API_KEY should be the API key for your chosen provider.
ChatGPT Plus/Pro subscribers: You can use LLM.subscription_login() to authenticate with your ChatGPT account and access Codex models without consuming API credits. See the LLM Subscriptions guide for details.

Troubleshooting

  • 401 Unauthorized: Check that the client sends X-Session-API-Key and that it matches OH_SESSION_API_KEYS_0.
  • Secrets are missing after restart: Set a stable OH_SECRET_KEY before starting the server.
  • The server is reachable locally but not from another machine: Use --host 0.0.0.0 only behind trusted network controls, then check firewall and proxy rules.
  • CORS errors in a browser: Set OH_ALLOW_CORS_ORIGINS_0 to the browser app origin.
  • Port conflict: Start with another port, for example --port 8001.

Next Steps