Skip to content

[Bug]: Desktop/TUI cannot persist an explicit zero-tool state; empty toolsets fail open #82010

Description

@Ramibynow

Bug description

Hermes Desktop/TUI on a hosted Hermes 0.20.0 runtime cannot represent a durable, explicit zero-model-tool state through supported configuration.

This is security-sensitive because an administrator can persist and read back empty tool configuration while a genuinely fresh Desktop session still exposes the default tool catalog.

Reproduction

Persist configuration equivalent to:

toolsets: []
platform_toolsets:
  desktop: []
  cli: []
tools:
  tool_search:
    enabled: false

Also disable all selectable skills and MCP servers, then construct a genuinely fresh Desktop/TUI session and inspect the live agent through session-aware tools.show(session_id) plus session.info.tools.

Observed on Hermes 0.20.0:

Persisted/effective toolsets: []
Enabled selectable skills: 0
MCP servers: 0
Fresh live-agent tools: 47

No model prompt is required to reproduce the exposure.

Source-level cause

tui_gateway.server._load_enabled_toolsets() currently follows this pattern after loading configured CLI toolsets:

enabled = _get_platform_tools(cfg, "cli", include_default_mcp_servers=True)
if not enabled:
    return None
return sorted(enabled | _gui_surface_toolsets(session_platform))

An explicit empty configuration is therefore converted to None, which downstream means default/unrestricted selection. A non-empty minimal configuration is not an equivalent workaround because _gui_surface_toolsets() injects project, and for Desktop also desktop_ui.

agent.disabled_toolsets is also not currently forwarded by the Desktop/TUI gateway. PR #44505 addresses that separate propagation gap but remains open.

Process override is not a durable hosted workaround

HERMES_TUI_TOOLSETS=context_engine can produce zero schemas because context_engine is a valid non-empty toolset that currently resolves to no model tools and returns before GUI-surface injection.

On a hosted runtime, however, persisting that value through the dashboard environment API and invoking reload.env produced zero tools only on the worker handling that RPC. A later independent WebSocket/session exposed 47 tools. A full instance Stop → Start preserved the on-disk value but the first independent post-restart session still exposed 47 tools.

This shows that a worker-local process override is not a durable replacement for an explicit configuration state in a multi-worker hosted deployment.

Expected behavior

Hermes should provide one supported, restart-durable configuration representation for zero model-callable tools, with fail-closed semantics across Desktop/TUI workers.

Acceptable designs include:

  1. preserve explicit empty selection as [] rather than converting it to None;
  2. add an explicit agent.disable_all_tools: true setting; or
  3. make agent.disabled_toolsets effective across every Desktop/TUI agent-construction path and capable of suppressing automatic GUI surfaces.

Automatic project/desktop_ui injection must not override an explicit zero-tool state.

Acceptance criteria

  • Persisted explicit zero state survives process and instance restart.
  • Three independently constructed Desktop/TUI WebSocket sessions each report:
    • tools.show.total == 0
    • tools.show.sections == []
    • zero names in session.info.tools
  • Zero state remains zero with no skills and no MCP servers.
  • Missing configuration retains current defaults for backward compatibility.
  • Invalid toolset names fail closed or produce a blocking configuration error; they must not silently enable defaults.
  • Add request-level regression coverage for main session creation, tools.show, background/preview agents, and MCP reload.

Environment

  • Hermes Agent: 0.20.0
  • Surface: Hermes Desktop connected to a hosted dashboard/TUI gateway
  • Hosted instance identity and credentials intentionally omitted

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Medium — degraded but workaround existsarea/configConfig system, migrations, profilescomp/desktopElectron desktop app (apps/desktop/*)comp/tuiTerminal UI (ui-tui/ + tui_gateway/)sweeper:risk-compatibilitySweeper risk: may break existing users, config, migrations, defaults, or upgradestype/bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions