Summary
When the Desktop app is connected to a single remote backend serving multiple profiles (app-global remote mode), creating a new chat via the sidebar "New Session" button or the Ctrl/Cmd+N shortcut silently creates the session in the launch profile (the backend's active_profile, typically default) — even when the user has explicitly selected a different profile in the profile rail and the sidebar is showing that profile's sessions.
Because the model picker is independent of the profile, the new chat keeps the model the user was using in the other profile, so everything looks right — but the session binds to the wrong profile's state.db, HERMES_HOME, SOUL.md, memories, and skills. Any cron jobs the agent creates in that conversation are registered in the wrong profile too (and deliver to that profile's channels). This caused real damage on our side twice before we traced it: an overnight autonomous task intended for an isolated "lab" profile ran inside the main profile, used its skills, and delivered to its Telegram home channel.
Environment
- Desktop: Windows 11 build from
apps/desktop at main 484f484c2 (2026-06-11); bug confirmed still present on origin/main as of 2026-06-12
- Connection:
connection.json mode: "remote", single remote URL, profiles: {} (app-global remote mode)
- Backend: Hermes Agent v0.16 (all-in-one container), 2 profiles:
default (launch/active) + one named profile
Steps to reproduce
- Connect the Desktop to a remote backend that has a named profile besides
default (backend active_profile = default).
- Click the named profile's square in the rail (sessions list switches to it — you are "in" that profile).
- Click the sidebar "New Session" button (or press Ctrl/Cmd+N).
- Send any message.
Expected: the new session is created in the selected (active gateway) profile and persists to its state.db.
Actual: the session is created in the launch profile (default) — it appears under default in the session list and persists to the root state.db.
Root cause
Three pieces interact:
-
Both new-chat entry points reset the next-chat profile to null:
apps/desktop/src/app/chat/sidebar/index.tsx (~line 818): if (isNewSession) { $newChatProfile.set(null) }
apps/desktop/src/app/hooks/use-keybinds.ts (~line 131, 'session.new' handler): $newChatProfile.set(null)
The comments at both sites say a plain new chat should "land in whatever profile the live gateway is on" / "target the current live profile".
-
apps/desktop/src/app/session/hooks/use-session-actions.ts (createBackendSessionForSend, ~line 380) omits the profile param when $newChatProfile is null:
...(newChatProfile ? { profile: newChatProfile } : {})
-
The server (tui_gateway/server.py, session.create handler, ~line 3342) interprets a missing profile as the launch profile:
"Omitted/own profile → the launch profile (unchanged for single-profile and per-profile-remote setups)."
So null does not mean "current live profile" as the client comments intend — in app-global remote mode it means "launch profile", which is default regardless of $activeGatewayProfile. The paths that do set $newChatProfile (profile rail click → selectProfile, the per-profile "+" in the All-profiles view → newSessionInProfile, and the /profile <name> slash command) work correctly, which makes the button/shortcut failure intermittent-looking and hard for users to diagnose.
Suggested fix
In createBackendSessionForSend, fall back to the live gateway profile instead of omitting the param:
const newChatProfile = $newChatProfile.get() ?? normalizeProfileKey($activeGatewayProfile.get())
(Server-side _profile_home already returns None for the launch profile, so always passing the resolved profile is a no-op for single-profile users.) Alternatively, change the two set(null) call sites to set($activeGatewayProfile.get()) — either way makes the behavior match the existing comments.
Impact
Multi-profile users separate profiles precisely to isolate memory, skills, channels, and autonomous jobs. This bug silently routes work — including cron creation and channel delivery — across that isolation boundary, with no visual indication until the agent identifies itself.
Summary
When the Desktop app is connected to a single remote backend serving multiple profiles (app-global remote mode), creating a new chat via the sidebar "New Session" button or the Ctrl/Cmd+N shortcut silently creates the session in the launch profile (the backend's
active_profile, typicallydefault) — even when the user has explicitly selected a different profile in the profile rail and the sidebar is showing that profile's sessions.Because the model picker is independent of the profile, the new chat keeps the model the user was using in the other profile, so everything looks right — but the session binds to the wrong profile's
state.db, HERMES_HOME, SOUL.md, memories, and skills. Any cron jobs the agent creates in that conversation are registered in the wrong profile too (and deliver to that profile's channels). This caused real damage on our side twice before we traced it: an overnight autonomous task intended for an isolated "lab" profile ran inside the main profile, used its skills, and delivered to its Telegram home channel.Environment
apps/desktopat main484f484c2(2026-06-11); bug confirmed still present onorigin/mainas of 2026-06-12connection.jsonmode: "remote", single remote URL,profiles: {}(app-global remote mode)default(launch/active) + one named profileSteps to reproduce
default(backendactive_profile=default).Expected: the new session is created in the selected (active gateway) profile and persists to its
state.db.Actual: the session is created in the launch profile (
default) — it appears underdefaultin the session list and persists to the rootstate.db.Root cause
Three pieces interact:
Both new-chat entry points reset the next-chat profile to
null:apps/desktop/src/app/chat/sidebar/index.tsx(~line 818):if (isNewSession) { $newChatProfile.set(null) }apps/desktop/src/app/hooks/use-keybinds.ts(~line 131,'session.new'handler):$newChatProfile.set(null)The comments at both sites say a plain new chat should "land in whatever profile the live gateway is on" / "target the current live profile".
apps/desktop/src/app/session/hooks/use-session-actions.ts(createBackendSessionForSend, ~line 380) omits theprofileparam when$newChatProfileisnull:The server (
tui_gateway/server.py,session.createhandler, ~line 3342) interprets a missingprofileas the launch profile:So
nulldoes not mean "current live profile" as the client comments intend — in app-global remote mode it means "launch profile", which isdefaultregardless of$activeGatewayProfile. The paths that do set$newChatProfile(profile rail click →selectProfile, the per-profile "+" in the All-profiles view →newSessionInProfile, and the/profile <name>slash command) work correctly, which makes the button/shortcut failure intermittent-looking and hard for users to diagnose.Suggested fix
In
createBackendSessionForSend, fall back to the live gateway profile instead of omitting the param:(Server-side
_profile_homealready returnsNonefor the launch profile, so always passing the resolved profile is a no-op for single-profile users.) Alternatively, change the twoset(null)call sites toset($activeGatewayProfile.get())— either way makes the behavior match the existing comments.Impact
Multi-profile users separate profiles precisely to isolate memory, skills, channels, and autonomous jobs. This bug silently routes work — including cron creation and channel delivery — across that isolation boundary, with no visual indication until the agent identifies itself.