OpenHands / OpenHands/OpenHands
Canvas (cloud/SaaS): verification confirm & compact-context buttons raise HTTP 405
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 88.5k
- Forks
- 11.6k
- Avg merge
- 2d 22h
- Merged PRs (30d)
- 189
Description
Summary
In prod and staging (launched from openhands/saas-deploy), the Agent Canvas UI at app.all-hands.dev/canvas returns HTTP 405 when the user clicks:
- the verification confirm button (confirmation mode), and
- the compact context (condense) button.
The legacy UI at app.all-hands.dev/ does not have this problem — the same buttons work there.
Root cause
This is not a CORS issue (initial suspicion). It is a missing route.
In cloud mode the Canvas frontend routes every agent-server runtime call through a POST /api/cloud-proxy envelope on the cloud backend, with the per-conversation runtime URL passed as hostOverride. That /api/cloud-proxy route does not exist on the saas-deploy backend, so every runtime-scoped call returns 405 Method Not Allowed.
The legacy openhands/openhands UI works because it calls the runtime directly with the X-Session-API-Key header — it never goes through /api/cloud-proxy.
The runtime's CORS allowlist (OH_ALLOW_CORS_ORIGINS, already set to the Canvas origin in saas-deploy) permits direct browser→runtime calls, so the proxy hop is unnecessary. Canvas was dealing with runtime calls differently from the legacy UI, which is why only Canvas broke.
Affected runtime calls (all routed via /api/cloud-proxy → 405)
respondToConfirmation(verification confirm)condenseConversation(compact context)sendMessage/sendEvent- bash event reads (
listOutputs) executeCommanddownloadFilegetGitCommits/ commit-changes / commit-diff
Proposed fix
Collapse each cloud runtime branch onto the same direct typed-client path local mode already uses (ConversationClient / BashClient / RemoteWorkspace / FileClient / HttpClient pointed at the per-conversation runtime URL, authenticated with the session API key). The runtime CORS allowlist already permits the cross-origin call.
App-API-only calls that have no per-conversation runtime host (event history search, git changes/diff listing, profile/acp-model switches) keep using callCloudProxy against the cloud backend host — those are not runtime calls and are not affected.
This is the "easy fix" alternative to the heavier enterprise-side approach in https://github.com/OpenHands/enterprise/pull/424.
Environment
- Frontend:
app.all-hands.dev/canvas(Agent Canvas) - Backend:
openhands/saas-deploy(prod + staging) - Legacy UI
app.all-hands.dev/unaffected
This issue was created by an AI agent (OpenHands) on behalf of the user.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by tracing the Canvas cloud runtime branches for respondToConfirmation, condenseConversation, sendMessage, and the other listed runtime calls, comparing them with the local ConversationClient, BashClient, RemoteWorkspace, FileClient, and HttpClient paths. Done means runtime calls use the per-conversation URL with the session API key and no longer return 405, while app-API-only calls continue using callCloudProxy.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- api, cloud, frontend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 62/100