Skip to content

bridge: add πŸ‘€ on receive and βœ… on reply emoji reactions#167

Merged
benvinegar merged 1 commit intomainfrom
feat/slack-emoji-ack
Feb 24, 2026
Merged

bridge: add πŸ‘€ on receive and βœ… on reply emoji reactions#167
benvinegar merged 1 commit intomainfrom
feat/slack-emoji-ack

Conversation

@benvinegar
Copy link
Copy Markdown
Member

Brings back the attentive emoji behavior:

  • :eyes: on receive β€” immediately when a valid user message arrives from Slack, before forwarding to the agent
  • :white_check_mark: on reply β€” when the agent sends its first reply back to the same thread (via /send or /reply)

Both bridges (broker-pull and legacy Socket Mode) implement identical behavior. Pending ack reactions are tracked in a map keyed by channel:thread_ts and auto-expire after 10 minutes. All reactions are fire-and-forget β€” failures are logged as warnings but never block message delivery or agent forwarding.

Changes

  • slack-bridge/broker-bridge.mjs β€” added pendingAckReactions map, resolveAckReaction() helper, πŸ‘€ in handleUserMessage, βœ… in /send and /reply endpoints
  • slack-bridge/bridge.mjs β€” same pattern using Slack Web API directly
  • test/broker-bridge.integration.test.mjs β€” updated fire-and-forget test to expect and verify the πŸ‘€ reactions.add call

When a user message arrives in Slack, the bridge immediately reacts with
:eyes: to signal attentiveness. When the agent sends its first reply back
to the same thread, the bridge adds :white_check_mark: to the original
message.

Both bridges (broker-pull and legacy Socket Mode) implement the same
behavior. Pending ack reactions are tracked in a map keyed by thread and
auto-expire after 10 minutes. Reactions are fire-and-forget β€” failures
are logged but never block message delivery.
@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented Feb 24, 2026

Greptile Summary

Restores emoji reaction feedback for Slack users by adding πŸ‘€ immediately when messages arrive and βœ… when the agent replies. Both bridge implementations (broker-pull and Socket Mode) use identical fire-and-forget reaction logic with 10-minute auto-expiry. The implementation tracks pending reactions by channel:thread_ts, which means multiple user messages in the same thread will only result in the last message receiving a checkmark.

Confidence Score: 4/5

  • Safe to merge with minor edge case in multi-message threads
  • Implementation is clean, follows fire-and-forget pattern correctly, includes proper error handling, and has test coverage. The thread-keying behavior means only the last message in a thread gets βœ… before reply, which may or may not be intentional but doesn't break functionality
  • No files require special attention

Important Files Changed

Filename Overview
slack-bridge/broker-bridge.mjs Added emoji reaction tracking with πŸ‘€ on receive and βœ… on reply; implementation has a minor edge case where multiple messages in same thread before reply will only mark the last one
slack-bridge/bridge.mjs Mirrors broker-bridge.mjs emoji reaction pattern using Slack Web API directly; shares same thread-keying behavior

Last reviewed commit: df00a0a

Copy link
Copy Markdown

@greptile-apps greptile-apps Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

Comment on lines +737 to +742
const threadKey = `${ackChannel}:${event.thread_ts || ackMessageTs}`;
pendingAckReactions.set(threadKey, {
channel: ackChannel,
messageTs: ackMessageTs,
receivedAt: Date.now(),
});
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if a user sends multiple messages in the same thread before the agent replies, only the last message gets βœ… (each message overwrites the previous entry since they share the same channel:thread_ts key). consider whether this is intentional or if individual messages should be tracked using channel:messageTs as the key instead

Prompt To Fix With AI
This is a comment left during a code review.
Path: slack-bridge/broker-bridge.mjs
Line: 737-742

Comment:
if a user sends multiple messages in the same thread before the agent replies, only the last message gets βœ… (each message overwrites the previous entry since they share the same `channel:thread_ts` key). consider whether this is intentional or if individual messages should be tracked using `channel:messageTs` as the key instead

How can I resolve this? If you propose a fix, please make it concise.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Intentional β€” the βœ… signals "the agent replied to this thread", not "the agent processed this specific message." Each individual message already gets its own πŸ‘€ on arrival, so you can tell which ones were seen. Putting βœ… on every queued message in a burst would look noisy.

Responded by pi using anthropic/claude-sonnet-4-20250514.

Comment thread slack-bridge/bridge.mjs
Comment on lines +308 to +313
const threadKey = `${event.channel}:${event.thread_ts || event.ts}`;
pendingAckReactions.set(threadKey, {
channel: event.channel,
messageTs: event.ts,
receivedAt: Date.now(),
});
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same threading behavior as broker-bridge: multiple messages in one thread before agent reply will only mark the last one with βœ…

Prompt To Fix With AI
This is a comment left during a code review.
Path: slack-bridge/bridge.mjs
Line: 308-313

Comment:
same threading behavior as broker-bridge: multiple messages in one thread before agent reply will only mark the last one with βœ…

How can I resolve this? If you propose a fix, please make it concise.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same answer as the broker-bridge comment β€” this is intentional. πŸ‘€ marks each individual message, βœ… marks the thread as responded-to. Only the most recent message in a burst gets the checkmark, which avoids visual noise.

Responded by pi using anthropic/claude-sonnet-4-20250514.

@benvinegar benvinegar merged commit 0a13f48 into main Feb 24, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant