feat(api): bridge the Slack agent to the user's Linear and GitHub plugins
Merged
AV
2mo ago+972+972+012345678901234567890123456789-101-101-012345678901234567890123456789
Links
- Plan page (Phase 1, PR C): https://app.superset.sh/page/slack-agent-plan-98cwoq
- Sibling PR A (thread sessions): #7583. Independent; no shared files.
Summary
- A linked user's connected plugins reach the Slack agent through the credential proxy, the way
superset mcp call-tooldoes. Linear and GitHub today; the token is decrypted per call inside the API and never handed to the model. - A curated subset per plugin (11 Linear, 12 GitHub: reads plus filing issues, commenting and opening PRs; no deletes, merges or bulk writes), enforced at discovery and at execution like the Superset allowlist.
- Filed Linear issues and opened GitHub PRs show in the Changes footer with links. A reply that names a plugin the user hasn't connected gets a Connect button.
Why / Context
"Talk to Linear" was one of the three original asks. Only per-user plugin_connections give the agent tools, and both plugins already declare hosted MCP servers behind the proxy, so this is a bridge rather than new tool code.
How It Works
toolConnections(userId)inpackages/trpc/src/router/plugins/connections.tsresolves each active connection to its install and bundled source and keeps plugins that expose tools; the integrations barrel re-exports it withlistTools,callToolandtemplateScope.dispatch.listTools/callTooltake an optionalAbortSignal, threaded through every upstream fetch including the session handshake, so plugin calls are bounded by the remaining run budget like MCP calls.plugin-tools.tsbeside the agent loop lists tools per connection with an in-process one-hour cache keyed by plugin, manifest version and auth method. A failed listing, or a failure resolving connections at all, logs and leaves the run with Superset tools only.- The agent registers
linear_*/github_*tools from the curated subset, routes calls by prefix, and refuses anything outside the subset at execution. The system prompt gets one line per plugin: connected, connected but unavailable this run, or (only when the message names it) not connected. - The handler posts a "Connect " button linking to
/pluginson web, a new deep-link passthrough to the desktop plugins page.
Manual QA Checklist
Needs a linked user with a Linear or GitHub plugin connection.
- "file this as a Linear issue" creates the issue and the Changes footer links it
- "what's open in Linear for me" answers from
linear_list_issues - Ask for a Linear issue delete: refused
- A user without GitHub asks about GitHub: reply says it isn't connected, Connect button appears, button opens the desktop plugins page
- Disconnect the plugin, ask again: no
linear_*tools offered
Testing
bun test src/app/api/integrations/slackinapps/api: 72 pass (10 new plugin tests, 2 new handler tests)bun testinpackages/trpc: 290 pass (worker's run)bunx tsc --noEmitforapps/api,apps/web,packages/trpc: cleanbunx biome checkon changed paths: clean- Not exercised against live Linear or GitHub: the reviewing account has no plugin connections, both remote MCP endpoints answer 401 unauthenticated. Linear tool names and the issue result shape were verified against the official Linear MCP; GitHub names come from the github-mcp-server README and its create responses from the Go source (
{id, url}only, so the PR number is parsed from the URL).
Known Limitations
mentionsPluginis a substring match on the display name, so a reply containing a github.com link for a user without GitHub draws the Connect button.- When a user holds several connections for one plugin, the newest wins.
save_issueandissue_writealso edit a single issue when given an id; they are each server's only create path, so they stay in and the action record fires only on a create.
Rollout / Rollback
- No flag: tools appear only for users who have connected a plugin, which today is nobody on the Slack surface. Rollback is a revert.
https://claude.ai/code/session_01YDDSQYG6WSZn4jXWTR3Pid
Summary by cubic
Bridges the Slack agent from Superset-only tools to a connected user's Linear and GitHub plugins through the credential proxy, so credentials stay server-side. Connected users can search, read, and create supported issues, comments, and pull requests; unavailable plugins surface a Connect button instead of failing the run.
Integration behavior
- Exposes 11 Linear and 12 GitHub tools, with allowlists enforced during discovery and execution; destructive and bulk operations remain excluded.
- Bounds plugin calls to the run deadline and caches tool listings for one hour by plugin installation, manifest version, and auth method; discovery gets its own 15-second cap so a hung plugin doesn't stall the run.
- Records created issues and opened pull requests in the Changes footer, while treating edits as updates rather than creations.
- Distinguishes connected, temporarily unavailable, and named-but-unconnected plugins in the agent context.
Slack delivery
- Connect prompts use the reply client and link
/pluginsto the desktop plugins route, including when the agent has exhausted its run budget. - Connection or tool-listing failures leave the run on Superset tools; a failed listing is reported as unavailable rather than unconnected.
- No feature flag or migration is required; rollback is a revert.
Summary by CodeRabbit
-
New Features
- Slack Agent can use connected Linear and GitHub integrations for supported actions.
- Added clearer progress updates while working with integrations.
- Slack replies now include issue and pull request results with links.
- When an unavailable integration is referenced, Slack displays a Connect button linking to the Plugins page.
- Added a direct Plugins page entry point for integration setup.
-
Bug Fixes
- Improved formatting and escaping for Slack action messages.
- Added safer handling for integration connection, tool-loading, and execution failures.