OpenHands/agent-canvas

Document migration from OpenHands OSS Local GUI to Agent Canvas

已关闭

#1,054 创建于 2026年6月3日

 (2 条评论) (0 个反应) (0 位负责人)TypeScript (26 个派生)github user discovery
documentationgood first issue

仓库指标

星标
 (43 个星标)
PR 合并指标
 (平均合并 2天 10小时) (30 天内合并 106 个 PR)

描述

Context

Agent Canvas is intended to replace the OSS Local GUI experience from OpenHands/OpenHands. This issue tracks the verified migration behavior and documentation/work needed for users moving from the old OSS Local GUI to Agent Canvas.

Investigation snapshots:

  • OpenHands/agent-canvas: 10d0a1bf (2026-06-03, "Add frontend-only and backend-only agent-canvas modes")
  • OpenHands/OpenHands: 8fdf41d (2026-06-02, "Avoid Keycloak full scan in Resend sync")
  • OpenHands/software-agent-sdk: e3c9828, package version 1.24.0, matching agent-canvas/config/defaults.json

This issue was created and updated by an AI agent (OpenHands) on behalf of the user.

TL;DR

Agent Canvas does not perform a complete in-place migration from OpenHands OSS Local GUI state. It reuses a narrow subset of the old ~/.openhands/settings.json data, ignores several old top-level settings, stores LLM profiles in a different location/shape, and currently does not reuse old plaintext secret values when Agent Canvas starts with its default generated OH_SECRET_KEY.

The migration guide needs to be explicit about the following:

  1. Back up ~/.openhands before first Agent Canvas launch.
  2. Re-enter or migrate LLM API keys and custom secret values unless a migration helper is added.
  3. Recreate old Local GUI LLM profiles in Agent Canvas, except for the single auto-created profile described below.
  4. Recreate git provider tokens / repository integrations; old provider_tokens are ignored by the local agent-server used by Agent Canvas.
  5. Review app preferences (language, analytics consent, sound notifications, git identity), disabled skills, search/Tavily setup, workspace paths, and conversation history.

Verified persistence behavior

OpenHands OSS Local GUI persistence

OpenHands Local GUI stores durable single-user state through the app-server file store:

  • Persistence directory selection: OH_PERSISTENCE_DIR -> FILE_STORE_PATH -> ~/.openhands
    • OpenHands/openhands/app_server/config.py
  • Settings file: settings.json
    • OpenHands/openhands/app_server/settings/file_settings_store.py
  • Secrets file: secrets.json
    • OpenHands/openhands/app_server/secrets/file_secrets_store.py
  • Docker compose mounts host ~/.openhands into the app container.
    • OpenHands/docker-compose.yml

The old file stores serialize secrets in plaintext by passing context={'expose_secrets': True}.

Agent Canvas / agent-server persistence

Agent Canvas launches openhands-agent-server version 1.24.0 by default:

  • Version source of truth: agent-canvas/config/defaults.json
  • Dev/npm launcher sets OH_PERSISTENCE_DIR to the parent of ~/.openhands/agent-canvas, i.e. ~/.openhands.
    • agent-canvas/scripts/dev-safe.mjs
  • Docker entrypoint sets OH_PERSISTENCE_DIR=${HOME}/.openhands and stores Agent Canvas conversations/bash events under ~/.openhands/agent-canvas/....
    • agent-canvas/docker/entrypoint.sh
  • Agent Canvas always configures an OH_SECRET_KEY in the normal launcher paths: generated/persisted in ~/.openhands/agent-canvas/secret-key.txt unless the user supplies one.
    • agent-canvas/scripts/dev-safe.mjs
    • agent-canvas/docker/entrypoint.sh

This means Agent Canvas points at the old Local GUI settings.json / secrets.json files by default, but the new agent-server model only imports the fields listed below.

Data compatibility matrix

Old Local GUI data Verified Agent Canvas behavior Source evidence
settings.json.agent_settings Reused. The agent-server persisted settings model includes agent_settings; SDK migrations accept older agent settings, add agent_kind, canonicalize legacy agent_kind: "llm" to "openhands", and drop deprecated verification fields moved to conversation settings. software-agent-sdk/openhands-agent-server/openhands/agent_server/persistence/models.py; software-agent-sdk/openhands-sdk/openhands/sdk/settings/model.py
LLM API key inside agent_settings.llm.api_key Not reused under default Agent Canvas launch when the old value is plaintext. The new server loads settings with a cipher because OH_SECRET_KEY is configured. validate_secret() attempts Fernet decrypt and returns None on plaintext/non-decryptable values. software-agent-sdk/openhands-sdk/openhands/sdk/utils/pydantic_secrets.py; software-agent-sdk/openhands-sdk/openhands/sdk/utils/cipher.py; agent-canvas/scripts/dev-safe.mjs
settings.json.conversation_settings Reused. The persisted model includes conversation_settings; SDK migration v0 -> v1 is applied. software-agent-sdk/openhands-agent-server/openhands/agent_server/persistence/models.py; software-agent-sdk/openhands-sdk/openhands/sdk/settings/model.py
settings.json.llm_profiles Not imported. Agent-server PersistedSettings has schema_version, agent_settings, conversation_settings, and active_profile; it does not have llm_profiles. Pydantic ignores old extra top-level fields. software-agent-sdk/openhands-agent-server/openhands/agent_server/persistence/models.py
Legacy single default LLM profile Conditionally auto-created in the new profile store when /api/profiles is listed and no profile files exist, but only if settings.llm_api_key_is_set is true after settings load. With old plaintext API keys plus default Agent Canvas OH_SECRET_KEY, that condition is false. software-agent-sdk/openhands-agent-server/openhands/agent_server/profiles_router.py
New Agent Canvas LLM profiles Stored as separate JSON files under ~/.openhands/profiles/*.json, not embedded in settings.json. Profile names must match ^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$. software-agent-sdk/openhands-sdk/openhands/sdk/llm/llm_profile_store.py
secrets.json.custom_secrets names/descriptions Loaded into the new Secrets model if the JSON shape is {custom_secrets: {NAME: {secret, description}}} or {custom_secrets: {NAME: "value"}}. software-agent-sdk/openhands-agent-server/openhands/agent_server/persistence/models.py
secrets.json.custom_secrets.*.secret plaintext values Not usable under default Agent Canvas launch for the same reason as LLM API keys: OH_SECRET_KEY is configured, validate_secret() tries to decrypt, and plaintext values become None. Listing still returns names/descriptions; value lookup returns 404 when the loaded secret value is None. software-agent-sdk/openhands-agent-server/openhands/agent_server/persistence/models.py; software-agent-sdk/openhands-agent-server/openhands/agent_server/persistence/store.py; software-agent-sdk/openhands-agent-server/openhands/agent_server/settings_router.py
secrets.json.provider_tokens Ignored by the local agent-server. The new Secrets model explicitly stores custom secrets only and comments that it does not store provider tokens because the agent-server does not integrate with OAuth providers directly. software-agent-sdk/openhands-agent-server/openhands/agent_server/persistence/models.py
settings.json.secrets_store.provider_tokens legacy field Ignored by Agent Canvas / agent-server. Old OpenHands app-server migrated this field into old secrets.json.provider_tokens; the new agent-server does not read secrets_store and does not read provider tokens. OpenHands/openhands/app_server/settings/settings_router.py; software-agent-sdk/openhands-agent-server/openhands/agent_server/persistence/models.py
Top-level old settings: language, enable_sound_notifications, user_consents_to_analytics, git_user_name, git_user_email Not reused from old settings.json. Agent Canvas persists these locally in browser localStorage key openhands-agent-server-app-preferences because local /api/settings only persists nested agent/conversation diffs. agent-canvas/src/api/app-preferences-store.ts; agent-canvas/src/api/settings-service/settings-service.api.ts
disabled_skills Not reused from old settings.json. Agent Canvas stores local disabled skills in browser localStorage key openhands-agent-server-disabled-skills. agent-canvas/src/api/settings-service/settings-service.api.ts
search_api_key, sandbox_api_key, max_budget_per_task, remote_runtime_resource_factor, sandbox_grouping_strategy, email fields Not reused by local Agent Canvas because the local agent-server persisted model does not include these top-level old app-server fields and Agent Canvas local settings transform only derives fields from agent_settings and conversation_settings. software-agent-sdk/openhands-agent-server/openhands/agent_server/persistence/models.py; agent-canvas/src/api/settings-service/settings-service.api.ts
Old Local GUI conversation history and metadata Not automatically listed/imported by Agent Canvas. Old app-server event files use v1_conversations/{conversation_id} and SQL-backed app conversation metadata; Agent Canvas agent-server uses its own OH_CONVERSATIONS_PATH, defaulting to ~/.openhands/agent-canvas/conversations in launchers. OpenHands/openhands/app_server/event/event_service_base.py; OpenHands/openhands/app_server/conversation_paths.py; agent-canvas/scripts/dev-safe.mjs; agent-canvas/docker/entrypoint.sh
config.toml Not read by Agent Canvas or openhands-agent-server. Repository search finds no runtime TOML config loader in Agent Canvas or agent-server; old OpenHands docs describe config.toml setup mainly for headless/CLI defaults. agent-canvas/; software-agent-sdk/openhands-agent-server/; OpenHands/Development.md

Environment-variable mapping

OpenHands Local GUI env/config Agent Canvas equivalent / status
OH_PERSISTENCE_DIR Still honored by openhands-agent-server. Agent Canvas defaults it to ~/.openhands.
FILE_STORE_PATH Old Local GUI fallback only. Use OH_PERSISTENCE_DIR for Agent Canvas.
SESSION_API_KEY Agent-server still supports this as a legacy fallback, but Agent Canvas launchers use user-facing LOCAL_BACKEND_API_KEY and pass it to the server as OH_SESSION_API_KEYS_0.
VITE_BACKEND_BASE_URL="localhost:3000" Agent Canvas normal entry point is http://localhost:8000; frontend-only/dev setups use VITE_BACKEND_BASE_URL pointed at the active agent-server/ingress URL.
VITE_BACKEND_HOST="127.0.0.1:3000" Agent Canvas Vite proxy defaults to 127.0.0.1:8000.
WORKSPACE_BASE, workspace_base in config.toml Agent Canvas uses VITE_WORKING_DIR, stored local workspaces, per-conversation working dirs, and Docker /projects mounts.
RUNTIME=local/process/remote, SANDBOX_*, AGENT_SERVER_IMAGE_* These are old app-server sandbox orchestration knobs. Agent Canvas talks directly to openhands-agent-server; npm/local mode runs without a sandbox, Docker mode runs the all-in-one container, and custom agent-server versions are selected with OH_AGENT_SERVER_LOCAL_PATH, OH_AGENT_SERVER_GIT_REF, or OH_AGENT_SERVER_VERSION.
OPENHANDS_PROVIDER_BASE_URL, LLM_BASE_URL Agent Canvas primary user path is LLM Profiles in the UI. The direct SDK default model remains gpt-5.5, but Agent Canvas explicitly sends its own frontend default when no model is configured.
TAVILY_API_KEY / SEARCH_API_KEY Old OpenHands app-server had a Tavily MCP proxy path. Agent Canvas exposes MCP through the /mcp page and marketplace entries; Tavily is configured as a regular MCP server entry.
VITE_ENABLE_BROWSER_TOOLS Agent Canvas-specific. Set to false to omit browser_tool_set from new conversation payloads.
VITE_LOAD_PUBLIC_SKILLS Agent Canvas-specific. Defaults to enabled; set to false to stop loading public skills from OpenHands/extensions.
LOCAL_BACKEND_API_KEY Agent Canvas user-facing API key variable. Required in --public mode; auto-generated/persisted in local mode when unset.
OH_SECRET_KEY Critical in Agent Canvas. Generated/persisted by default. Also causes old plaintext secret fields to fail decryption unless a migration/import path handles them.

Launch and behavior changes users see

Old OpenHands Local GUI

  • Source/dev: make run
  • Backend: 127.0.0.1:3000
  • Frontend: 127.0.0.1:3001
  • Docker: make docker-run, compose exposes 3000
  • Default runtime orchestration is the OpenHands app-server managing sandboxed agent-server instances

Agent Canvas

  • npm/global: npm install -g @openhands/agent-canvas then agent-canvas
  • Source/dev: npm run dev
  • Main entry point: http://localhost:8000/
  • Full stack defaults: ingress 8000, agent-server 18000, automation backend 18001, Vite 3001 in dev
  • Partial modes: agent-canvas --frontend-only, agent-canvas --backend-only
  • Docker all-in-one image exposes 8000, persists under ~/.openhands, and expects project folders mounted at /projects

Additional changed behavior

  • Agent Canvas is a port of the OpenHands frontend that talks directly to openhands-agent-server / software-agent-sdk, not the full OpenHands app backend.
  • Hosted/account/org management UI is removed or hidden in the OSS Agent Canvas path.
  • Agent Canvas local mode auto-generates and injects a session API key. Public mode (--public) requires LOCAL_BACKEND_API_KEY and prompts the browser user for it.
  • OpenHands frontend default model in the inspected repo is openhands/claude-opus-4-5-20251101; Agent Canvas frontend default is openhands/minimax-m2.7; SDK/agent-server direct default is gpt-5.5.
  • Agent Canvas npm/local mode runs without a sandbox and has host filesystem access. Docker mode is the isolated path documented in the README.
  • Agent Canvas full stack includes the automation backend by default.
  • Agent Canvas has a top-level /mcp page and marketplace data from @openhands/extensions; local install filters out OAuth-only marketplace options.
  • Terminal tab is a read-only transcript of agent events, not an interactive shell.
  • Browser tab is screenshot/URL state from browser-tool events, not a full manually-driven browser UI.
  • Agent Canvas adds the canvas_ui tool and conditionally includes browser_tool_set / task_tool_set based on env, server tool metadata, and the sub-agent setting.
  • Local LLM profile switching and ACP model switching are local-backend features; cloud repository/search calls use the cloud proxy path.

Required migration work

  • Add a migration guide: "Migrating from OpenHands Local GUI to Agent Canvas".
  • Add a backup-first step for ~/.openhands.
  • Document that old plaintext LLM API keys and custom secret values are not reused under the default generated OH_SECRET_KEY flow.
  • Provide a one-time migration/import path for plaintext old secrets into encrypted agent-server storage, or explicitly require users to re-enter LLM API keys and custom secrets.
  • Provide a one-time importer for old embedded llm_profiles into ~/.openhands/profiles/*.json, or explicitly require users to recreate profiles.
  • Document that old provider_tokens are not consumed by local Agent Canvas and provide the replacement workflow for repo/git access.
  • Document app preferences and disabled skills as browser-local Agent Canvas settings that do not import from old settings.json.
  • Document the env-var mapping table above.
  • Document changed launch commands, ports, workspace behavior, sandbox/security model, default model, MCP/Tavily setup, and automation availability.
  • State that old conversation history is not automatically migrated/listed.
  • Add a fixture-based regression test with an old-style settings.json and secrets.json to lock the chosen migration behavior.

Suggested implementation approach

  1. Build a migration checker that runs before or during first Agent Canvas startup when ~/.openhands/settings.json or ~/.openhands/secrets.json exists.
  2. Detect old app-server fields:
    • llm_profiles
    • plaintext agent_settings.llm secret fields
    • secrets.json.custom_secrets plaintext secret fields
    • secrets.json.provider_tokens
    • app preference fields
    • disabled_skills
  3. For sensitive fields, import through agent-server APIs with plaintext exposure limited to local startup code, then save back through the new encrypted stores.
  4. Write imported LLM profiles through /api/profiles/{name} so files land in ~/.openhands/profiles/*.json with the current profile-store validation rules.
  5. Leave old files backed up or write a migration marker; do not silently overwrite old files with partial data.

贡献者指南