#15727: fix(routing): resolve channel default account instead of hardcoded 'default'
size: S
## Summary
Fixes #9198 — binding routing fails for multi-account channels where the default account id is not literally `"default"`.
## Root Cause
`matchesAccountId()` in `src/routing/resolve-route.ts` compared the inbound account against the hardcoded `DEFAULT_ACCOUNT_ID` (`"default"`) when a binding omitted `accountId`. This meant bindings like:
```yaml
bindings:
- agentId: bizPeer
match:
channel: whatsapp
peer: { kind: direct, id: "+1000" }
```
…would never match on a channel whose sole (and thus default) account is named `"biz"`.
## Fix
- Use `resolveChannelDefaultAccountId` from `src/channels/plugins/helpers.ts` to determine the channel's actual default account id.
- Normalize both sides of the comparison via `normalizeAccountId` from `session-key.ts`.
- Added regression test for the non-literal default account scenario.
## Testing
- All 30 existing + 1 new test pass (`pnpm test src/routing/resolve-route.test.ts`)
- [x] AI-assisted (Claude, fully tested)
- [x] I understand what this code does
<!-- greptile_comment -->
<h2>Greptile Overview</h2>
<h3>Greptile Summary</h3>
This PR fixes account matching for bindings that omit `accountId` by resolving the channel’s actual default account id (instead of comparing against the hardcoded `"default"`), and adds a regression test for channels whose default account id is non-literal.
The change is implemented in `src/routing/resolve-route.ts` by introducing a helper that looks up the channel plugin and asks it (via `resolveChannelDefaultAccountId`) for the default account id, then uses that value when deciding whether a binding with no `accountId` matches. The test suite is extended in `src/routing/resolve-route.test.ts` to cover a single-account channel named `"biz"`.
<h3>Confidence Score: 2/5</h3>
- This PR has a real risk of breaking routing in config-only / early-init contexts due to relying on the runtime plugin registry during route resolution.
- The functional intent looks correct and a regression test was added, but `resolveAgentRoute()` now imports/calls `getChannelPlugin()` from the runtime plugin registry module, which can throw if the registry isn’t initialized and also pulls heavy runtime dependencies into a shared routing path. That’s a behavior change that can surface at runtime outside the test case.
- src/routing/resolve-route.ts
<sub>Last reviewed commit: ee90398</sub>
<!-- greptile_other_comments_section -->
<sub>(3/5) Reply to the agent's comments like "Can you suggest a fix for this @greptileai?" or ask follow-up questions!</sub>
<!-- /greptile_comment -->
Most Similar PRs
#13477: routing: normalize account ID matching for agent bindings
by davidahmann · 2026-02-10
85.3%
#9437: fix: normalize accountId in binding matching for consistent routing
by dbottme · 2026-02-05
82.8%
#23656: fix(routing): trust binding agentId even when not in agents.list
by SleuthCo · 2026-02-22
79.7%
#14359: fix: prefer named Telegram account over orphan 'default' in binding...
by itsGustav · 2026-02-12
79.3%
#18801: fix(routing): use fresh config in resolveAgentRoute to prevent stal...
by mcaxtr · 2026-02-17
77.1%
#21271: fix(commands): pass channel/capabilities/shell/os to runtime in com...
by evansantos · 2026-02-19
77.0%
#14888: fix(routing): normalize peer.kind in matchesPeer for symmetric comp...
by omair445 · 2026-02-12
77.0%
#8507: fix: preserve accountId for multi-account agent-to-agent messaging
by djh58 · 2026-02-04
76.1%
#19615: fix(discord): include default account when sub-accounts are configured
by prue-starfield · 2026-02-18
75.7%
#23727: Fix Telegram channel resolution drift across announce + message sen...
by SmithLabsLLC · 2026-02-22
74.8%