Skip to content

dsh-feishu-beacon

Verified

dsh-feishu-beacon · v0.2.5 · MIT · Web UI

DSH plugin that pushes agent progress and human-attention events to a Feishu (Lark) custom-bot webhook

Install

dsh plugin add dsh-feishu-beacon

Confirm the layer applied with dsh --profile default --dump-config — see the install guide.

Source

Tags

Creators

Readme

dsh-feishu-beacon

npm license downloads stars

English · 简体中文

把 DeepSeek Harness agent 的进展,以及那些需要你回来的时刻,推送到飞书群。

长时间运行的 agent 有两个麻烦:你不想一直盯着它,但一旦走开,又会错过它「没有你就无法继续」的那些时刻。这个插件同时解决这两件事——agent 会主动把自己的里程碑报给一个你配置的飞书机器人,而提问、授权请求和失败则无论 agent 是否记得上报都会被推送。

PROGRESS
Task: 修复不稳定的部署
Workspace: beacon-project
Time: 2026-09-21 14:20:03

第 2/4 步完成:问题出在重试定时器的竞态,不在部署脚本。

你会收到哪些通知

触发时机 收到什么
agent 到达它认为值得告知你的里程碑 它自己写的内容,标题为 PLAN、PROGRESS、DECISION 或 DONE
agent 需要你的回答 DECISION 卡片,正文首行为 Answer needed,包含每个问题与每个选项及其说明
agent 需要对敏感操作授权 DECISION 卡片,正文首行为 Authorization needed,包含工具名与原因
一次运行失败 Turn failed,包含错误信息

卡片类型严格只有四种——PLAN(任务拆解)、PROGRESS(完成关键步骤)、DECISION(需要你回到电脑前处理:做决定,或授权 agent 做不到的事)、DONE(交付了什么)。任何需要你动手的事都是 DECISION,无论它是提问还是权限请求;标题下方那一行会说明是哪一种。

Turn failed 是这四类之外的唯一一张卡片,它保留自己的颜色:一次跑挂的运行不是你能回答的决定,也不能被误当成决定。

每条都以交互卡片形式送达,标题栏颜色让你一眼看出是什么——也可以改成纯文本,见关于「Message format」。

运行成功时不会推送任何东西。 如果你做完一件事、手机却毫无动静,那正是它在正常工作:每次运行都汇报是噪音,而这个插件存在的意义就是避免噪音。

而且在你明确要求之前,它什么都不会推——一次只针对一个任务。 你坐在电脑前时并不需要手机通知,而插件无法判断你是否已经走开——只有你自己知道。所以默认是静默的:只有在当前这段工作被开启 watch 时才会推送。见观察一个任务。

观察一个任务

watch 就是你的一句"我要让它自己跑,有事告诉我"。它由 agent 在你的指令里识别出这个请求后开启,任务结束时自动关闭,所以你永远不需要记得去关掉通知。

用你自己的话开口就行,没有需要记住的关键词:

我要出去一下,你做的过程中随时告诉我 我走开了,有进展就发我 每完成一步跟我说一声

agent 从你的指令里读出这个请求,并在它发出的第一条消息上打开 watch。看起来像请求但其实不是的情况:

不算请求 原因
"模拟一个有交互的长任务" "长"本身不是请求
"修一下 dsh-feishu-beacon 这个插件" 提到插件名是在谈论工具,不是在要求被告知这次的工作
在一个使用本插件的仓库里干活 仓库不是你的指令
"接着之前那个继续" 之前的请求授权的是之前的任务,不是这一个

读这个意图是 agent 的事,插件不再用关键词去代替它判断。 早先的版本要求你的指令里出现字面的 beacon,那个判定同时在两个方向上都错了:这个词就在本包的名字里,所以"修一下 dsh-feishu-beacon 这个插件"会授权一次通知;而任何机制都无法把这种"提及"和"请求"区分开。

插件仍然守住的是后果:一个 watch 只管一个回合,它是唯一能让消息发出去的凭据,而设置页里的开关优先级在它之上。

从被授权那一刻起:

你会收到 直到
agent 上报的每一个里程碑 本回合结束
每一个需要你回答的问题 本回合结束
每一个授权请求 本回合结束
任务失败时的失败信息 本回合结束

任务结束时,watch 随之结束。 watch 是为它被要求的那一个回合开启的,回合边界就是它的到期时刻——没有东西需要被关闭,也没有东西需要你记着。失败是这个回合能说的最后一句话,它会在控制权交还给你之前推送,所以"任务崩了"恰恰是仍然能到达你的那一条。

在任务中途回答 agent 提出的 decision,不会结束 watch。它还在做同一个任务,只是需要你先回一句。

watch 是 agent 做出的判断,不是插件替你按下的开关:agent 必须识别出你要求被持续告知,才会开启一个。这也是为什么同一回合里后来的一条指令关不掉它——回合边界是唯一的关闭点,agent 自己也无法在中途结束上报。

一个任务,一份授权

watch 的作用域是一个任务——agent 交出控制权之前所做的那段工作。你的下一条指令重新从静默开始,即使上一个任务的 watch 从没被关闭过,所以你永远不会因为一个"活过了头的 watch"而继续收到通知。下一个任务要收,就再说一次——用你自己的话。

开始之前

  • 已安装 dsh CLI,并且有 web profile。
  • 一个你有权限添加机器人的飞书群。

安装

dsh plugin --profile web add dsh-feishu-beacon

然后重启 harness。设置页面只在启动时加载,所以正在运行的 harness 还看不到它。

配置步骤

1. 在飞书里创建机器人

飞书官方文档有完整的图文步骤——自定义机器人的设置入口在哪、如何复制 Webhook 地址、签名校验怎么工作:自定义机器人使用指南。

简版步骤:

  1. 打开你想接收通知的飞书群。
  2. 设置 → 群机器人 → 添加机器人 → 自定义机器人。
  3. 起个名字,复制它给出的 Webhook 地址。
  4. 如果机器人启用了签名校验,把 签名密钥 也复制下来。

2. 填进插件

打开 设置 → Feishu beacon,粘贴 Webhook 地址。地址必须以 https:// 开头。如果你的机器人校验签名,把密钥也粘上;不校验就留空。

这里没有保存按钮——你输完即已写入,字段下方的状态行会告诉你是否生效。如果某个值被拒绝,它会留在输入框里并附上原因。

3. 点「Send test」

Send test 是页面上唯一的按钮。它会立刻用页面当前显示的值发一条消息,因此一次性证明三件事:地址对、密钥对、你的手机能看到这个群。这条消息一两秒内就会出现在飞书里。

如果页面报错,见如果它不工作。

4. 告诉 agent 去汇报

里程碑上报是 agent 自己的判断,所以需要你交代一次——用你自己的话:

我出去一下,你做的过程中随时告诉我

提问、授权请求和失败不需要你另外交代:只要 watch 开着,不管 agent 记不记得汇报,它们都会被推送。

可以调什么

全部都在同一个设置页上,而且全部立即生效,不需要重启任何东西。

设置项 作用
Enabled 总开关。关闭时完全不推送。
Notify on questions agent 需要你回答时推送。
Notify on approvals agent 需要授权时推送。
Notify on failed turns 运行失败时推送。
Title prefix 加在每个标题前面,用来区分不同机器/环境,例如 [HOME-PC] PROGRESS。
Host URL in messages 加一行 Open at:,指回你的 harness。详见下文。
Max characters 整条消息长度上限,默认 3000。超出部分会被截断并以 ... 结尾。
Message format card(默认)或 text。详见下文。
Signing secret 仅在机器人校验签名时需要。
Webhook URL 机器人的 Webhook 地址。

三个通知开关是故意独立的:关掉一个不会影响另外两个。

两个凭据字段只显示 stored 或 not set,不显示值本身;只有在确实存了凭据时,旁边才会出现 Clear。你的 Webhook 和密钥保存在 harness 上,永远不会被发回浏览器。

关于「Message format」

消息以两种形式之一送达:交互卡片或纯文本。

  • card(默认)——彩色标题栏、一行安静的元信息(任务与时间),然后是正文。颜色让你在读内容之前就知道这是什么:失败红色、待决橙色、完成绿色、计划与进展蓝色。
  • text——全部挤在一个纯文本块里,也就是早期版本的形式。

你不需要一次选对。 用 card 时,如果你的群不接受交互卡片,插件会把同一条消息改用纯文本重发,所以格式问题绝不会让你丢掉通知。发生这种情况时 Send test 会告诉你——消息仍然送达了,但页面会说明卡片未被接受,你可以改成 text 不再尝试。

如果你就想要最朴素的形式,或者不想在卡片被拒时多发一次请求,那就选 text。

关于「Host URL in messages」

这个字段只控制一行——Open at:——其它什么都不影响。它的意义在手机上:飞书通知本身不携带任何会话信息,那一行就是你点回 harness 的入口。

  • 在跑 harness 的同一台机器上看通知? 留空即可。它会回退到 DSH_WEB_URL,harness 自己会设置。
  • 在手机上看通知? 回退值通常是 http://127.0.0.1:<端口>,这个地址在手机上指向手机自己,点了打不开。请填一个手机能访问的地址——同一 WiFi 用局域网 IP,外网用隧道/反代地址。

当这个字段和 DSH_WEB_URL 都没有设置时,这一行会被直接省略。

从 0.1.x 升级

0.2.x 要求 dsh 0.2,0.1.1 要求 dsh 0.1.x——两者互不兼容。 跑 dsh 0.2 就装 0.2.x;还在 dsh 0.1.x 就留在 0.1.1。

配置存放位置也变了:现在存在当前 profile 的 patch 层里,不再存于 settings.yaml。升级后请重新填入 Webhook 地址和签名密钥。

如果它不工作

装完后设置里找不到这个插件。 dsh plugin add 即使在安装失败时也会报成功,而没被登记为 bundle 的包永远不会加载。检查 $DSH_HOME/profiles/web/package.json,确认 dsh-feishu-beacon 同时出现在 dependencies 和 dsh.profile.bundles 里。如果没有,重跑安装并留意 pnpm 的报错。最常见的原因是 $DSH_HOME/profiles/web/pnpm-workspace.yaml 里有个未决定的 allowBuilds: 条目——把它答成 false(对已发布的包来说构建脚本没有用),然后重新安装。

「Send test」失败。 确认 Webhook 地址以 https:// 开头;如果机器人校验签名,确认密钥与机器人一致。页面上的 502 表示飞书那边拒绝了这条消息。

我没收到通知。 先看最可能的原因:你并没有要求过。上报是静默的,直到 agent 从你的指令里识别出"请持续告知我",并且在任务结束时停止——所以一条你从没提过这个要求的任务什么都不会推,而仅仅提到本插件名也不会让它推。按顺序检查:你真的说了要被持续告知吗?然后确认这一次应该收到:运行成功是不会有任何推送的。再检查 Enabled 与对应的 Notify on… 开关。如果在 watch 开着时一次运行失败却没收到,那就是推送本身失败了——harness 日志里会有一条 warning,而绝不会是 error,因为推送失败不允许影响你的会话。

agent 说没有 watch,所以不能上报。 那是插件在拒绝一次没有 watch 的推送。它不是在要你换个说法:如果你想要上报,用你自己的话说明就行。

通知收到了,但 Open at: 链接打不开。 那个地址从你看消息的设备访问不到。见关于「Host URL in messages」。

消息被截断了。 超过 Max characters(默认 3000)就会截断。想接更长的内容可以调大,但请注意:手机上过长的消息反而没用,而手机正是这个插件的目标场景。

已知限制

  • 回复不会回来。 自定义机器人 Webhook 只能发。你无法在飞书里回答问题——消息会提示你回到 harness。
  • 不会重试。 一次失败的推送就是永久丢失。这也是为什么工具路径会把失败告诉 agent,而只有事件路径保持沉默。
  • 极长会话可能重复收到同一条通知。 去重是有容量上限的,超过之后会从头开始。
  • 飞书必须能访问到 Webhook,你的 harness 也必须能访问飞书。 企业网络只要挡住任一方向,消息就会静默丢失——依赖它之前先用 Send test 验证。

卸载

dsh plugin --profile web remove dsh-feishu-beacon

这会把包移除,但不会把它的名字从 profile 的 bundle 名单里删掉:dsh 只在安装时协调 dsh.profile.bundles,所以卸载会留下那个名字,下次启动就会尝试加载一个已经不存在的 bundle。请打开 $DSH_HOME/profiles/web/package.json,把 "dsh-feishu-beacon" 也从 dsh.profile.bundles 里删掉,然后重启 harness。

你的 Webhook 地址与签名密钥仍留在 profile 的配置文件(cordis.patch.yml)里。如果想让它们一并消失,把那行也删掉。

给开发者

插件的设计说明、目录结构、测试方式与变更记录都在 README.dev.md —— 只有英文版,因为它面向的是改这个插件的人,而不是装它的人。

许可证

MIT