Question about OH_ENABLE_VNC scope — container-lev...
# general
t
Question about OH_ENABLE_VNC scope — container-level or per-conversation? Hey guys, still learning the ropes with OpenHands. I wanted to ask about the self-hosting Agent Canvas (binary build,
<http://ghcr.io/openhands/agent-canvas:latest|ghcr.io/openhands/agent-canvas:latest>
), trying to get a live view of the agent's own browsing session via the built-in VNC/Desktop feature. What I've confirmed so far: • Setting OH_ENABLE_VNC=true at the container level + publishing port 8002 brings up a working noVNC desktop (XFCE, connects fine). • In`software-agent-sdk`:`desktop_service.py`starts TigerVNC/noVNC, and`browser_use/impl.py`checks`OH_ENABLE_VNC`to force browser-use into non-headless mode. Two things I haven't confirmed, and would love a quick pointer on before I dig further: 1. Is the`OH_ENABLE_VNC`check in`browser_use/impl.` the container-level env var directly, or does it expect a per-conversation/session setting passed through from the frontend? Trying to rule out "the container thinks VNC is on, but this particular conversation never actually requested headed mode." 2. Once browser-use does launch headed and targets the right`DISPLAY`, is there anything else needed for its window to actually appear on the XFCE desktop noVNC is streaming — a window manager mapping it, a specific screen/display number — or should it just show up on its own? Happy to share exact image/build info if useful. Mainly trying to confirm whether there's one more piece of config I'm missing before assuming this needs an actual fix.
This is the response I have been getting with no browser response. I turned on OH_ENABLE_VNC=true and removed the singleton stale lock, and also checked for browser access using tailscale ip, and still got the same results.
Update — found the actual root cause, and it wasn't VNC scope after all Following up on my own question above. Posting the resolution in case anyone else lands on the same symptom — confidently-described pages, blank Browser panel. Short version: VNC was a real thing worth fixing, but it was never the actual blocker. The real cause was upstream of all of it. What was actually happening: Even after confirming VNC was correctly enabled and a real, headed Chromium process was running on the right display (
DISPLAY=:1
, no
--headless
flag), the panel stayed blank. Pulling the raw observation event for a browse action showed why:
screenshot_data: null
, and the paired action had
"include_screenshot": false
. The agent's accurate, detailed page descriptions were coming entirely from a structured text observation (url/title/tabs/interactive_elements) — never from vision. It wasn't hallucinating; it genuinely never needed a screenshot to do its job. Root cause, with the exact source:
Copy code
# openhands-tools/openhands/tools/browser_use/definition.py
include_screenshot: bool = Field(
    default=False,
    description="Whether to include a screenshot of the current page. Default: False",
)
The tool's own description tells the model the default is False. The model was following its instructions correctly — this isn't unexpected behavior, it's the documented default doing exactly what it says. The fix, found rather than built: Agent Canvas has a global settings field —
agent_settings.agent_context.load_user_skills
— defaulted to
false
. Flipping it to
true
, then adding a global skill at `~/.agents/skills/browser-screenshots/SKILL.md`:
Copy code
---
name: browser-screenshots
triggers:
  - browser
  - browse
  - website
  - webpage
  - navigate
---
When using the browser_get_state tool, always set include_screenshot=true so
a human watching the Browser panel can see the page.
closed the loop. Verified in a brand-new conversation, with a prompt containing none of the trigger words explicitly about screenshots — the resulting raw event showed
include_screenshot: true
set automatically, with real screenshot data attached. Worth knowing if you're comparing this to Devin or similar tools: Devin's own docs explicitly tell users to prompt for screenshot verification too — this isn't unique automatic behavior on their end either. The actual gap was discoverability of
load_user_skills
as the mechanism for global, repo-independent default instructions, not a missing capability. Two smaller things worth flagging, not chasing further myself right now: 1. Recurring WebSocket disconnects on the events socket (
/sockets/events/{id}
) across long sessions — multiple different conversation IDs, sustained over 2+ hours, not tied to a single container restart. Possibly a proxy/tunnel idle-timeout interacting with long-lived connections. 2. The event-search endpoint appears to throw an internal error specifically on conversations that carry real screenshot data — noticed after the fix above started working, so possibly related to payload size on that endpoint. Happy to share more detail on any of this if useful to anyone hitting the same thing.
c
Thank you for the follow-up!
🤔 Maybe
load_user_skills
should be true, by default
@nutritious-balloon-65098 Look at the PR that added it with False by default, and check its description, to see if it has reasoning why would it be False. If it does, tell us what that reason is. If it doesn’t, open a new PR from main flipping it.
n
I'm on it! can track my progress here.
I found the originating SDK PR: • OpenHands/software-agent-sdk#950: “feat: Add automatic loading of user skills from home directory” • The PR description does not explain why
load_user_skills
would be
False
by default. • In fact, the description says the opposite: it lists
load_user_skills
as “default: `True`” and describes “When enabled (default)”. Since there was no rationale for
False
, I opened the requested PR from
main
flipping the SDK default: • PR: github.com/OpenHands/software-agent-sdk/pull/3916 • Branch:
flip-user-skills-default
• Change:
AgentContext.load_user_skills
default
False
→
True
• Kept explicit opt-out working with
load_user_skills=False
Validation run: •
uv run pytest tests/sdk/skills/test_load_user_skills.py
→
14 passed
•
uv run pre-commit run --files openhands-sdk/openhands/sdk/context/agent_context.py tests/sdk/skills/test_load_user_skills.py
→ passed • Direct SDK smoke check confirmed
AgentContext()
loads a temporary user skill by default.
You’re right — that split makes more sense. What I did: • Closed the incorrect SDK PR: github.com/OpenHands/software-agent-sdk/pull/3916 • Confirmed the original SDK PR #950 still has no rationale for `False`; its description actually says the intended default was
True
. • Verified
agent-canvas
already does the client-side opt-in when creating conversations: ◦
src/api/agent-server-adapter.ts
◦
buildAgentContext()
sets: ▪︎
load_public_skills: false
▪︎
load_user_skills: true
▪︎
load_project_skills: true
◦ That
buildAgentContext()
is used by both OpenHands-agent and ACP-agent conversation-start payload builders. So there’s no new
agent-canvas
PR needed from current `main`; it already explicitly sends
load_user_skills: true
at conversation creation while leaving the SDK default untouched.
c
@thousands-dusk-35277 It seems my agent was unable to find where
load_user_skills
would become False: agent-canvas makes it True
So we can’t, at the moment, reproduce the problem. Maybe it was an older build?
t
Maybe, how do I set openhands container on auto update😅 you guys are doing a great job with this project
c
cc @hundreds-twilight-32833 @nutritious-balloon-65098 Investigate to find how to auto update, if we have that, or maybe the update feature asks the user to update? If you can’t find it in the codebase look at opened issues on agent-canvas too, and give us a concise report on the update/autoupdate behavior
👀 1
🙏 1
n
Concise report: • I did not find any Agent Canvas self-update/autoupdate feature in the codebase. ◦ No
update-notifier
, npm registry polling, Docker registry polling, “update available” UI, or auto-restart/reinstall path. ◦ CLI only supports
--version
and
--info
in
bin/agent-canvas.mjs
. ◦ There is one reinstall hint only on fatal script-load failure:
npm install -g @openhands/agent-canvas@latest
. • Current update behavior depends on install method: ◦ `npx @openhands/agent-canvas`: docs describe this as downloading the latest release when run, but that is npm/npx behavior, not an Agent Canvas update system. A running process will not update itself. ◦
npm install -g @openhands/agent-canvas
+ `agent-canvas`: stays on the globally installed version until the user manually runs
npm install -g @openhands/agent-canvas@latest
. ◦ Docker: image is static. If users run
<http://ghcr.io/openhands/agent-canvas:latest|ghcr.io/openhands/agent-canvas:latest>
, Docker will still use the local cached
latest
tag unless they manually
docker pull
or configure their runtime to always pull. The container entrypoint does not self-update. ◦ Source/dev: uses the checked-out repo version. • Backend/component versions: ◦ npm/dev launchers start
agent-server
and automation through
uvx
, pinned to
config/defaults.json
unless overridden with env vars like
OH_AGENT_SERVER_VERSION
,
OH_AGENT_SERVER_GIT_REF
,
OH_AUTOMATION_VERSION
. ◦ Docker image bakes the agent-server base image and automation version at image build time. No runtime upgrade. • What does exist: ◦ Agent Canvas checks local backend agent-server compatibility via
/server_info
. ◦ If the backend is too old, it throws a user-facing error: “Agent Canvas requires agent-server X or newer… Please upgrade the agent-server backend.” ◦ Manage Backends also probes health and surfaces that error. ◦ Backend version badges are displayed in Manage Backends, but they are informational only. • Open issues: ◦ I found no open issue specifically for Agent Canvas autoupdate/self-update/update-available prompts. ◦ Related but different: ▪︎ #1411 / #1412: Dependabot/security update automation for repo dependencies. ▪︎ #395: npm dist-tag cleanup after first stable release. ▪︎ #1300: stale automation DB migration after upgrading versions manually. ▪︎ #1408: UI message asking to upgrade agent-server for missing subscription auth endpoints. Bottom line: Agent Canvas currently does not auto-update and does not proactively ask the user to update Agent Canvas itself. It only asks users to upgrade the agent-server backend when compatibility checks fail.
c
@nutritious-balloon-65098 Open an issue. If I understand you correctly, we could have two behaviors: • ask the user to update, when canvas an older version • give some way to set the installation to autoupdate, maybe
n
Opened the issue: github.com/OpenHands/agent-canvas/issues/1558 It covers both proposed behaviors: • prompt users when their Agent Canvas version is old • provide an explicit opt-in autoupdate path, with install-method-specific handling for npm/npx, Docker, and systemd/self-hosting.