openhands changelog¶
0.10.0¶
Released 2026-10-26.
Changes¶
The whole home directory persists¶
/home/openhands now lives on the data volume (subdirectory home), so CLI
logins, MCP OAuth tokens, tool configuration in ~/.config and ~/.local and
caches survive a restart. ~/.openhands and ~/workspace stay in their own
subdirectories, mounted inside the home, so existing settings, conversations
and work trees need no migration. ~/.claude is now part of the home
subdirectory instead of a subdirectory claude of its own. A new init
container, seed-home, copies the files the image ships in its home
(.bashrc, .profile, .bash_logout) into the volume when they are missing
and never overwrites one. Caches such as ~/.cache/uv grow on the volume.
MCP servers that each user logs in to with OAuth¶
A RemoteMCPServer annotated openhands.dev/auth: oauth2 becomes an MCP server
that each user authorizes in the browser, for example a vendor's hosted MCP
server for mail or calendars. The entry uses the server's own URL and the
pre-registered OAuth client in the Secret named by openhands.dev/oauth-client
(keys client_id and client_secret), with the scopes of
openhands.dev/oauth-scopes. Without openhands.dev/oauth-client the agent
registers itself at the server (dynamic client registration). It appears switched off under Settings > MCP: open
it, authorize it, switch it on. The agent keeps the tokens encrypted in its
settings and refreshes them; a later change of the client id, the scopes or the
Secret is written to the entry without logging the user out.
Add-on MCP servers by bundle or name¶
A RemoteMCPServer labelled mcp.openshift.eu/addon: "true" reaches the agent
only when its mcp.openshift.eu/bundle is in mcp.bundles or its
mcp.openshift.eu/server is in mcp.servers, for example
mcp.bundles: [google-workspace]. The mcp-* charts of this repository stamp
these labels. Servers without the add-on label are discovered as before.
mcp.labelDomain changes the prefix.
Google issues a refresh token¶
An authorization request to accounts.google.com asks for offline access, so a
Google login keeps working after the first hour. This needs build.enabled.
mcpDiscovery is now mcp¶
The values under mcpDiscovery moved to mcp. mcpDiscovery is still read in
this version and its keys override mcp.
Upgrade¶
Move any values under mcpDiscovery to mcp; the next minor version stops
reading mcpDiscovery. List the add-on bundles or servers an agent should get
in mcp.bundles or mcp.servers. The upgrade rebuilds the image and restarts the
pod once. What the tools kept in the home outside ~/.openhands and
~/workspace before the upgrade (CLI logins, ~/.config, caches) was not on the
volume and starts empty once; log in to the CLIs again.
0.9.6¶
Released 2026-10-26.
Changes¶
Google Workspace, Microsoft 365 and Azure CLIs in the image¶
The image the chart builds now carries gws (Google Workspace CLI 0.22.5),
m365 (CLI for Microsoft 365 11.11.0) and az (Azure CLI 2.91.0), next to
aws (AWS CLI v2, a Debian package) that it already had. They are entries of
build.tools at pinned releases, and the build runs each of them once and fails
when one does not start.
build.tools takes two new kinds for them: venv installs a requirement with
pip into its own environment under /opt/venv, and tarball installs a
binary from a release archive after checking the archive against its SHA-256
digest.
The image holds no credential for these CLIs. Log in from the agent's terminal:
gws auth login, m365 setup once and then m365 login, aws configure sso,
az login --use-device-code. The login is kept in the container, outside the
data volume: after a pod restart, log in again.
The image grows by about 700 MB, mostly the Azure CLI and the CLI for Microsoft 365.
Upgrade¶
Nothing to do. If you set build.tools yourself, add the three entries from
the chart's values.yaml to get the new CLIs. The upgrade starts a new image
build, and the pod restarts on the new image when it is done.
0.9.5¶
Released 2026-10-26.
Changes¶
Claude Code conversations survive a restart¶
Claude Code keeps its session store in ~/.claude, which was not on the data
volume. After every pod restart it could not resume an open conversation and
started a fresh session with only a replay of the history. The chart now mounts
~/.claude from the data volume (subdirectory claude), next to settings and
~/workspace. Sessions started before the upgrade are not recovered; new ones
persist. The upgrade restarts the pod once.
0.9.4¶
Released 2026-10-25.
Changes¶
MCP servers of every Project the agent may see¶
MCP discovery lists the OpenShift Projects the agent's ServiceAccount may see
and the RemoteMCPServers in each, besides its own namespace. A namespace that
refuses the list is skipped, so Kubernetes RBAC on the namespace decides which
servers an agent sees: a platform that grants an agent read access to
RemoteMCPServers and get on the namespace in another namespace makes that
namespace's servers appear. A name that also exists in the own namespace becomes
0.9.3¶
Released 2026-10-25.
Changes¶
Room for an agent at work¶
The agent-canvas container now requests 250m CPU and 2Gi and is limited to 4 CPU and 16Gi, so a busy agent is neither killed for memory nor throttled hard. The sizes follow measured usage of the agents on the platform with generous headroom. The proxy sidecars may use 256Mi instead of 128Mi.
0.9.2¶
Released 2026-10-25.
Changes¶
Token proxy: agent identity through the tenant realm¶
The token proxy copy follows images/agent-identity/token-proxy.py. With AGENT_TOKEN_VIA_URL set, the agent first gets a token from its tenant's own realm with its ServiceAccount token, and that token is the client assertion for the shared realm. Without the variable nothing changes.
0.9.1¶
Released 2026-10-25.
Fixes¶
Claude Code ends its session after the first turn¶
Through a gateway that streams no token usage (an OpenAI-compatible backend behind an Anthropic-format endpoint), the Claude ACP adapter failed with "Cannot read properties of undefined (reading 'input_tokens')" and every later message answered "The Claude Agent session has ended". The image build patches the adapter so missing usage counts as zero.
Upgrade¶
The image is rebuilt on upgrade.
0.9.0¶
Released 2026-10-25.
Changes¶
Every gateway model under Settings > LLM¶
llm.gatewayModels (default true) adds a profile for every model the gateway
lists at /v1/models, on every pod start. Profiles that exist, also those a user
edited, are left as they are; the active profile does not change. Before, only
llm.model and llm.models were offered. Set it to false to keep that list.
0.8.0¶
Released 2026-10-25.
Changes¶
Apps of a team¶
team and tenant put every object of the chart into <tenant>-<team>, the
namespace of the tenant's team, so an app ordered for a team runs next to the
team's agents and MCP servers. Without team the chart renders into the release
namespace as before.
0.7.0¶
Released 2026-10-25.
Changes¶
The agent's own token for MCP servers¶
The token proxy can carry the agent's own OpenID Connect token on MCP calls. With tokenProxy.agentToken.tokenUrl set, calls under tokenProxy.agentToken.paths (default /mcp) get a token from a client_credentials grant at that endpoint, authenticated with a short-lived ServiceAccount token for tokenProxy.agentToken.audience (federated client authentication). No secret is stored; the token is kept until shortly before it expires. Model calls keep the ServiceAccount token. serviceAccount.labels puts labels on the ServiceAccount, for example the one a platform uses to register it as a client of the realm.
Upgrade¶
Nothing changes until tokenProxy.agentToken.tokenUrl is set. The pod restarts once, because the token proxy script changed.
0.6.2¶
Released 2026-10-25.
Changes¶
Documents and diagrams¶
The image gains a toolset for architecture work: LibreOffice without GUI (soffice: Word, PowerPoint, Excel, Visio import, PDF export), pandoc, graphviz, plantuml with nwdiag network diagrams, rsvg-convert, ImageMagick and mermaid-cli (mmdc, on the image's Chromium), plus markitdown, python-docx, docxtpl, python-pptx, openpyxl, vsdx and diagrams from PyPI. The build renders a Word file to PDF and a Mermaid, an nwdiag and a diagrams picture to prove they work.
soffice is a wrapper that puts LibreOffice's program directory first in LD_LIBRARY_PATH: the base image's LD_LIBRARY_PATH otherwise resolves the UNO libraries outside their $ORIGIN runpath and LibreOffice does not start.
Skill marketplaces¶
skills.marketplaces registers skill marketplaces in Claude Code or
OpenHands plugin format, for example github:
No leftover profile default¶
The seed moves agent profiles that still use the LLM profile default to the active profile before it removes default; 0.6.0 and 0.6.1 left it in place because the delete was refused while the agent profile default used it.
Wispr Flow icon¶
The wispr-flow MCP server shows its logo.
Upgrade¶
A new image builds on the next sync. The image is larger by about 600 MB (LibreOffice and fonts).
0.6.1¶
Released 2026-10-25.
Changes¶
Icons on installed MCP servers¶
Agent Canvas 1.33 draws a logo on an installed MCP server only when its URL equals an entry of the Library, and drops the icon of the server's settings. Servers behind the token proxy never match, so every card showed the generic symbol. The image build now patches the frontend to keep the icon and show it when no Library entry matches; the build fails when the frontend no longer has the expected shape.
Icons come from the RemoteMCPServer annotation openhands.dev/icon, from a list of known names (now with kagent-tools, librenms, memory, netbox, kubernetes, bitwarden and others, and a working netbox logo), from the new icon field of mcpServers, and the Kubernetes logo for the built-in kubernetes server.
Upgrade¶
A new image builds on the next sync; an instance with build.enabled false keeps its image.
0.6.0¶
Released 2026-10-24.
Changes¶
The gateway is a provider under Settings > LLM¶
Agent Canvas 1.33 lists models as profiles of a provider connection. The chart only wrote the plain model settings, so Settings > LLM showed no provider. With gateway.upstream set, the seed now creates the provider connection llm.connection.name (default Gateway) to the token proxy, one profile per model in llm.model and llm.models, and activates the profile of llm.model. The profile default that earlier versions left without a connection is removed.
SHELL and the rest of the opencode-agent toolset¶
The image sets SHELL=/bin/bash, which Claude Code needs for its Bash tool. The build adds ripgrep, xxd, vi, lsof, psmisc, procps, iproute2, ping, traceroute, whois, bc, dos2unix, gnupg, sysstat, cpio and file from Debian, and ruff from PyPI, so the image carries what the opencode-agent image has. opencode itself stays out: its build is for musl.
Upgrade¶
A new image builds on the next sync. The pod restarts because the seeded values change, and the seed adds the connection and profiles to the existing settings. An instance with build.enabled false keeps its image: point image.tag at a 0.6.0 build to get the tools.
0.5.0¶
Released 2026-10-24.
Changes¶
A2A server, one agent per conversation¶
A new sidecar makes the agent an A2A server, so other agents and kagent
can chat with it. Every A2A context becomes its own conversation, and
every titled conversation started in the UI is also a sub-agent named
Listed in kagent¶
With kagent installed the chart registers a BYO Agent named like the release. kagent runs it as a small relay pod in front of the sidecar, because the agent-server listens on loopback only. Set a2a.tenantAuth.oidcIssuers to the realm kagent logs users in with, or kagent's chats get 401.
0.4.0¶
Released 2026-10-24.
Changes¶
openhands 0.4.0 publishes UI MCP servers to the team (#42)¶
A remote MCP server a user adds in the OpenHands UI now becomes an AgentgatewayBackend of the project, with the headers OpenHands would send in a Secret owned by the backend. The platform turns it into a gateway endpoint and a RemoteMCPServer, so every agent of the team discovers it; removing it in the UI removes the backend. OAuth, in-pod and local servers stay personal, and the platform's admission policy decides which hosts a project may reach. The UI entry's description shows the outcome.
0.3.0¶
Released 2026-10-24.
Changes¶
openhands 0.3.0: Agent Canvas 1.33.0, OAuth MCP redirect to the route (#38)¶
Agent Canvas 1.33.0 ships agent-server 1.58.1 and automation 1.25.1. The settings, MCP, secrets and agent-profile endpoints the seed and mcp-sync scripts call are unchanged, and the entrypoint still carries the two STATIC_SERVER_BIND_HOST lines the build rewrites to loopback, so the Containerfile and scripts need no change.
The upstream entrypoint now defaults LOG_LEVEL to WARNING, which only quiets the backends' startup output.
OpenHands registers http://localhost:
mcp-sync also gives discovered servers an icon: annotation openhands.dev/icon on the RemoteMCPServer, else the logo of a known name such as gitlab or grafana.
0.2.0¶
Released 2026-10-23.
Changes¶
openhands 0.2.0 discovers RemoteMCPServers (#37)¶
Sidecar mcp-sync turns every kagent RemoteMCPServer of the project into an MCP server of the agent and keeps the list in step: gateway URLs go through the token proxy, servers that need Secret headers are skipped, entries a user made are left alone. It also writes the git token as GITLAB_TOKEN into the secrets store, which is what turns on the UI's git provider features.
The ClusterRole that reads RemoteMCPServers belongs to kagent, which owns the CRD; the chart only binds it (mcpDiscovery.clusterRole, default kagent-remotemcpserver-view) in its own namespace.
0.1.3¶
Released 2026-10-22.
Changes¶
Bind login groups to a ClusterRole¶
Kubernetes refuses a Role that grants permissions the creator does not
hold. A project admin, and the project's Argo CD with admin, do not hold
the verb login, so the group lockdown of 0.1.2, 0.3.5 and 0.2.1 failed
to sync for them ("attempting to grant RBAC permissions not currently
held"). oauth.loginClusterRole names a ClusterRole holding that verb;
allowedGroups are bound to it in a RoleBinding
0.1.2¶
Released 2026-10-22.
Changes¶
openhands 0.1.2 (Agent Canvas 1.30.0), owner or group login lockdown (#34)¶
Agent Canvas 1.30.0 binds the frontend through STATIC_SERVER_BIND_HOST instead of a literal --host ::, so the loopback patch rewrites both assignments (the build still asserts two hits). The volume claim template drops the version label: Kubernetes refuses any change there, so every appVersion bump failed the StatefulSet update. A cookie secret that is not 16, 24 or 32 characters long is hashed to 32, as in opencode-agent and openwebui, so a 48-character generated value works.
opencode-agent 0.3.5 and openwebui 0.2.1: with neither oauth.ownerEmail nor person.email set, the login proxy drops the emails file and admits everyone who may get services/proxy on the UI Service, which admin and edit grant. A team instance from a managed Template needs no e-mail. Open WebUI then allows sign-up with role user; the first user is admin. With an owner set the render is unchanged.
Every chart now offers two lockdowns. oauth.ownerEmail admits that one user (emails file). oauth.allowedGroups admits only members of those groups: the login Role grants the verb login on services/proxy of the UI Service and the login proxy checks that verb. The previous check, get on services/proxy, is also held by admin and edit, so any project editor passed a group lockdown. With neither set, project editors log in. openhands gains oauth.ownerEmail.
Verified on berry-ai with the authorization.openshift.io SAR the proxy sends: a grncloud-engineering member is allowed login, a grncloud-admins project admin and an outsider are refused, the same admin is allowed get.
The group lockdown checks the verb login, which only the login Role grants; the tests asserted the previous verb get.
0.1.1¶
Released 2026-10-22.
Changes¶
openhands 0.1.1 preconfigures agents¶
The first-run wizard asked for an LLM and overwrote the seeded model with openai/gpt-5.6-sol; the image now marks it done in the page (the frontend's only condition is localStorage openhands-onboarded).
agentSecrets seeds the environment of the ACP agents into the agent-server secrets store, so Claude Code and Codex no longer ask for keys and base URLs; agentProfiles seeds selectable ACP agent profiles.
Verified on berry-ai (sam-10x): fresh browser opens without wizard; Claude Code answers through /anthropic on the gateway; Codex answers with a provider config that turns off its WebSocket transport.
0.1.0¶
Released 2026-10-22.
Changes¶
Add openhands 0.1.0 chart (#30)¶
Shared OpenHands Agent Canvas behind an OpenShift login. One StatefulSet runs agent-canvas, oauth-proxy and a token proxy that sends the pod's ServiceAccount token to an OpenAI-compatible gateway for models and MCP.
The upstream chart cannot carry sidecars and pins UID 10001, which restricted-v2 rejects. This chart builds the upstream image with an OpenShift toolset, runs it with an arbitrary UID, keeps the session key out of the page, seeds model and MCP settings through the agent-server API once per value change, and admits only groups that hold create on services/proxy (cluster-reader holds get).
Verified live on berry-ai as release sam-10x: restricted-v2, login redirect, completion through the gateway, MCP tools listed, restart keeps conversations and settings.
build.toolsImage copies every binary of an image such as opencode-agent (its /usr/local/bin except OpenCode, Go toolchain, /tools, sonar-scanner and Ansible collections), so both agents carry the same CLI versions. Python and npm tools are tied to that image's Alpine runtimes and are reinstalled on Debian at pinned versions from build.tools; the build runs one check per tool as a non-root UID and fails on any miss.
kubernetesMcpServer adds the local stdio MCP server the opencode agents use. The agent-server starts stdio servers with a reduced environment, so the seed hook hands KUBERNETES_SERVICE_HOST and _PORT through passEnv. mcpServers entries take enabled, because the agent-server lists all servers within one 30 s budget and one slow server drops them all.
The login check is back to get on services/proxy: cluster-reader does not hold it; the earlier switch to create rested on a malformed test.
Verified live on berry-ai as sam-10x: every tool check passes, kubernetes and public MCP tools work in a UI conversation, PDF upload and parsing work in the UI.
A new browser met "No backend configured" and had to paste the session API key: the upstream entrypoint binds the frontend to ::, and then it does not embed the key. The image now rewrites that flag to 127.0.0.1 (the build fails when the upstream text is not found). On loopback the frontend embeds the key, so a logged-in browser gets a connected backend, and only oauth-proxy in the pod can fetch that page.
The agent-server also listens on 127.0.0.1, so the probes run curl in the container. Verified on berry-ai: neighbour pod sees 8000 and 18000 refused; fresh browser opens without a backend prompt and chats.