This skill should be used when the user asks to "test a cross-repo feature", "deploy a feature branch to staging", "test SDK against OH Cloud", "e2e test a cloud workspace feature", "test provider tokens", "test secrets inheritance", or when changes span the SDK and OpenHands server repos and need end-to-end validation against a staging deployment.
How to end-to-end test features that span OpenHands/software-agent-sdk and OpenHands/OpenHands (the Cloud backend).
| Repo | Role | What lives here |
|---|---|---|
software-agent-sdk | Agent core | openhands-sdk, openhands-workspace, openhands-tools packages. OpenHandsCloudWorkspace lives here. |
OpenHands | Cloud backend |
FastAPI server (openhands/app_server/), sandbox management, auth, enterprise integrations. Deployed as OH Cloud. |
deploy | Infrastructure | Helm charts + GitHub Actions that build the enterprise Docker image and deploy to staging/production. |
Data flow: SDK client → OH Cloud API (/api/v1/...) → sandbox agent-server (inside runtime container)
There are two flows depending on which direction the dependency goes:
| Flow | When | Example |
|---|---|---|
| A — SDK client → new Cloud API | The SDK calls an API that doesn't exist yet on production | workspace.get_llm() calling GET /api/v1/users/me?expose_secrets=true |
| B — OH server → new SDK code | The Cloud server needs unreleased SDK packages or a new agent-server image | Server consumes a new tool, agent behavior, or workspace method from the SDK |
Flow A only requires deploying the server PR. Flow B requires pinning the SDK to an unreleased commit in the server PR and using the SDK PR's agent-server image. Both flows may apply simultaneously.
Use this when the SDK calls an endpoint that only exists on the server PR branch.
In the OpenHands repo, implement the new API endpoint(s). Run unit tests:
cd OpenHands
poetry run pytest tests/unit/app_server/test_<relevant>.py -v
Push a PR. Wait for the "Push Enterprise Image" (Docker) CI job to succeed — this builds ghcr.io/openhands/enterprise-server:sha-<COMMIT>.
In software-agent-sdk, implement the client code (e.g., new methods on OpenHandsCloudWorkspace). Run SDK unit tests:
cd software-agent-sdk
pip install -e openhands-sdk -e openhands-workspace
pytest tests/ -v
Push a PR. SDK CI is independent — it doesn't need the server changes to pass unit tests.
See Deploying to a Staging Feature Environment below.
See Running E2E Tests Against Staging below.
Use this when the Cloud server depends on SDK changes that haven't been released to PyPI yet. The server's runtime containers run the agent-server image built from the SDK repo, so the server PR must be configured to use the SDK PR's image and packages.
The SDK PR must have CI pass so its agent-server Docker image is built. The image is tagged with the merge-commit SHA from GitHub Actions — NOT the head-commit SHA shown in the PR.
Find the correct image tag:
AGENT_SERVER_IMAGES section"short_sha": "<tag>"In the OpenHands repo PR, pin all 3 SDK packages (openhands-sdk, openhands-agent-server, openhands-tools) to the unreleased commit and update the agent-server image tag. This involves editing 3 files and regenerating 3 lock files.
Follow the update-sdk skill → "Development: Pin SDK to an Unreleased Commit" section for the full procedure and file-by-file instructions.
Push the pinned changes. The OpenHands CI will build a new enterprise Docker image (ghcr.io/openhands/enterprise-server:sha-<OH_COMMIT>) that bundles the unreleased SDK. Wait for the "Push Enterprise Image" job to succeed.
Follow Deploying to a Staging Feature Environment using the new OpenHands commit SHA.
CI guard: check-package-versions.yml blocks merge to main if [tool.poetry.dependencies] contains rev fields. Before the OpenHands PR can merge, the SDK PR must be merged and released to PyPI, then the pin must be replaced with the released version number.
The deploy repo creates preview environments from OpenHands PRs.
Option A — GitHub Actions UI (preferred):
Go to OpenHands/deploy → Actions → "Create OpenHands preview PR" → enter the OpenHands PR number. This creates a branch ohpr-<PR>-<random> and opens a deploy PR.
Option B — Update an existing feature branch:
cd deploy
git checkout ohpr-<PR>-<random>
# In .github/workflows/deploy.yaml, update BOTH:
# OPENHANDS_SHA: "<full-40-char-commit>"
# OPENHANDS_RUNTIME_IMAGE_TAG: "<same-commit>-nikolaik"
git commit -am "Update OPENHANDS_SHA to <commit>" && git push
Before updating the SHA, verify the enterprise Docker image exists:
gh api repos/OpenHands/OpenHands/actions/runs \
--jq '.workflow_runs[] | select(.head_sha=="<COMMIT>") | "\(.name): \(.conclusion)"' \
| grep Docker
# Must show: "Docker: success"
The deploy CI auto-triggers and creates the environment at: