feat(agent): open, watch and resume Slack channels from agent runs
GI
2mo ago+4993+4993+0123456789012345678901234567890123456789-206-206-012345678901234567890123456789
Opened automatically when feat/agent-run-visibility was pushed.
The title is written from the diff and rewritten as you push, because this is squashed onto main and the title becomes the commit subject and the changelog line. Retitle it yourself and it is yours — the automation stops touching it.
Summary by cubic
Implements CRM-1: an agent run can now open its own Slack channel, invite people, and post into it, and gets woken up when messages or joins arrive in that channel. Previously Slack actions could only target a destination chosen when the agent was saved; now a run can create and claim a channel, and inbound Slack events resume that same parked run instead of starting a second one.
Behavior
- New
open_slack_channelandinvite_to_slack_channeltools are manifest-approved actions, with the same dependency checks and idempotency as existing actions; reopening a name already in use joins the existing channel, and the run keeps the channel it already owns. - Reusing a channel refuses an unavailable one (archived, kicked bot, or a private channel the bot can no longer see) and rejoins before handing it back; invitations stop when a run ends.
- Slack message posts can use
resolution: "run-channel", which resolves to the channel the run opened. - The new
/webhooks/slack/eventsendpoint verifies signatures and stores events inslackEventInbox; the agent drains them on the cron, in order, retrying undelivered resumes for five minutes. - Inbound Slack is off by default: without
SLACK_SIGNING_SECRET, the endpoint rejects every request, and answers 200 to bodies it cannot parse so Slack stops retrying. invite_to_slack_channelreturns invited and refused arrays, and throws only when Slack refuses every address; a paused agent's Slack message is kept for replay.- Run action results and the agent's final summary now appear in run history.
Setup / migration
- Requires
SLACK_SIGNING_SECRETand the newapp_mentions:readSlack scope; existing Slack connections must be re-authorized. - Migrations add
agentRun.slackChannelId,slackEventInbox, andagentAction.result. - Slack destinations now require a
resolutionfield (chosenorrun-channel); saved agents with older Slack destinations need that field set. bun run tunnel:slackprovides a stable local hostname for Slack event delivery; it followsPORTunlessSLACK_TUNNEL_PORToverrides it.