Problem
When a user mentions a managed employee such as Prime in Slack, the channel can remain visually silent until the whole model/tool run finishes. Users cannot distinguish a healthy, accepted request from a dead Socket Mode receiver.
This is distinct from serenorg/seren-core#260: #260 makes a failed ingress worker observable and recoverable; this issue exposes accepted/running state to the Slack user.
Proposed behavior
Add an immediate :eyes: reaction to each valid, non-self-authored, allowlisted inbound Slack message before the event is handed to the managed runtime. Treat reaction failure as a fail-open UX error: log it, but never drop or fail the inbound event.
State contract for v1:
- no
:eyes: within about two seconds: ingress is unavailable or the event was rejected
:eyes: present, no reply yet: the Slack plugin received and queued the request; downstream work may be running or waiting
- reply present: the channel turn completed
A later lifecycle enhancement may remove :eyes: on reply or replace it with a warning on terminal failure, but that is not required for the first shippable acknowledgement.
Implementation notes
- Add Slack Web API
reactions.add support in channels/slack/src/slack_api.rs.
- Trigger it only after inbound event type, self-author, team, and sender-policy checks pass.
- Use Slack
event.ts, not client_msg_id; the reactions API requires the message timestamp. Preserve that timestamp in event metadata for future lifecycle updates.
- Keep the call fail-open and redact token/content from all errors.
- The existing Equi Prime manifest already requests
reactions:write; deployment should still verify the installed token scope.
Acceptance criteria
Problem
When a user mentions a managed employee such as Prime in Slack, the channel can remain visually silent until the whole model/tool run finishes. Users cannot distinguish a healthy, accepted request from a dead Socket Mode receiver.
This is distinct from serenorg/seren-core#260: #260 makes a failed ingress worker observable and recoverable; this issue exposes accepted/running state to the Slack user.
Proposed behavior
Add an immediate
:eyes:reaction to each valid, non-self-authored, allowlisted inbound Slack message before the event is handed to the managed runtime. Treat reaction failure as a fail-open UX error: log it, but never drop or fail the inbound event.State contract for v1:
:eyes:within about two seconds: ingress is unavailable or the event was rejected:eyes:present, no reply yet: the Slack plugin received and queued the request; downstream work may be running or waitingA later lifecycle enhancement may remove
:eyes:on reply or replace it with a warning on terminal failure, but that is not required for the first shippable acknowledgement.Implementation notes
reactions.addsupport inchannels/slack/src/slack_api.rs.event.ts, notclient_msg_id; the reactions API requires the message timestamp. Preserve that timestamp in event metadata for future lifecycle updates.reactions:write; deployment should still verify the installed token scope.Acceptance criteria
app_mentiongets exactly one:eyes:reaction before model completion.event.tseven whenclient_msg_idis present.#test-agent-prime(C0BJSQDLURY); never in the production team channel.