Skip to content

[codex] clarify agent server setup docs#534

Open
neubig wants to merge 2 commits into
mainfrom
codex/agent-server-user-docs
Open

[codex] clarify agent server setup docs#534
neubig wants to merge 2 commits into
mainfrom
codex/agent-server-user-docs

Conversation

@neubig
Copy link
Copy Markdown
Member

@neubig neubig commented May 28, 2026

Summary

  • Rework the Agent Server package page from implementation/deployment internals into install, run, secure, connect, and troubleshooting guidance.
  • Rewrite the Local Agent Server guide around the user flow for bringing up a server locally, securing it with OH_SESSION_API_KEYS_0, and connecting with Workspace(host=..., api_key=...).
  • Regenerate llms.txt and llms-full.txt so the LLM-facing docs reflect the new guidance.

Why

The previous Agent Server docs were more useful to SDK developers than to users trying to run the server for an Agent Canvas-style backend. They also used older or misleading auth examples, including bearer-token examples instead of the current X-Session-API-Key flow.

Runtime validation evidence

This PR update was generated by an AI agent (OpenHands) on behalf of neubig.

Validated in a fresh sandbox venv on Python 3.13.13.

What failed before the follow-up docs fix

The original unpinned install command from this PR installed a mismatched package set: openhands-agent-server==1.24.0 with openhands-sdk==1.17.0. Starting the server then failed before binding a port:

ModuleNotFoundError: No module named 'openhands.sdk.agent.acp_models'

That is why this update changes the install instructions to pin all openhands-* packages to the same release.

Corrected install command now validated

python -m venv .venv
source .venv/bin/activate
export OPENHANDS_VERSION="1.24.0"
pip install -U \
  "openhands-sdk==$OPENHANDS_VERSION" \
  "openhands-tools==$OPENHANDS_VERSION" \
  "openhands-workspace==$OPENHANDS_VERSION" \
  "openhands-agent-server==$OPENHANDS_VERSION"
pip check

Important output:

No broken requirements found.
python 3.13.13
openhands-sdk==1.24.0
openhands-tools==1.24.0
openhands-workspace==1.24.0
openhands-agent-server==1.24.0

Local server without session auth

The sandbox has an ambient SESSION_API_KEY, so I explicitly unset it to test the documented local unauthenticated mode:

env -u SESSION_API_KEY -u OH_SESSION_API_KEYS_0 -u OH_SECRET_KEY \
  OPENHANDS_SUPPRESS_BANNER=1 \
  python -m openhands.agent_server --host 127.0.0.1 --port 8001

HTTP checks:

GET http://127.0.0.1:8001/health -> 200 {"status":"ok"}
GET http://127.0.0.1:8001/api/conversations/count -> 200 0
GET http://127.0.0.1:8001/api/settings -> 200 {"agent_settings": ...}

Server log included:

Server initialization complete - ready to serve requests
Uvicorn running on http://127.0.0.1:8001

Local server with OH_SESSION_API_KEYS_0

export OH_SESSION_API_KEYS_0="$(openssl rand -hex 32)"
export OH_SECRET_KEY="$(openssl rand -hex 32)"
OPENHANDS_SUPPRESS_BANNER=1 \
  python -m openhands.agent_server --host 127.0.0.1 --port 8000

HTTP/auth checks:

GET http://127.0.0.1:8000/health -> 200 {"status":"ok"}
GET http://127.0.0.1:8000/api/conversations/count without X-Session-API-Key -> 401 {"detail":"Unauthorized"}
GET http://127.0.0.1:8000/api/conversations/count with X-Session-API-Key -> 200 0
GET http://127.0.0.1:8000/server_info -> 200, version=1.24.0, sdk_version=1.24.0

SDK Workspace(host=..., api_key=...) connection

Executed against the authenticated server:

import os
from openhands.sdk import Workspace

workspace = Workspace(
    host="http://127.0.0.1:8000",
    api_key=os.environ["OH_SESSION_API_KEYS_0"],
    working_dir="workspace/project",
)
info = workspace.get_server_info()
result = workspace.execute_command("pwd && echo agent-server-doc-validation", timeout=30)

Output:

workspace_type= RemoteWorkspace
server_info_version= 1.24.0
server_info_sdk_version= 1.24.0
command_result= {"command": "pwd && echo agent-server-doc-validation", "exit_code": 0, "stderr": "", "stdout": "/tmp/agent-server-doc-validation-pin\nagent-server-doc-validation\n", "timeout_occurred": false}

Validation scope

The Agent Server install, process startup, health/readiness metadata, session API key behavior, and SDK remote workspace connection were validated with real package installs, real server processes, and real HTTP/SDK calls. I did not run the LLM-backed conversation.run() example because the requested Agent Server setup/auth/connectivity flow was proven without requiring an external model call.

@mintlify
Copy link
Copy Markdown

mintlify Bot commented May 28, 2026

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
all-hands-ai 🟢 Ready View Preview May 28, 2026, 4:35 PM

💡 Tip: Enable Workflows to automatically generate PRs for you.

Co-authored-by: openhands <openhands@all-hands.dev>
@neubig neubig marked this pull request as ready for review May 29, 2026 05:09
@neubig neubig requested review from enyst and xingyaoww as code owners May 29, 2026 05:09
Copy link
Copy Markdown
Contributor

all-hands-bot commented May 29, 2026

Review complete.

This review was performed through OpenHands Cloud Automation. You can log in and view the conversation here.

Copy link
Copy Markdown
Contributor

@all-hands-bot all-hands-bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review: [codex] clarify agent server setup docs

This is a well-directed rework. The old pages were primarily an internal architecture reference and a code-walkthrough of ManagedAPIServer; the new pages are practical install-and-run guides. The direction is right and the content is accurate. A few issues need attention before merging.


🔴 Critical

Hardcoded version 1.24.0 in install snippets (both files)

Both sdk/arch/agent-server.mdx and sdk/guides/agent-server/local-server.mdx have:

export OPENHANDS_VERSION="1.24.0"
pip install -U \
  "openhands-sdk==$OPENHANDS_VERSION" \
  ...

This will be stale the moment 1.25.0 ships, and readers will install an old version without realizing it. Options:

  • Drop the version pin and use pip install -U openhands-sdk openhands-tools openhands-workspace openhands-agent-server (always latest).
  • Use a placeholder like OPENHANDS_VERSION="<see releases>" with a link to the GitHub releases page.
  • If the docs pipeline supports version variables, use that instead.

🟡 Medium

Inconsistent api_key pattern between the two files

sdk/arch/agent-server.mdx "Connect From Python" section uses:

api_key=os.environ["OH_SESSION_API_KEYS_0"],  # raises KeyError if not set

sdk/guides/agent-server/local-server.mdx "Connect From the SDK" section uses:

api_key=os.environ.get("OH_SESSION_API_KEYS_0"),  # silently passes None

The local-server page then says "If the server was started without OH_SESSION_API_KEYS_0, omit api_key" — but the code doesn't omit it; it passes None. A reader copying the snippet and running an unauthenticated server will either get an unexpected error or silent behavior depending on whether the SDK treats None the same as omitting the argument. These two examples should be consistent. The arch page's os.environ["..."] pattern (fail loudly if not set) is the clearer choice when auth is expected.

OH_SECRET_KEY description is inconsistent and vague in local-server.mdx

The arch page has a clear <Note> explaining what OH_SECRET_KEY actually does:

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

The local-server guide only says:

"Use OH_SECRET_KEY whenever you want conversations and stored settings to survive restarts with their sensitive values intact."

This understates the risk: if the key changes, previously encrypted values are unrecoverable. The <Note> from the arch page (or equivalent) should be in the local-server guide as well.


🟢 Minor / Suggestions

Duplicate install instructions

The install block is byte-for-byte identical in both files. If the package list or version changes, both pages need to be updated in sync. Consider a shared Mintlify snippet (like the existing RunExampleCode import pattern) to DRY this up, or at minimum add a cross-reference so readers know the canonical location.

working_dir="workspace/project" needs a brief explanation

Both Python snippets use working_dir="workspace/project" without explanation. New users will wonder: does this directory need to exist beforehand? Is workspace/project a convention? The arch page's "Runtime Files" section explains the layout, but that connection isn't made in the local-server guide. A single sentence would help.

"Connect From Another Service" section is thin

This section in local-server.mdx describes the same two configuration values already covered in "Connect From the SDK" but without a code example. Consider either adding a raw curl example for non-SDK callers, or folding this guidance into the "Connect From the SDK" section.


✅ What's working well

  • Replacing the architecture/design-decisions content with actionable install-and-run steps is exactly the right call.
  • The security guidance (<Warning> for unauthenticated mode, OH_SESSION_API_KEYS_0, key rotation with _1, CORS config) is clear and well-ordered.
  • Troubleshooting sections in both files are concise and cover the most common failure modes.
  • Removing the inlined ManagedAPIServer code and replacing it with a reference to the example file is a significant readability improvement.
  • The Expose It Safely section in the arch page (5-step checklist before using --host 0.0.0.0) is a nice safety net.

This review was generated by an AI agent (OpenHands) on behalf of the user through OpenHands Automation. View conversation

Comment thread sdk/arch/agent-server.mdx
python -m venv .venv
source .venv/bin/activate
export OPENHANDS_VERSION="1.24.0"
pip install -U \
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hardcoded version will go stale. Consider dropping the pin (pip install -U openhands-sdk openhands-tools openhands-workspace openhands-agent-server) or using a placeholder that links to the releases page, so readers always get the correct version.

python -m venv .venv
source .venv/bin/activate
export OPENHANDS_VERSION="1.24.0"
pip install -U \
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same hardcoded 1.24.0 as in sdk/arch/agent-server.mdx. Since the install block is identical in both files, if this is updated in one place it must also be updated in the other — a shared snippet would eliminate that risk.

workspace = Workspace(
host="http://127.0.0.1:8000",
api_key=os.environ.get("OH_SESSION_API_KEYS_0"),
working_dir="workspace/project",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

os.environ.get(...) silently passes None when OH_SESSION_API_KEYS_0 is not set, but the text below says to omit api_key in that case. These are different behaviors. If auth is optional, the example should show a conditional: api_key=os.environ['OH_SESSION_API_KEYS_0'] if 'OH_SESSION_API_KEYS_0' in os.environ else None or restructure the snippet to match the arch page's os.environ['OH_SESSION_API_KEYS_0'] (which fails loudly when the key is absent and auth is required).

This example is available on GitHub: [examples/02_remote_agent_server/01_convo_with_local_agent_server.py](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/02_remote_agent_server/01_convo_with_local_agent_server.py)
</Note>
Use `OH_SECRET_KEY` whenever you want conversations and stored settings to survive restarts with their sensitive values intact. Keep this value stable and store it in your normal secret manager.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This description understates the risk. The arch page's <Note> is more accurate: if OH_SECRET_KEY changes between restarts, previously encrypted values (LLM API keys, stored secrets) cannot be recovered, not just that they won't persist. Consider carrying the same <Note> here.

@neubig
Copy link
Copy Markdown
Member Author

neubig commented May 29, 2026

@OpenHands /iterate

@openhands-ai
Copy link
Copy Markdown

openhands-ai Bot commented May 29, 2026

Uh oh! There was an unexpected error starting the job :(

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants