fix(channels): add default_agent to SidecarChannelConfig — restore inbound routing pin (closes #5294)#5295
Merged
houko merged 1 commit intoMay 20, 2026
Conversation
…bound routing pin (closes librefang#5294) Sidecar adapter migration (librefang#5241) dropped the per-channel default_agent field that in-process configs (TelegramConfig, DiscordConfig, etc.) used to seed AgentRouter.channel_defaults at boot. The router-population loop in channel_bridge.rs pushed sidecar adapters into the adapters vec with None for the default-agent slot, so the per-channel set_channel_default_with_name call never fired for sidecar channels. Result: inbound messages on a sidecar channel with no explicit binding fell through to the non-deterministic 'first available agent' branch in resolve_or_fallback. Spawning a new agent (without restricting its channels allowlist) silently redirected inbound traffic to it. Fix: add default_agent: Option<String> to SidecarChannelConfig and propagate it through the adapter-push so the existing population loop seeds the router. No behavioural change when the field is absent. Test: sidecar_default_agent_roundtrip_5294.
houko
approved these changes
May 20, 2026
houko
left a comment
Contributor
There was a problem hiding this comment.
Verified:
default_agentfield has#[serde(default)](librefang-types/src/config/types.rs~2180), so existing[[sidecar_channels]]blocks without it still parse asNone— back-compat preserved.- Wire-through reaches the router:
sidecar_config.default_agent.clone()lands in the registration tuple alongside the in-process adapter path (channel_bridge.rs~3282-3285), and the router loop at 3295-3329 feeds it toset_channel_default_with_name()— same code path that already works for in-process adapters. - Regression test
sidecar_default_agent_roundtrip_5294(inchannels/src/sidecar.rs) covers serde present + absent. End-to-end routing is exercised by the existingbridge_integration_test.rstests.
Stale golden schema is pre-existing (config_schema_golden test is already #[ignore]) and orthogonal.
This was referenced May 20, 2026
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.
Closes #5294.
Problem
Sidecar adapter migration (#5241) dropped the per-channel
default_agentfield that in-process configs (TelegramConfig,DiscordConfig, …) used to seedAgentRouter.channel_defaultsat boot. The router-population loop inchannel_bridge.rs(around line 3295) pushes sidecar adapters into theadaptersvec withNonefor the default-agent slot, so the per-channelrouter.set_channel_default_with_namecall never fires for sidecar channels.Result: inbound messages on a sidecar channel with no explicit binding fall through to the non-deterministic 'first available agent' branch in
resolve_or_fallback. Spawning a new agent (without restricting itschannelsallowlist) silently redirects inbound traffic to it.Reproduction
[[sidecar_channels]]. Existing agent (e.g.fandangorodelo) withchannels = ["telegram"]in its manifest, receiving Telegram traffic correctly.Profesor) without restricting itschannelslist (defaults tochannels = []).Profesorinstead offandangorodelo, because the router has nochannel_defaults["telegram"]and falls through to first-available.Fix
Add
default_agent: Option<String>toSidecarChannelConfig(mirrors the equivalent field on in-process channel configs) and propagate it through the adapter-push so the existing population loop seeds the router.No behavioural change when the field is absent — deployments that currently rely on the "first available" fallback continue working.
Test plan
cargo check -p librefang-types -p librefang-channels— cleancargo clippy -p librefang-types -p librefang-channels --all-targets -- -D warnings— cleancargo test -p librefang-channels --lib sidecar_default_agent_roundtrip_5294— passes (new test covering absent + explicit-value round-trip).default_agent = "fandangorodelo"in config, traffic routes correctly even when other agents exist.Notes
This only addresses the missing-router-default half of #5294. The two related concerns (
channels = []accept-all semantics, and the 'first available' fallback being a silent footgun) are separate and need their own discussion — see the issue body. Happy to follow up on either if maintainers want to flip those defaults too.