Flue + Slack实战:5分钟在团队频道搭一个对话Agent
【免费下载链接】flueThe sandbox agent framework.项目地址: https://gitcode.com/GitHub_Trending/flue1/flue
Flue 是一个开源的 TypeScript 沙箱 Agent 框架(The sandbox agent framework),而 examples/slack-channel 正是它的官方 Slack 频道示例。本教程将带你用 Flue 的@flue/slack频道包 + 一个真实示例,在5 分钟内把 AI 对话 Agent 接入团队 Slack 频道:在频道里 @ 一下机器人,它就会在对应线程里自动回复。签名验证、Webhook 样板代码全部由框架搞定,你只写业务逻辑。
一、Flue 是什么?为什么适合做 Slack Agent
Flue 的核心理念只有一句话:Agent 就是一个函数。
用几个 Hook 就能给 Agent 装配完整的能力,官方称为"可编程 Harness":
| Hook | 作用 |
|---|---|
useModel() | 指定大模型,如anthropic/claude-haiku-4-5 |
useTool() | 挂载类型化工具(调 API、发消息等) |
useInitialData() | 读取实例创建时携带的结构化数据 |
Slack 场景里最关键的三个卖点:
- 会话连续性:每个 Slack 线程对应一个稳定的 Agent 实例,上下文自动延续
- 签名验证内建:精确字节签名 + 5 分钟时间窗 + URL 验证,全部由 packages/slack 包自动处理
- 线程级隔离:
channel.instanceId(thread)生成规范化的线程标识,不同线程互不串线
二、准备工作:创建项目与 Slack 凭据
2.1 获取代码
仓库内置了可直接运行的 Slack 示例,克隆后即可使用:
git clone https://gitcode.com/GitHub_Trending/flue1/flue示例位于 examples/slack-channel/,依赖声明见 package.json:核心是@flue/runtime、@flue/slack和官方@slack/web-api客户端。
💡 如果要在已有项目中添加 Slack 频道,可参考官方蓝图 channel--slack.md,它给出了完整的接入模板。
2.2 创建 Slack App,拿到两个密钥
在 Slack 应用管理后台创建你的 App 并启用Events API,然后配置两个环境变量(启动应用时必需):
| 环境变量 | 用途 |
|---|---|
SLACK_SIGNING_SECRET | 验证 Slack 请求签名的精确字节 |
SLACK_BOT_TOKEN | 机器人出站调用(发消息)的凭据 |
构建与类型检查不需要真实凭据,但应用启动时会校验缺失并报错,见 slack.ts 的requiredEnv处理。
三、五步搭建:从 @提及 到线程自动回复
第 1 步:创建频道模块 channels/slack.ts
频道模块是整个接入的中枢。核心调用只有一个:createSlackChannel(),完整实现见 slack.ts。它做了三件事:
- 验签:对请求原始字节做签名校验,拒绝超过 5 分钟的时间戳,URL 验证请求自动应答
- 监听 @提及:收到
app_mention事件后提取频道 ID 和线程时间戳 - 分发给 Agent:调用
dispatch(Assistant, {...}),用channel.instanceId(thread)派生稳定的线程实例 ID
框架还内置了一个线程回复工具replyInThread,让 Agent 能精确回复到绑定线程,见 slack.ts:
// Agent 获得一个窄范围的工具:只能回复自己绑定的线程 export function replyInThread(ref: { channelId: string; threadTs: string }) { return defineTool({ name: 'reply_in_slack_thread', async run({ data }) { return await client.chat.postMessage({ channel: ref.channelId, thread_ts: ref.threadTs, text: data.text, }); }, }); }🔒 安全设计:频道 ID、凭据被刻意排除在工具参数之外——Agent 只能回复"自己"的线程,这是示例有意为之的应用层策略。
第 2 步:编写 Agent:agents/assistant.ts
Agent 就是一个带'use agent'指令的函数,完整代码见 assistant.ts:
'use agent'; export function Assistant() { useModel('anthropic/claude-haiku-4-5'); const data = useInitialData<v.InferOutput<typeof initialDataSchema>>(); useTool(replyInThread(data)); // 挂载线程回复工具 return `Reply in the bound Slack thread when appropriate. ...`; } Assistant.initialData = initialDataSchema;initialData携带了线程的频道 ID、线程时间戳、发起人等信息——Agent 直接读结构化数据,无需解析实例 ID。
第 3 步:挂载路由 app.ts
频道只在app.ts挂载处提供路由,只需两行,见 app.ts:
app.route('/agents/assistant', createAgentRouter(Assistant)); app.route('/channels/slack', channel.route());挂载后自动生成三个可用端点:
POST /channels/slack/events—— 接收 Events API 事件(必选)POST /channels/slack/interactions—— Block Kit 交互(按需)POST /channels/slack/commands—— 斜杠命令(按需)
不需要的回调直接省略,对应路由就不存在。
第 4 步:配置 Vite 构建
Flue 通过 Vite 插件工作,vite.config.ts 只有三行:
import { flue } from '@flue/vite'; export default defineConfig({ plugins: [flue()] });第 5 步:在 Slack 后台填入事件 URL,开始对话
在 Slack 应用后台把Event URL配置为你的https://<你的域名>/channels/slack/events,订阅app_mention事件,把机器人拉进频道。然后:
你:@FlueBot 帮我总结一下昨天的站会要点 FlueBot:(在同一线程内)好的,我来梳理……✅ 完成!整个接入就是:建频道 → 写 Agent → 挂路由 → 配 URL。
四、生产环境要留意的 3 个细节
- 重试去重:Slack 可能对失败或缓慢的投递进行重试。需要唯一性的场景,应在分发时用
idempotencyKey: payload.event_id声明投递名,重复投递会收敛到同一次提交而非触发第二轮对话 - 实例 ID 不是授权凭证:
slack:v1:团队:频道:线程只校验语法不校验权限,任何直接暴露 Agent 的路由都要自行鉴权 - 短生命周期能力别外传:
trigger_id、response_url等字段只在受信请求处理内使用,切勿写入分发数据、模型上下文或持久化存储
五、常见问题
@机器人没有反应?按顺序排查:事件 URL 是否可达、SLACK_SIGNING_SECRET是否与环境一致、服务器时钟是否在 5 分钟窗口内、机器人是否已加入该频道。
想支持按钮交互或斜杠命令?在 slack.ts 中取消interactions与commands回调的注释,并在 Slack 后台配置对应 URL 即可。
Agent 和频道互相 import 会不会循环依赖?不会。示例中频道 import Agent、Agent import 频道,是安全的——导入的绑定只在事件回调和 Agent 函数体内延迟读取。
六、相关资源索引
| 资源 | 路径 |
|---|---|
| Slack 完整示例 | examples/slack-channel/ |
@flue/slack包 | packages/slack/ |
| Slack 接入蓝图 | blueprints/channel--slack.md |
| 频道总览蓝图 | blueprints/channel.md |
| 框架文档站点源码 | apps/docs/ |
Flue 还有 Teams、Discord、Telegram、GitHub 等十余种频道包,接入方式与本文完全一致。掌握这套"频道 → 分发 → Agent → 线程回复"的模式后,把 AI 助手铺到你的每个协作工具,只需要复制粘贴级别的成本 🚀
【免费下载链接】flueThe sandbox agent framework.项目地址: https://gitcode.com/GitHub_Trending/flue1/flue
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考