* fix(title): honor auxiliary.title_generation.enabled=false in WebUI title paths (#6814) Hermes Agent gates title generation on auxiliary.title_generation.enabled (default true), but the WebUI orchestration only used the aux config to pick a model route, so enabled=false still triggered LLM title calls via the active chat model or the aux route, and could persist a fallback title. Add a profile-scoped _aux_title_generation_enabled() helper beside _get_aux_title_config() with the same default/truthy semantics as the Agent (boolean and string forms). Gate three automatic paths on it: - _run_background_title_update(): skip with status skipped / title_generation_disabled, provisional title untouched, no fall-through to the active agent model. - _run_background_title_refresh(): skip with refresh_skipped / title_generation_disabled. - generate_session_title_for_session(): explicit (None, 'title_generation_disabled', '') so manual regenerate returns an explicit disabled response and imported-session auto-titling stays quiet. Checks run inside the profile-scoped worker context so a background job cannot read another profile after a switch. Tests (tests/test_issue6814_title_generation_enabled_gate.py, 20 cases): default-on when omitted, disabled with/without aux route (no LLM call, title untouched, skipped status, stream_end still emitted), string/boolean false forms, adaptive refresh path, manual regenerate explicit response, helper parsing matrix. fail-before: 19 failed on unpatched code. Regression: title family 154 passed (incl. test_2235 routing cases). * docs: document auxiliary.title_generation.enabled behavior (#6814) Addresses the Greptile #6877 review note: document the newly enforced setting and the manual-regenerate disabled response in docs/advanced-chat-setup.md. * fix(title): mirror Hermes agent's canonical is_truthy_value contract exactly Gate review (Codex) found the enabled-parser diverged from the agent's canonical contract: it used a 'disable on false/0/no/off' blocklist, but the agent uses is_truthy_value(value, default=True) — an allowlist (utils.TRUTHY_STRINGS = {1,true,yes,on}). So None wrongly routed through the string branch and empty/ unrecognized strings wrongly stayed ENABLED. Now: None->True (default), bool unchanged, str truthy ONLY for {1,true,yes,on}, else bool(value) — byte-for-byte with agent/title_generator._auto_title_enabled. Test matrix corrected + expanded. Co-authored-by: X-Shihai <X-Shihai@users.noreply.github.com> --------- Co-authored-by: X-Shihai <48356232+xushihai@users.noreply.github.com> Co-authored-by: nesquena-hermes <nesquena-hermes@users.noreply.github.com> Co-authored-by: X-Shihai <X-Shihai@users.noreply.github.com>
5.5 KiB
Advanced chat setup
Two optional features for self-hosted Hermes WebUI deployments. Most users need neither — the defaults (in-process chat, no prefill) work out of the box.
Session recall prefill
WebUI can attach ephemeral prefill messages to new browser-originated agent turns. This is useful when a deployment already has a local recall or router script for Joplin, Obsidian, Notion, llm-wiki, or another third-party notes source and wants browser chat to know where durable context lives.
Prefer a compact router-style prefill (for example, "Joplin has the durable project context; use the available notes/search tools before answering detail-dependent questions") instead of dumping the full note corpus into every new browser session. The prefill should point the agent toward retrieval; the notes/search tools should provide the specific facts on demand.
Static JSON remains supported through prefill_messages_file or
HERMES_PREFILL_MESSAGES_FILE. For dynamic recall, opt in explicitly with a
WebUI-specific script hook:
webui_prefill_messages_script:
- python3
- /path/to/notes_recall.py
webui_prefill_messages_script_timeout: 5
or:
HERMES_WEBUI_PREFILL_MESSAGES_SCRIPT="python3 /path/to/notes_recall.py" \
HERMES_WEBUI_PREFILL_MESSAGES_SCRIPT_TIMEOUT=5 \
./ctl.sh restart
The script may print either an OpenAI-style JSON message list, a JSON object with
a messages list, or plain text; plain text is wrapped as one user prefill
message so dynamic recall text becomes ordinary context instead of an extra
system instruction. If the hook must provide system-level guidance, emit JSON
messages with an explicit role: "system" entry instead. Script output is capped
at 256 KiB before parsing. Parsed prefill context is then bounded by
webui_prefill_context_max_chars or HERMES_WEBUI_PREFILL_CONTEXT_MAX_CHARS
(default: 12,000 characters; set to 0 to disable). When a dynamic script
exceeds the budget and a compact static prefill file is configured, WebUI falls
back to that file. If no compact fallback is available, WebUI injects a short
retrieval instruction instead of sending the oversized note/body payload with
every new browser turn. The browser only receives a compact status event
(source, label, message count, compaction metadata, and redacted errors),
never the prefill message bodies.
Session title generation
Hermes WebUI derives a provisional session title from the first user message and, after the first response, may call an LLM to generate a better title (and periodically refresh it for long sessions).
Automatic title-generation LLM calls honor the active Hermes profile's
auxiliary.title_generation.enabled setting (default: true):
auxiliary:
title_generation:
enabled: false
When disabled:
- the provisional first-message title stays in place and is never replaced or overwritten by an automatic LLM call or local fallback;
- the periodic adaptive refresh is skipped;
- the explicit "regenerate title" action returns a
title_generation_disabledresponse instead of calling a title model.
The WebUI's auto_title_refresh_every setting remains a separate control for
periodic refreshes of already-generated titles; it does not re-enable
automatic generation when the auxiliary flag is off.
Gateway-backed browser chat
By default, browser chat runs through WebUI's in-process legacy runtime. Advanced
self-hosted deployments can opt into routing new browser turns through a running
Hermes Gateway API server while preserving the existing WebUI /api/chat/start
and /api/chat/stream browser contract:
HERMES_WEBUI_CHAT_BACKEND=gateway \
HERMES_WEBUI_GATEWAY_BASE_URL=http://127.0.0.1:8642 \
HERMES_WEBUI_GATEWAY_API_KEY=... \
./ctl.sh restart
Gateway-backed approval prompts need one more explicit opt-in because they use the Gateway runs API path:
HERMES_WEBUI_CHAT_BACKEND=gateway \
HERMES_WEBUI_GATEWAY_BASE_URL=http://127.0.0.1:8642 \
HERMES_WEBUI_GATEWAY_API_KEY=... \
HERMES_WEBUI_GATEWAY_USE_RUNS_API=true \
./ctl.sh restart
Use this when the connected gateway advertises approval support and you want tool approval cards to appear in WebUI. Without HERMES_WEBUI_GATEWAY_USE_RUNS_API=true, gateway chat stays on the legacy chat-completions transport and approval-capable commands can remain pending in the agent without a WebUI approval card.
HERMES_WEBUI_CHAT_BACKEND is intentionally strict: only gateway,
api_server, or api-server enable the bridge. Generic truthy values such as
1 or true are ignored so existing deployments do not change execution
ownership accidentally. If HERMES_WEBUI_GATEWAY_API_KEY is omitted, WebUI falls
back to API_SERVER_KEY when present. When Gateway returns HTTP 401, WebUI
reports a gateway_auth_error that points at this WebUI↔Gateway key mismatch
rather than showing the Gateway's generic provider-style "Invalid API key" body.
/api/health/agent also includes a redacted gateway_chat block so operators can
see whether gateway mode, base URL, and API-key presence are configured without
exposing the key value. That gateway_chat field is an operator diagnostic
payload only; it is not currently rendered as a user-facing health banner in the
browser UI.
The bridge is best used by operators who already run Hermes Gateway/API Server locally and want browser-originated chat to use the same runtime/tool path as messaging surfaces. Attachments, cancellation, approvals, and clarify prompts still follow WebUI's current compatibility path and may not match every messaging surface until the runtime-adapter migration is complete.