Channels/Messaging — Ack Reactions
Acknowledgement Reaction Scope Gating & WhatsApp Specialization
Ack reactions provide visual confirmation that the agent received a message. This module implements scope-based gating that considers chat type, mention status, and platform-specific behaviors (particularly WhatsApp’s unique reaction model).
5 Scopes WhatsApp Special Mention-Aware Zero-Config
📚 What is this & why does it matter?
In a busy group chat with dozens of messages, users need to know their message was received by the agent — not just ignored. Ack reactions (e.g., a 👀 emoji) provide that instant feedback. But they must be selective: reacting to every message in a group would be noisy. The scope system controls exactly when reactions fire.
💡 Real-world analogy
Think of a waiter at a restaurant. In a private dining room (DM), the waiter acknowledges every request immediately. In the main dining hall (group), the waiter only responds when called by name (@mention). The “scope” setting lets the restaurant manager decide the waiter’s response policy for each room type.
Contents
Scope Types
export type AckReactionScope =
| "all" // React to every message
| "direct" // React only in DMs
| "group-all" // React to all group messages
| "group-mentions" // React only when @mentioned in groups (default)
| "off" // Never react
| "none"; // Alias for "off"
Gate Parameters
export type AckReactionGateParams = {
scope: AckReactionScope | undefined; // Configured scope
isDirect: boolean; // Is this a DM?
isGroup: boolean; // Is this a group chat?
isMentionableGroup: boolean; // Can this group support mentions?
requireMention: boolean; // Is mention required?
canDetectMention: boolean; // Can the platform detect mentions?
effectiveWasMentioned: boolean; // Was the bot effectively mentioned?
shouldBypassMention?: boolean; // Bypass mention for authorized commands?
};
Decision Flow
flowchart TD
START["shouldAckReaction()"]
START --> SCOPE{"scope?"}
SCOPE -->|"off"/"none"| FALSE["return false"]
SCOPE -->|"all"| TRUE["return true"]
SCOPE -->|"direct"| IS_DM{"isDirect?"}
IS_DM -->|Yes| TRUE
IS_DM -->|No| FALSE
SCOPE -->|"group-all"| IS_GRP{"isGroup?"}
IS_GRP -->|Yes| TRUE
IS_GRP -->|No| FALSE
SCOPE -->|"group-mentions"| MENTIONABLE{"isMentionableGroup?"}
MENTIONABLE -->|No| FALSE
MENTIONABLE -->|Yes| REQ{"requireMention?"}
REQ -->|No| FALSE
REQ -->|Yes| DETECT{"canDetectMention?"}
DETECT -->|No| FALSE
DETECT -->|Yes| MENTIONED{"effectiveWasMentioned
OR shouldBypassMention?"}
MENTIONED -->|Yes| TRUE
MENTIONED -->|No| FALSE
export function shouldAckReaction(params: AckReactionGateParams): boolean {
const scope = params.scope ?? "group-mentions";
if (scope === "off" || scope === "none") return false;
if (scope === "all") return true;
if (scope === "direct") return params.isDirect;
if (scope === "group-all") return params.isGroup;
if (scope === "group-mentions") {
if (!params.isMentionableGroup) return false;
if (!params.requireMention) return false;
if (!params.canDetectMention) return false;
return params.effectiveWasMentioned || params.shouldBypassMention === true;
}
return false;
}
WhatsApp Specialization
WhatsApp has a dedicated ack reaction function with its own mode system:
export type WhatsAppAckReactionMode = "always" | "mentions" | "never";
export function shouldAckReactionForWhatsApp(params: {
emoji: string; // Must be non-empty
isDirect: boolean;
isGroup: boolean;
directEnabled: boolean; // WhatsApp-specific DM toggle
groupMode: WhatsAppAckReactionMode;
wasMentioned: boolean;
groupActivated: boolean; // Bypass for activated groups
}): boolean
flowchart TD
WA["shouldAckReactionForWhatsApp()"]
WA --> EMOJI{"emoji
non-empty?"}
EMOJI -->|No| FALSE["return false"]
EMOJI -->|Yes| DIRECT{"isDirect?"}
DIRECT -->|Yes| DIR_EN{"directEnabled?"}
DIR_EN -->|Yes| TRUE["return true"]
DIR_EN -->|No| FALSE
DIRECT -->|No| IS_GRP{"isGroup?"}
IS_GRP -->|No| FALSE
IS_GRP -->|Yes| MODE{"groupMode?"}
MODE -->|"never"| FALSE
MODE -->|"always"| TRUE
MODE -->|"mentions"| MENTION_CHECK["Delegate to
shouldAckReaction()"]
Decision Matrix
| Scope | DM | Group (mentioned) | Group (not mentioned) | Group (bypass) |
|---|---|---|---|---|
all | ✔ | ✔ | ✔ | ✔ |
direct | ✔ | ✘ | ✘ | ✘ |
group-all | ✘ | ✔ | ✔ | ✔ |
group-mentions | ✘ | ✔ | ✘ | ✔ |
off | ✘ | ✘ | ✘ | ✘ |