paperclip-plugin-slack
v2.1.0
Published
[](https://www.npmjs.com/package/paperclip-plugin-slack) [](https://opensource.org/licenses/MIT)
Readme
paperclip-plugin-slack
Slack Chat OS plugin for Paperclip. Turns Slack into a bidirectional agent command center - notifications, approvals, multi-agent threads, voice-to-task pipelines, custom workflow commands, and proactive agent suggestions.
Built on the Paperclip plugin SDK and the domain event bridge (PR #909).
Why this exists
Multiple Paperclip users asked for notifications on the same day the plugin system shipped (2026-03-14):
"is there a way to have codex/claude check paperclip to see when tasks are done without me prompting it?" - @Choose Liberty, Discord #dev
"basically to have it 'let me know when its done'" - @Choose Liberty, Discord #dev
"can claude code check paperclip to see when tasks are done" - @Nascozz, Discord #dev
@dotta (maintainer) responded: "we're also adding issue-changed hooks for plugins so when that lands someone could [make notifications]." The event bridge (PR #909) shipped that same day. @dotta also asked for "someone to make a plugin that's a totally separate package" to validate the DX. @Ryze said "Really excited by the plugins. I had developed a custom plugin bridge that I will now deprecate and migrate over to the new supported plugin system."
This is that plugin.
What it does
Phase 1: Notifications + HITL Escalation
Notifications (rich Block Kit formatting)
- Issue created - Title, description snippet, status, priority, assignee, project fields, and a "View Issue" button
- Issue done - Completion confirmation with status fields and view button
- Approval requested - Interactive Approve, Reject, and View buttons. Click to act without leaving Slack.
- Agent error - Error message in a code block with warning indicator
- Agent online - Connection confirmation with check mark
- Budget threshold - Alerts at 80%, 90%, and 100% budget usage (deduped per threshold)
- Onboarding milestone - Celebrates an agent's first successful run
Interactive approvals
- Approve/reject buttons on every approval notification
- Clicking a button calls the Paperclip API and updates the Slack message inline
- Identifies which Slack user acted (logged as
slack:{user_id})
Issue-thread confirmations
- Posts pending
request_confirmationissue interactions to Slack with Accept/Reject buttons - Clicking a button resolves the interaction in Paperclip and updates the Slack message inline
- Uses the approvals channel when configured, otherwise falls back to the default channel
HITL escalation
- Agents that get stuck can escalate to a dedicated Slack channel with full conversation context
- Rich Block Kit formatting with conversation history, agent reasoning, and confidence score
- "Use Suggested Reply" button when the agent has a best-guess response
- "Reply to Customer", "Override Agent", and "Dismiss" buttons
- Configurable timeout (default 15 min) with automatic default action (defer, close, retry)
- Customer messages queued during escalation and delivered with the human's response
- Exposes
escalate_to_humantool for agents
Per-type channel routing
- Route approvals, errors, and pipeline events to separate Slack channels
- Falls back to the default channel when a per-type channel isn't configured
- Per-company overrides still take priority
Daily digest
- Scheduled job (9am daily) with real stats from the Paperclip API
- Tasks completed, tasks created, active agents, total cost, and top performer
- Cost data accumulated from
cost_event.createdevents throughout the day
Phase 2: Multi-Agent Group Threads
- Multiple agents per thread - Spawn up to
maxAgentsPerThread(default 5) agents in a single Slack thread via/clip acp spawn <agent> [display_name] - @mention routing - @mention an agent name to direct your message to a specific agent; falls back to reply-to context, then most recently active
- Agent handoff -
handoff_to_agenttool lets one agent request a handoff to another with Approve/Reject buttons in-thread - Discussion loops -
discuss_with_agenttool starts a back-and-forth conversation between two agents with configurable max turns - Human checkpoints - Discussion pauses every 5 turns with Continue/Stop buttons so humans stay in the loop
- Stale detection - Discussions auto-pause after 5 minutes of inactivity
- Output sequencing - When multiple agents are active, outputs are queued and delivered in order with agent name labels
- Session registry - Tracks active/closed sessions per thread with native SDK sessions (preferred) and ACP fallback
/clip acp status- Show all active agents in the current thread/clip acp close [name]- Close a specific agent or the most recently active one
Phase 3: Media-to-Task Pipeline
- Auto-detect media files - Audio (mp3, m4a, ogg, wav, webm, flac) and video (mp4, webm, quicktime) attachments in threads are automatically processed
- Whisper transcription - Audio files are sent to a
whisper-transcriberagent for speech-to-text - Brief Agent - Optional agent summarizes the transcription into an actionable brief
- Inline results - Transcription and brief run IDs posted back to the original thread
process_mediatool - Agents can programmatically trigger media processing with an optionalbriefAgentId- Slack Events API -
file_sharedevents trigger the pipeline automatically
Phase 4: Custom Workflow Commands
!commandsyntax - Type!deploy stagingor!triage bug-123in any thread to trigger registered workflows- Multi-step workflows - Each command runs a sequence of steps:
invoke_agent,post_message,create_issue,wait_approval - Argument interpolation - Use
$1,$2, or$argsin step templates to pass user arguments register_commandtool - Agents or admins can register new commands at runtime- Step-level approval gates -
wait_approvalsteps pause execution with Approve/Reject buttons - Progress indicators - Each step posts status to the thread; failures show error details
/clip commands- List all registered custom commands with descriptions and usage
Phase 5: Proactive Agent Suggestions
- Event watches -
register_watchtool sets up a trigger: when an event matching a pattern fires, an agent is invoked with a templated prompt - Wildcard patterns - Match exact events (
issue.created) or wildcards (agent.run.*) - Prompt interpolation - Use
${event.payload.key}in watch prompts to inject event data - Built-in sales templates - 5 pre-built watch templates:
new-lead-follow-up,deal-stalled,high-value-issue,budget-warning,agent-error-diagnosis list_watch_templatestool - Browse available templatesremove_watchtool - Remove watches by ID- Scheduled check job - Watches are evaluated periodically against buffered events (last 100 per company)
/clip watches- List all active watches with trigger counts
Slash commands
/clip status- Show active agents and recent completions/clip agents- List all agents with status badges/clip issues [open|done]- List issues filtered by status/clip approve <id>- Approve a pending approval/clip acp spawn <agent> [display]- Add an agent to this thread/clip acp status- Show all agents in this thread/clip acp close [name]- Close a specific agent (or most recent)/clip commands- List registered custom commands/clip watches- List active event watches/clip help- Show this help message
Install
npm install paperclip-plugin-slackOr register with your Paperclip instance directly:
curl -X POST http://127.0.0.1:3100/api/plugins/install \
-H "Content-Type: application/json" \
-d '{"packageName":"paperclip-plugin-slack"}'[!NOTE] Company-scoped activation (#9557, first stable in
v2026.720.0): the host now resolves plugin secret references under a company scope. This plugin is deliveries-only: it reads no configuration and resolves no secrets at startup, and builds its runtime from the host's company-scoped configuration delivery (onConfigChanged). Onv2026.817.0+ it activates out of the box; onv2026.720.0/722.0save the plugin configuration once through the settings panel after installing, to trigger the first delivery. The earlier temporary secret-ref kill switch (#5429) was removed upstream in #9557 — no host pinning is needed any more.
Troubleshooting: confirm your Paperclip host
If the plugin looks broken, first confirm which Paperclip host it's actually talking to. Run paperclipai plugin target (#8575) — it prints the resolved API URL plus the server's status, version, deploymentMode, and deploymentExposure before anything is installed. A server version older than this plugin expects is the most common cause of activation failures and secret-resolution errors (e.g. slackTokenRef not resolving) that look like plugin bugs but aren't. If the URL or version is wrong, retarget Paperclip — or update the server — before opening an issue.
Setup
Create a Slack app at https://api.slack.com/apps
Add the required bot scopes:
chat:writefor posting notifications and command responsescommandsfor the/clipslash commandfiles:readif you want voice/file ingestionapp_mentions:readand the relevant message history scopes if you want Slack message events routed to agents
Choose one inbound mode:
- Socket Mode: enable Socket Mode, create an app-level token with
connections:write, and store that token as a Paperclip secret. Socket Mode is the easiest local setup because Slack sends events and interactive payloads over the WebSocket instead of requiring a public Request URL. - Webhook mode: keep Socket Mode disabled and configure the public Slack URLs below.
- Socket Mode: enable Socket Mode, create an app-level token with
For webhook mode, configure these Slack app URLs:
| Slack setting | Request URL | |---------------|-------------| | Event Subscriptions |
<paperclip base URL>/api/plugins/paperclip-plugin-slack/webhooks/slack-events| | Slash Commands (/clip) |<paperclip base URL>/api/plugins/paperclip-plugin-slack/webhooks/slash-command| | Interactivity & Shortcuts |<paperclip base URL>/api/plugins/paperclip-plugin-slack/webhooks/slack-interactivity|Install the app to your workspace and copy the Bot OAuth Token
In Paperclip, create a company secret holding the Bot OAuth Token, by either:
- UI: Open any agent's Configuration → Environment variables, enter a name (e.g.
slack-bot-oauth-token) and the Bot OAuth Token as the value, then click Create / Seal. The secret is created at the company level (not bound to that agent — despite the agent-context UI) and the returned UUID can be used from any plugin in the company. - REST API:
POST /api/companies/{companyId}/secretswith body{"name": "slack-bot-oauth-token", "value": "<your-bot-oauth-token>", "provider": "local_encrypted"}. The response contains the secret's UUID.
Copy the resulting secret UUID — you'll paste it into
slackTokenRefin the next step.- UI: Open any agent's Configuration → Environment variables, enter a name (e.g.
Install the plugin and configure the Bot token secret UUID in
slackTokenRef, the app-level token secret UUID inslackAppTokenRefwhen using Socket Mode, the signing secret reference inslackSigningSecretRef, and your default channel ID. The host-delivered company owns all inbound commands and confirmation state. LeaveslackAppTokenRefempty to keep webhook mode only.
Configuration
| Setting | Description |
|---------|-------------|
| slackTokenRef | Secret reference for the Slack Bot OAuth token |
| slackAppTokenRef | Optional secret reference for the Slack app-level xapp-... token used by Socket Mode |
| paperclipApiKeyRef | Secret reference for a Paperclip API key; required when enabling issue-thread confirmations |
| defaultChannelId | Default Slack channel ID (e.g. C01ABC2DEF3) |
| approvalsChannelId | Dedicated channel for approvals (optional) |
| errorsChannelId | Dedicated channel for agent errors (optional) |
| pipelineChannelId | Dedicated channel for agent lifecycle events (optional) |
| notifyOnIssueCreated | Post when issues are created (default: true) |
| notifyOnIssueDone | Post when issues are completed (default: true) |
| notifyOnApprovalCreated | Post when approvals are requested (default: true) |
| notifyOnRequestConfirmationCreated | Post pending issue-thread confirmations (default: false; requires paperclipApiKeyRef) |
| notifyOnAgentError | Post when agent runs fail (default: true) |
| notifyOnAgentConnected | Post when agents connect/disconnect (default: true) |
| notifyOnBudgetThreshold | Post when agents hit budget limits (default: true) |
| enableDailyDigest | Send daily activity summary at 9am (default: false) |
| escalationChatId | Dedicated channel for agent escalations (optional) |
| escalationTimeoutMs | Timeout before default action fires (default: 900000 / 15 min) |
| escalationDefaultAction | Action on timeout: defer, dismiss, or auto_reply (default: defer) |
| escalationHoldMessage | Message sent to customer while waiting (default: "Your request has been escalated to a human agent. Please hold.") |
| paperclipBaseUrl | Base URL for the Paperclip API (default: http://localhost:3100) |
| maxAgentsPerThread | Max concurrent agents in a single thread (default: 5) |
Agent tools
The plugin registers these tools that agents can call:
| Tool | Phase | Description |
|------|-------|-------------|
| escalate_to_human | 1 | Escalate to a human operator with conversation context and optional suggested reply |
| handoff_to_agent | 2 | Request a handoff from one agent to another with approval buttons |
| discuss_with_agent | 2 | Start a turn-based discussion loop between two agents |
| process_media | 3 | Process an audio/video file - transcribe and optionally brief |
| register_command | 4 | Register a custom !command with workflow steps |
| register_watch | 5 | Register an event watch that triggers an agent on matching events |
| remove_watch | 5 | Remove a registered event watch |
| list_watch_templates | 5 | List built-in watch templates for common use cases |
Migration
v2.0.1
The slackTokenRef field now declares format: "secret-ref", which is required for Paperclip to collect and resolve secret references at activation time. Previously, the field was a plain string with no format annotation, causing plugin activation to fail with Invalid secret reference.
If you installed v2.0.0: you must re-configure the plugin. Create a company secret holding the Slack Bot OAuth Token using one of the paths in the Setup section above (UI or REST API), then paste the resulting secret UUID into the slackTokenRef field in the plugin configuration. Raw token strings are no longer accepted in this field.
Development
npm install
npm run typecheck
npm test
npm run buildTests cover notifications, approvals, escalation, session registry, media pipeline, custom commands, proactive suggestions, Block Kit formatting, Socket Mode, and slash commands.
For full local verification, run npm run verify. For the standalone diagnostic script only, set SLACK_APP_TOKEN and run npm run smoke:socket to verify that Slack returns a Socket Mode WebSocket URL. Installed plugin workers use slackAppTokenRef and paperclipApiKeyRef; they do not read host environment credentials or package .env files.
Contributing
Issues and PRs welcome at github.com/mvanhorn/paperclip-plugin-slack.
Auto-publishes to npm on push to main via OIDC trusted publishing.
Credits
@MatB57 - Escalation channel concept, "Chat OS" vision for turning chat plugins into bidirectional agent command centers, and the HITL suggested-reply flow.
License
MIT
