feat: wire Agent Canvas through Replicated/Helm installs#954
Conversation
Agent Canvas was added to the Helm chart (subchart + /canvas ingress) but was never wired into the Replicated (KOTS) release, so it never deployed on replicated or KOTS-derived Helm installs. - Pin a real default image tag for the agent-canvas subchart so enabling it produces a valid image reference (it previously defaulted to an empty tag). - Add an agent_canvas_enabled config option (default on) in config.yaml. - Add an optionalValues block in openhands.yaml that enables the subchart, points the image at the licensed proxy registry, and mounts /canvas on the primary app host with the existing openhands-tls secret; lockToCloud targets the instance's own app URL. Add agent-canvas to the builder block for airgap image bundling. - Add conditional statusInformers for the agent-canvas deployment/service/ingress. - Add a helm-unittest suite for the agent-canvas ingress. Co-authored-by: openhands <openhands@all-hands.dev>
lilagrc
left a comment
There was a problem hiding this comment.
Initial code review (via /codereview repo skill)
Reviewed against the repo's code-review guidelines. Overall this follows the established Replicated wiring patterns well — the optionalValues block, statusInformers, builder entry, and config toggle all mirror plugin-directory and automation. No blocking (important+) issues found. A few points worth a decision before this leaves draft:
1. Default-on vs. opt-in (guideline #7: "Defaults serve the self-hosted user") — most substantive
agent_canvas_enabled defaults to "1", whereas the comparable feature toggles plugin_directory_enabled and automations_enabled both default to "0". Enabling a relatively new preview UI by default for every self-hosted/Replicated user is a notable posture change. Unless there's a product decision to ship Canvas on by default, defaulting to "0" would be more consistent with the other optional components and safer for self-hosted users. (Flagged in the PR description as an open question.)
2. TLS secret name is inconsistent with the other chart ingresses
The Canvas ingress uses secretName: openhands-tls, but every other ingress in the openhands chart (ingress-root, -mcp, -automation, -integrations-hub, -plugin-directory) uses app-all-hands-{{ .Values.tls.env }}-tls. Both secrets are created with the same cert by openhands-secrets/templates/tls-certificate.yaml, so this is functional, not a bug — but the inconsistency is a small future-maintenance trap. Consider aligning Canvas with the same app-all-hands-<env>-tls secret the sibling ingresses use. (The agent-canvas ingress template takes an explicit secretName, so this is purely a value choice in replicated/openhands.yaml.)
3. Pinned sha- image tag will go stale
The replicated block overrides image.repository but intentionally inherits image.tag from the subchart default (sha-ef3b28a). Because agent-canvas only publishes sha-/pr- tags and there's no image-tag-bump workflow wiring it into this repo, this pin will drift over time unless the deploy workflow always overrides it or a bump automation is added. Worth confirming the intended source of truth for the Canvas tag and whether a follow-up (semver releases or an auto-bump caller) should track it.
4. Config grouping (minor)
plugin_directory_enabled lives under the Experimental group ("Preview features … Enable at your own risk"). If Canvas is still preview-quality, placing agent_canvas_enabled there rather than in a new dedicated group may set clearer expectations; if it's considered GA, a standalone group is fine.
Nits
- None blocking. The comments on the
optionalValuesblock and image tag are clear and helpful.
Tests and build validation look solid (helm unittest 31 passed incl. the new ingress suite; make manifests builds cleanly).
This review was generated by an AI agent (OpenHands) on behalf of the user.
Summary
Agent Canvas (the
/canvasUI) was added to the Helm chart in #900 — theagent-canvassubchart, thetemplates/ingress-agent-canvas.yamlumbrella ingress, and anagent-canvas:block incharts/openhands/values.yaml. However, that PR never touchedreplicated/, so the feature was never wired into the Replicated (KOTS) release. Replicated installs (and Helm installs derived from the KOTS values) are driven byreplicated/openhands.yaml, which had zero agent-canvas configuration, so the subchart stayed at itsenabled: falsedefault and never deployed. There was also no config toggle, no status informers, and no airgap image-bundling entry.A latent bug compounded this: the subchart's
image.tagdefaulted to"", so even a bareagent-canvas.enabled: truewould render an invalid image reference (ghcr.io/openhands/agent-canvas:) and fail to pull.This PR wires Agent Canvas all the way through to Replicated/Helm customers.
Changes
charts/openhands/charts/agent-canvas/values.yaml— pin a real defaultimage.tag(sha-ef3b28a, the currentmainbuild; digest-verified against the ghcrmaintag) so the chart is deployable on its own. The OpenHands Cloud deploy workflow still overrides this at deploy time. agent-canvas only publishessha-/pr-tags (no semver), so this tracks a known-goodmainbuild.replicated/config.yaml— add anagent_canvas_configurationgroup with anagent_canvas_enabledbool. Defaulted on so it ships to customers, but is a clean opt-out.replicated/openhands.yaml—optionalValuesblock (gated onagent_canvas_enabled) that enables the subchart, points the image at the licensed proxy registry, adds the image pull secret, enables the ingress on the primary app host at/canvaswith the existingopenhands-tlssecret, and setsstaticServer.lockToCloudto the instance's own app URL (so the Canvas UI targets the customer's backend, not all-hands.dev);agent-canvasto thebuilderblock for airgap image bundling.replicated/application.yaml— add conditionalstatusInformersfor the agent-canvas deployment, service, and ingress.charts/openhands/tests/agent_canvas_ingress_test.yaml— new helm-unittest suite covering disabled cases,/canvasrouting, TLS on/off, and the required-host failure.Validation
helm unittest charts/openhands-> 31 passed (including 5 new agent-canvas tests).make manifestsbuilds all Replicated manifests cleanly with the canvas wiring present.replicated/*.yamlfiles parse as valid YAML.ghcr.io/openhands/agent-canvas:sha-ef3b28a) and correct--base-path/--lock-to-cloud/--auth-requiredargs.Notes / open questions
agent_canvas_enableddefaults to"1"to satisfy "available all the way through to customers." If you'd prefer opt-in like plugin-directory ("0"), that's a one-line change./canvas-> canvas,/-> app), matching productionapp.all-hands.dev/canvas.This PR was created by an AI agent (OpenHands) on behalf of the user.