协作办公
为 Cyrus 创建并配置 Slack 应用集成
在 Cyrus 中需要接入 Slack 时,通过 manifest 创建 Slack App、安装并安全写入 Bot Token 与 Signing Secret。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 38/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 60/100 ×0.15
适用场景
为 Cyrus 创建并配置 Slack 特定
解决思路
- 安全约束:禁止对 `~/.cyrus/.env` 或 `~/.cyrus/` 内任何文件使用 `Read`、`Edit` 或 `Write` 工具;只用 `Bash` 命令(如 `grep`、`printf >>` 等)操作 env 文件,避免密钥进入对话上下文;禁止从网页抓取、提取或读取 secret 值,改为引导用户手动复制。
- 检查已有配置:运行 `grep -E '^SLACK_BOT_TOKEN=' ~/.cyrus/.env 2>/dev/null`;若 `SLACK_BOT_TOKEN` 已设置,告知用户 Slack 已配置并跳过;重新配置需从 `~/.cyrus/.env` 删除 `SLACK_BOT_TOKEN` 和 `SLACK_SIGNING_SECRET` 后重新运行,然后跳到完成。
- 读取变量:运行 `grep '^CYRUS_BASE_URL=' ~/.cyrus/.env | cut -d= -f2-` 获取基础 URL(由 `setup-endpoint` 设置);从对话上下文获取 `AGENT_NAME` 和 `AGENT_DESCRIPTION`(由 orchestrator 的 Step 0 收集)。
- 构建 Manifest JSON:用实际值替换 `<AGENT_NAME>`、`<AGENT_DESCRIPTION>`、`<CYRUS_BASE_URL>`;严格使用给定模板;事件订阅路径必须是 `/slack-webhook`(不是 `/slack/events` 或其他),以匹配 Cyrus 代码库中 `SlackEventTransport` 注册的路由。
- scope 同步:此 scope 列表必须与 Slack App 配置以及 `https://github.com/cyrusagents/cyrus-hosted/blob/main/apps/app/src/lib/slack/constants.ts` 中定义的 scope 列表保持同步;若修改此处的 scope,应在该文件提出匹配修改,并更新依赖此 manifest 的线上 Slack App 配置。
- 构造 manifest 时包含:`display_information.name`=`<AGENT_NAME>`、`description`=`<AGENT_DESCRIPTION>`、`background_color`=`#00240e`;`features.bot_user.display_name`=`<AGENT_NAME>`、`always_online`=true;`oauth_config.redirect_urls`=[`<CYRUS_BASE_URL>/slack/oauth/callback`];`oauth_config.pkce_enabled`=false;`settings.event_subscriptions.request_url`=`<CYRUS_BASE_URL>/slack-webhook`;`settings.org_deploy_enabled`=false、`socket_mode_enabled`=false、`token_rotation_enabled`=false。
- user scopes 列表:`canvases:read`、`canvases:write`、`channels:history`、`chat:write`、`groups:history`、`im:history`、`mpim:history`、`users:read`、`users:read.email`、`reactions:write`、`search:read.public`、`search:read.private`、`search:read.mpim`、`search:read.im`、`search:read.files`、`search:read.users`。
- bot scopes 列表:`groups:read`、`app_mentions:read`、`assistant:write`、`canvases:write`、`channels:history`、`channels:read`、`chat:write`、`chat:write.customize`、`groups:history`、`im:history`、`im:read`、`files:read`、`files:write`、`mpim:history`、`reactions:write`、`search:read.files`、`search:read.public`、`search:read.users`、`users:read`、`users:read.email`、`mpim:read`。
- bot_events 列表:`app_mention`、`member_joined_channel`、`message.channels`、`message.groups`、`message.mpim`、`message.im`。
- 创建 Slack App 时始终用 "From a manifest" 流程,绝不用 "From scratch";决定浏览器自动化模式:1) 若有 `claude-in-chrome` MCP 工具 → 使用 Path A-1;2) 若安装 `agent-browser` 且连接 Chrome debug session → 使用 Path A-2;3) 否则 → 使用 Path B manual。
- Path A-1:使用 `mcp__claude-in-chrome__*` 工具操作用户现有 Chrome:导航到 https://api.slack.com/apps;点击 **Create New App**;在 modal 选 **From a manifest**;选择 workspace;点击 **Next**;选择 **JSON** tab 并粘贴 Step 3 中完全替换后的 manifest;点击 **Next**,review,点击 **Create**。创建后进入 Basic Information 页面;不要截图凭证页面;继续 Step 5。
- Path A-2:若 `agent-browser` 连接 Chrome debug session:运行 `agent-browser navigate "https://api.slack.com/apps"`;截图确认页面加载且用户已登录。
- 运行 `agent-browser click "button:text('Create New App')"`。
- 运行 `agent-browser click "button:text('From a manifest')"`。
- 截图查看 workspace picker,点击对应 workspace;若列出多个,询问用户哪一个;运行 `agent-browser click "button:text('Next')"`。
- 点击 **JSON** tab(如未选中):`agent-browser click "button:text('JSON')"`;用 JS 粘贴 manifest:`agent-browser eval "var editor = document.querySelector('textarea, [role=\"textbox\"], .ace_editor textarea, .CodeMirror textarea'); if (editor) { var nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLTextAreaElement.prototype, 'value').set; nativeInputValueSetter.call(editor, JSON.stringify(<MANIFEST_JSON>, null, 2)); editor.dispatchEvent(new Event('input', { bubbles: true })); 'pasted'; } else { 'editor not found'; }"`;若不行,尝试 `agent-browser click "textarea"`、`agent-browser keyboard "Control+a"`、`agent-browser type '<MANIFEST_JSON_STRING>'`;截图验证后点击 `agent-browser click "button:text('Next')"`。
- 截图验证 summary,点击 `agent-browser click "button:text('Create')"`;创建后不要截图凭证页面或尝试抓取 secret;继续 Step 5。
- Path B manual:指导用户:1. 去 https://api.slack.com/apps;2. 点击 **Create New App**;3. 在 modal 选择 **From a manifest**;4. 选择要关联的 **workspace**;5. 点击 **Next**;6. 选择 **JSON** 格式并粘贴以下 manifest。打印完全替换后的 manifest JSON 供用户复制;7. 点击 **Next**,review summary,点击 **Create**;继续 Step 5。
- Step 5:安装应用并收集凭证。应用创建后(任何路径),引导用户安装和收集凭证。代理不得从页面抓取、读取或提取 secret;由用户手动复制。
- 5a 安装到 Workspace:告诉用户:1. 在 Slack app settings 左侧 sidebar 去 **Install App**;2. 点击 **Install to Workspace**;3. 点击 **Allow**。若使用浏览器自动化 (A-1/A-2),代理可导航到 Install App 页面并点击按钮,但必须在安装完成后停止,且不要截图结果页面。
- 5b 添加凭证占位符:运行 `grep -q '^SLACK_BOT_TOKEN=' ~/.cyrus/.env || echo 'SLACK_BOT_TOKEN=' >> ~/.cyrus/.env`;运行 `grep -q '^SLACK_SIGNING_SECRET=' ~/.cyrus/.env || echo 'SLACK_SIGNING_SECRET=' >> ~/.cyrus/.env`。
- 5c 打开 env 文件供编辑:macOS 运行 `code --new-window ~/.cyrus/.env 2>/dev/null || open -a TextEdit ~/.cyrus/.env`;Linux 运行 `code --new-window ~/.cyrus/.env 2>/dev/null || xdg-open ~/.cyrus/.env`。
- 5d 引导用户复制凭证:告知用户:已打开 `~/.cyrus/.env`,需要粘贴两个值:1. **Bot User OAuth Token** — 去 app 的 **OAuth & Permissions** 页面,复制 **Bot User OAuth Token**(以 `xoxb-` 开头),粘贴到 `SLACK_BOT_TOKEN=` 后;2. **Signing Secret** — 去 app 的 **Basic Information** 页面,滚动到 **App Credentials**,点击 **Signing Secret** 旁的 **Show**,复制,粘贴到 `SLACK_SIGNING_SECRET=` 后;完成后保存并关闭文件。
- 5e 等待并验证:用户确认保存后,运行 `grep -c '^SLACK_BOT_TOKEN=.' ~/.cyrus/.env`;运行 `grep -c '^SLACK_SIGNING_SECRET=.' ~/.cyrus/.env`;两者必须返回 1(`=` 后的 `.` 确保值非空)。若任一返回 0,让用户检查文件。
- 完成提示:输出 ✓ Slack app created from manifest and installed;✓ Bot token and signing secret saved to `~/.cyrus/.env`。注意:事件订阅 `request_url` 在 Cyrus 实际运行前会无法通过 Slack verification challenge;Cyrus 启动后,去 app 的 **Event Subscriptions** 页面重新输入 URL 触发验证,否则 Slack 会自动重试。
适用边界 · 注意事项
- 不适用于已经设置 `SLACK_BOT_TOKEN` 且不需要重新配置 Slack 集成的场景。
- 不适用于没有 Cyrus 环境、无法访问 `~/.cyrus/.env` 或无法访问目标 Slack 工作区的场景。
- 不适用于需要完全自定义 Slack App 创建流程、OAuth 流程或非 manifest 配置的场景。