## Problem
When multiple channels (WhatsApp, iMessage, Telegram, etc.) are active,
responses intended for one channel could leak to another channel if
messages arrived simultaneously. This created serious privacy concerns.
**Root Cause:**
All channels were updating the SAME main session key with their delivery
context (channel, to, accountId). When messages arrived concurrently:
1. WhatsApp message arrives → updates session['agent:main:main'].lastChannel = 'whatsapp'
2. Agent starts processing (takes time)
3. iMessage message arrives → OVERWRITES session['agent:main:main'].lastChannel = 'imessage'
4. WhatsApp response delivers → reads session lastChannel = 'imessage'
5. Response goes to wrong channel!
## Solution
Changed all channel monitors to use the channel-specific session key
(route.sessionKey) instead of the shared main session key
(route.mainSessionKey) when updating delivery context.
Now each channel updates its own isolated session:
- WhatsApp: session['agent:main:whatsapp:dm:+1234']
- iMessage: session['agent:main:imessage:dm:alice']
- Telegram: session['agent:main:telegram:dm:12345']
This prevents cross-channel state clobbering.
## Changes
- src/discord/monitor/message-handler.process.ts
- src/imessage/monitor/monitor-provider.ts
- src/line/bot-message-context.ts
- src/signal/monitor/event-handler.ts
- src/slack/monitor/message-handler/dispatch.ts
- src/slack/monitor/message-handler/prepare.ts
- src/telegram/bot-message-context.ts
- src/web/auto-reply/monitor/process-message.ts
All changed from:
sessionKey: route.mainSessionKey
To:
sessionKey: route.sessionKey
## Testing
Manual testing needed:
1. Configure 2+ channels (e.g., WhatsApp + iMessage)
2. Send message to channel A
3. Immediately send message to channel B (within 100ms)
4. Verify responses go to correct channels
Fixes#4530
* feat(whatsapp): add debounceMs for batching rapid messages
Add a `debounceMs` configuration option to WhatsApp channel settings
that batches rapid consecutive messages from the same sender into a
single response. This prevents triggering separate agent runs for
each message when a user sends multiple short messages in quick
succession (e.g., "Hey!", "how are you?", "I was wondering...").
Changes:
- Add `debounceMs` config to WhatsAppConfig and WhatsAppAccountConfig
- Implement message buffering in `monitorWebInbox` with:
- Map-based buffer keyed by sender (DM) or chat ID (groups)
- Debounce timer that resets on each new message
- Message combination with newline separator
- Single message optimization (no modification if only one message)
- Wire `debounceMs` through account resolution and monitor tuning
- Add UI hints and schema documentation
Usage example:
{
"channels": {
"whatsapp": {
"debounceMs": 5000 // 5 second window
}
}
}
Default behavior: `debounceMs: 0` (disabled by default)
Verified: All existing tests pass (3204 tests), TypeScript compilation
succeeds with no errors.
Implemented with assistance from AI coding tools.
Closes#967
* chore: wip inbound debounce
* fix: debounce inbound messages across channels (#971) (thanks @juanpablodlc)
---------
Co-authored-by: Peter Steinberger <steipete@gmail.com>
Adds support for template variables in `messages.responsePrefix` that
resolve dynamically at runtime with the actual model used (including
after fallback).
Supported variables (case-insensitive):
- {model} - short model name (e.g., "claude-opus-4-5", "gpt-4o")
- {modelFull} - full model identifier (e.g., "anthropic/claude-opus-4-5")
- {provider} - provider name (e.g., "anthropic", "openai")
- {thinkingLevel} or {think} - thinking level ("high", "low", "off")
- {identity.name} or {identityName} - agent identity name
Example: "[{model} | think:{thinkingLevel}]" → "[claude-opus-4-5 | think:high]"
Variables show the actual model used after fallback, not the intended
model. Unresolved variables remain as literal text.
Implementation:
- New module: src/auto-reply/reply/response-prefix-template.ts
- Template interpolation in normalize-reply.ts via context provider
- onModelSelected callback in agent-runner-execution.ts
- Updated all 6 provider message handlers (web, signal, discord,
telegram, slack, imessage)
- 27 unit tests covering all variables and edge cases
- Documentation in docs/gateway/configuration.md and JSDoc
Fixes#923