fix(gateway): respect profile-scoped adapters in multiplex response delivery - #52225
Closed
franklinbravos wants to merge 1 commit into
Closed
fix(gateway): respect profile-scoped adapters in multiplex response delivery#52225franklinbravos wants to merge 1 commit into
franklinbravos wants to merge 1 commit into
Conversation
…elivery
In multiplex mode (gateway.multiplex_profiles: true), each profile has its
own platform adapters stored in `_profile_adapters[profile_name][platform]`.
However, ~20 call sites in the response delivery path only consulted
`self.adapters` (the default profile's adapters), causing responses to
always be sent through the default profile's bot/credentials regardless of
which profile's adapter received the original message.
Fixes include:
gateway/config.py:
- Ensure `_get_env()` uses the per-profile secret scope instead of
process-global `os.environ` in multiplex mode, preventing token leaks
across profiles that caused exclusive_bot_mentions to break.
- Also propagate `multiplex_profiles` when set under the `gateway:` key
in config.yaml (not just top-level).
- Replace bare `os.getenv()` calls with `_e()` so they pick up profile
secrets during secondary profile startup.
gateway/run.py — stream/delivery path (12 sites):
- `_run_agent_via_proxy` (proxy mode): stream consumer adapter, typing
indicator, and goal status notice.
- `_run_agent_inner` (local agent): stream consumer adapter, status
adapter, progress callback adapter, cleanup adapter, typing stop,
stale result cleanup, and pairing response adapters.
- `_handle_message`: pairng code and rate-limit response adapters.
The fix pattern at each site is the same:
# Before — always uses default profile's adapter:
adapter = self.adapters.get(source.platform)
# After — uses the source's profile adapter when available:
_profile_name = getattr(source, "profile", None)
_profile_adapter = (
self._profile_adapters.get(_profile_name, {}).get(source.platform) if _profile_name else None
)
adapter = _profile_adapter or self.adapters.get(source.platform)
When multiplex is off, `_profile_adapters` is empty and `source.profile`
is unset, so the fallback to `self.adapters` preserves existing
single-profile behavior with zero overhead.
This was referenced Jul 2, 2026
Contributor
|
Thanks for identifying the multiplex response-routing issue. This is an automated hermes-sweeper review; the requested behavior is already on current
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
In multiplex mode (
gateway.multiplex_profiles: true), each profile has its own platform adapters stored in_profile_adapters[profile_name][platform]. However, ~12 call sites in the response delivery path only consultedself.adapters(the default profile's adapters), causing responses to always be sent through the default profile's bot regardless of which profile's adapter received the original message.Changes
gateway/config.py_get_env()to use per-profile secret scope instead of process-globalos.environin multiplex mode, preventing cross-profile token leaks.multiplex_profileswhen set under thegateway:key in config.yaml.os.getenv()calls with_e()for profile-scoped resolution.gateway/run.pyPatched all
self.adapters.get(source.platform)call sites in the response delivery path to first checkself._profile_adapters[source.profile]when a profile is set. This covers proxy mode (stream consumer, typing indicator, goal status notice) and local agent (stream consumer, status adapter, progress callback, cleanup, typing stop, stale result, pairing responses).The fallback to
self.adapterspreserves existing single-profile behavior with zero overhead.Testing
Tested with 5 profiles (default, elias, iago, matias, sofia) each with distinct Telegram bot tokens. Verified that messages to a secondary profile's bot are now correctly delivered through that profile's bot instead of the default.