Skip to content

fix(gateway): respect routed profile in slash commands - #31102

Closed
tensorbit89-netizen wants to merge 1 commit into
NousResearch:mainfrom
tensorbit89-netizen:fix-gateway-routed-profile-commands
Closed

tensorbit89-netizen wants to merge 1 commit into
NousResearch:mainfrom
tensorbit89-netizen:fix-gateway-routed-profile-commands

Conversation

@tensorbit89-netizen

Copy link
Copy Markdown

Summary

  • Resolve the effective routed profile for gateway slash commands based on configured channel/thread routes.
  • Make /profile report the chat's effective profile and make /model read the effective profile config before showing the current model/provider.

Why

When a gateway process runs under one profile but Discord channels or threads are routed to named profiles, slash commands should reflect the profile that will actually handle that chat. Otherwise /profile and /model can show the gateway process profile instead of the routed chat profile.

Tests

  • python -m pytest tests/gateway/test_channel_profile_routing.py -q -o 'addopts='
  • python -m pytest tests/gateway/test_channel_profile_routing.py tests/gateway/test_status_command.py tests/gateway/test_model_command_custom_providers.py tests/gateway/test_session_model_override_routing.py -q -o 'addopts='

@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists comp/gateway Gateway runner, session dispatch, delivery labels May 23, 2026

@teknium1 teknium1 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for addressing routed-profile visibility in gateway slash commands. The premise remains valid on current main, but this implementation needs rework against the current multiplexing seam.

Problems

  • Current routing stamps event.source.profile in gateway/run.py:8629-8637; the agent resolves that same field in gateway/run.py:16977-16990. The PR instead introduces channel_profiles lookup at gateway/run.py:4613, a configuration shape with no current routing consumer. It can make /profile or /model report a profile that the agent will not use.
  • The PR only replaces the initial /model config read (gateway/run.py:10065). Its unchanged config_path remains process-scoped at line 10063, so global /model persistence still targets the gateway profile.
  • Current handlers live in gateway/slash_commands.py after 619bd782738adfa87544d0fda7a1114defe86e4c.

Suggested changes

  • Salvage this in gateway/slash_commands.py using event.source.profile and the existing profile-home resolver, including both read and persistence paths.
  • Test real multiplexed SessionSource.profile routing rather than a new mapping.

Automated hermes-sweeper review.

Comment thread gateway/run.py
active = self._active_profile_name()
if source is None:
return active
routes = self._channel_profile_routes(source.platform)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Current multiplex routing does not derive a profile from channel IDs: secondary adapters stamp event.source.profile before dispatch (gateway/run.py:8629-8637 on main), and the agent resolves that field. This new mapping can make slash commands select a profile that the actual turn will not use; derive from source.profile instead.

Comment thread gateway/run.py
config_path = _hermes_home / "config.yaml"
try:
cfg = _load_gateway_config()
cfg, _effective_profile = self._effective_user_config_for_source(source)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This fixes only the display-time config read. config_path remains _hermes_home / "config.yaml" immediately above, so the typed/picker global persistence paths still save to the gateway process profile. Scope the full command's read/write path to the same routed profile.

@teknium1 teknium1 added sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform area/profiles Multi-profile isolation, HERMES_HOME scoping labels Jul 13, 2026
@PRATHAMESH75

Copy link
Copy Markdown

Thanks for tackling this — the /profile and /model handlers absolutely should report the routed chat profile rather than the gateway process profile. One coverage concern on where the routes are read from:

_effective_profile_name_for_source resolves via _channel_profile_routes, which only reads a channel_profiles map (from the gateway / <platform> config blocks). But channel_profiles doesn't appear anywhere else in the tree — normal inbound routing resolves the profile through gateway.profile_routes, matched by gateway/profile_routing.py:match_profile_route and surfaced by the existing _profile_name_for_source(source) helper (gateway/run.py, gated on gateway.multiplex_profiles).

So for a normally-configured routed channel — e.g. the profile_routes list form in #69178:

gateway:
  multiplex_profiles: true
profile_routes:
  - platform: discord
    guild_id: "..."
    chat_id: "..."
    profile: boisejazz

_channel_profile_routes returns {}, and /profile / /model still fall back to the process/default profile — i.e. the symptom this PR targets keeps reproducing for the config shape that message routing already honors.

Suggestion: source the effective profile from the same engine messages use — reuse _profile_name_for_source(event.source) (fall back to the active profile when it returns None) instead of the separate channel_profiles map. That keeps slash commands and message routing in agreement and covers profile_routes out of the box. The _load_profile_config / _effective_user_config_for_source machinery here can stay as-is on top of it.

Happy to be wrong if channel_profiles is an intentionally new config surface — but then #69178's profile_routes case would still need wiring.

@teknium1

teknium1 commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

Thanks for this PR. Merged via #101247 (0437fe6) on current main — handoffs fail closed and load secrets off-loop; Discord slash commands honor profile_routes.

#101247 won as the consolidated fix because it covers the whole multiplex-profile bug class in one change (with tests) rather than the single symptom addressed here; this PR is superseded by it.
You were the first to submit/report this, and that is called out explicitly in #101247.

If anything from your original change is still missing on main >= 0437fe6, please open a fresh PR/issue against main and tag it. Thanks again.

@teknium1 teknium1 closed this Sep 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/profiles Multi-profile isolation, HERMES_HOME scoping comp/gateway Gateway runner, session dispatch, delivery P2 Medium — degraded but workaround exists sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants