nesquena/hermes-webui

bug(commands): /btw and /background sent as chat text when typed mid-turn — missing from busy-path slash intercept allowlist

Open

#6,597 opened on Jul 29, 2026

 (1 comment) (0 reactions) (0 assignees)Python (2,386 forks)github user discovery
bugcommandshelp wantedsprint-candidate

Repository metrics

Stars
 (17,368 stars)
PR merge metrics
 (Avg merge 14h 31m) (314 merged PRs in 30d)

Description

Summary

/btw and /background work correctly when the agent is idle, but typing them while a turn is running sends them through as chat text instead of executing the intended command. Since their primary value is exactly mid-task (/btw for a quick side lookup, /background for parallel work), that's the case that's broken.

Steps to reproduce

  1. Start a long-running agent task.
  2. While it's running (S.busy), type /btw what is the capital of France and press Enter.
  3. Instead of an ephemeral side-question bubble, the raw text "/btw what is the capital of France" gets steered into the active agent, or queued, or causes an interrupt — depending on defaultMessageMode.
  4. Repeat with /background. Same misrouting.

(When idle, both commands execute correctly — the bug is busy-only.)

Root cause

Both commands are registered client-side (static/commands.js:29-30cmdBtw, cmdBackground, both noEcho:true) and intercepted correctly on the idle send path at static/messages.js:1428. But when the composer submits while S.busy is true, the code returns early at the busy block (messages.js:1356-1376), before reaching the idle intercept.

The busy block has its own narrow allowlist of commands that bypass defaultMessageMode routing:

// static/messages.js:1368
if(_pc&&['steer','interrupt','queue','terminal','goal','yolo'].includes(_pc.name)){

btw and background are not in this list, so they fall through to defaultMessageMode behaviour and get treated as plain chat text.

Why both handlers are safe to call mid-turn

Both cmdBtw (commands.js:1727-1741) and cmdBackground (commands.js:1742-1755) are fully self-contained:

  • They only read S.session.session_id — they do not read S.busy, S.activeStreamId, or any agent-running state.
  • They call their own dedicated API endpoints (POST /api/btw, POST /api/background).
  • They connect to independent SSE streams / polling loops that do not share or interfere with the main session's active stream.
  • The /btw answer renders in a dedicated ephemeral bubble (.msg-row-btw), not the main message list.
  • The /background result surfaces via a composer badge + polling, then appends a _background-tagged message.

Previous precedent — Issue #4117

The same bug was reported for /yolo, fixed in v0.51.393 by adding yolo to this same allowlist (#4117). /btw and /background were simply overlooked.

Suggested fix

One-line addition in static/messages.js:1368:

// Current:
if(_pc&&['steer','interrupt','queue','terminal','goal','yolo'].includes(_pc.name)){

// Should be:
if(_pc&&['steer','interrupt','queue','terminal','goal','yolo','btw','background'].includes(_pc.name)){

Front-end only. No backend changes needed.

Scope

  • Repo: nesquena/hermes-webui
  • File: static/messages.js (~L1368)
  • Risk: low — one-line allowlist addition; both handlers are idempotent and session-scoped

Contributor guide