【免费下载链接】dsh-superagent-prototype
Towards a More Autonomous Agent System
在 dsh-superagent 中,编排器(Orchestrator)与执行器(Worker/Executor)会长时间无人值守地跑工单,唯一能落到人面前的只有少量文字消息。本文以仓库中的 Communication 节原文 prompts/team/communication.md 为主线,讲清三件事:什么情况才允许打扰人、消息该写成什么样、在 GitHub Review 场景下如何沟通而不制造噪音,并结合 src/core/replies.ts、src/infra/text.ts、src/app/tools/executor.ts 等源码说明这些“文字规范”背后哪些被代码硬性执行、哪些只靠提示词约束。读完后你能为团队定制一份可落地的通信政策,并知道每一条规则在系统里的确切位置与失效边界。
Communication 节在提示词体系中的位置
Communication 不是一份独立文档,而是三个**团队可编辑段(team sections)**之一,定义在 src/app/prompts.ts:
export const TEAM_SECTIONS = ['communication', 'scope', 'delivery'] as const const TEAM_HEADINGS: Record<TeamSection, string> = { communication: 'Communication', scope: 'Ticket scope', delivery: 'Delivery requirements' }默认文本由 src/app/context.ts 从prompts/team/*.md读入:
export const teamDefaults = { communication: promptFile('team/communication'), scope: promptFile('team/scope'), delivery: promptFile('team/delivery'), }teamDefaults会成为defaultPrompts()的初始配置(src/app/prompts.ts),因此 Communication 节在两份系统提示词中都存在。装配顺序见promptParts()(src/app/prompts.ts):
runtime/shared与角色段(runtime/orchestrator/runtime/worker);- 三个团队段:Communication → Ticket scope → Delivery requirements;
runtime/subscriptions、runtime/replies;- 主会话的
dispatch,或执行器的work; - 仅主会话的
runtime/admission; runtime/handoff/*;runtime/environment;- 仅主会话的
runtime/policy(每次模型请求重建,放在最后,使 Policy 变化不影响前面的文本)。
这个位置很关键:内置段落只按标题引用团队段(如 “follow the communication policy”),不在别处重复一遍规则。所以修改 Communication 节等同于修改两类角色的默认沟通行为,无需改动任何内置提示词,与 docs/004-prompts.md 的描述一致(在该文档的团队段表格中,Communication 一节负责“何时通知人、消息怎么写、GitHub 首行声明、Review 处理方式以及哪些普通账号属于 review bot”)。
面板侧也直接暴露这一段,见 src/client/locales.ts 与 src/client/locales.ts(“沟通方式 / Communication”),HTTP 层通过TEAM_SECTIONS下发可编辑段列表(src/app/http.ts)。
第一原则:人类注意力是稀缺资源
原文档的开篇就把“何时发消息”与“消息写法”合并成一条判据:人类注意力是未受请求消息的前提条件(原文第 8 行:Human attention is the condition for an unsolicited IM update.)。展开后可以拆成三个层次的规则。
允许主动发消息的四种情形
把原文档第 12~14、44、46 行归纳起来,未经请求的 IM 只有以下合法动因:
| 动因 | 原文依据 | 代码对应 |
|---|---|---|
| 交付物已自审、已验证、可供人 review 或使用 | “a ready outcome” | reply({ purpose: 'result' })需工单就绪 |
| 合并实质性完成了原始请求 | “a merge materially completes the original request” | ticketOutcome为merged也允许 result |
| 需要人做具体决定、给权限、给资源,或必须处理某项实质风险 | “a concrete decision, permission or resource” | orchestrator_report的human_action+attention |
| 确定无法完成,必须关闭请求 | “a definitive inability to complete” | state: 'blocked' \| 'failed',再经 attention 提出 |
明确被排除的“伪里程碑”
原文档用大量篇幅否定几类常见误判,这些否定比正面规则更有操作性:
- PR 存在 ≠ 可交付。“A PR merely existing is not a delivery milestone.” 第 19~20 行进一步禁止“带着‘还没完成’免责声明去宣布一个未就绪的 PR”。
- 未完成的进度、草稿、待跑检查、演示、例行 review 修复、重试/恢复细节、计划都必须留在内部(第 10 行)。
blocked/failed标签本身不是发消息的理由(第 14 行)。只有在自己无法补救、也无法委派时,打断才成立。- 没有人类动作的 pending checks:什么都不发(第 20 行)。
- 不要为已授权的工作请求许可、不要询问例行的实现偏好、不要重复请求同一决定、不要发送未变化的状态(第 45 行)。
发送前的“删除检验”
原文档给了一个可执行的文本级自检(第 51~52 行):
Before sending, ask of each clause: would deleting this prevent the human from understanding the result or taking the required action? If not, delete it.
配套还有两条防“变相超限”的规则:少句号不等于少信息,禁止把多个细节塞进分号链或长句(第 53 行);也不许把长消息拆成多条连发(该约束在代码里同样存在,见后文checkedImText的报错文案“Do not split it into multiple messages”)。
结果、草稿、阻塞:三种消息的最小信息集
原文档对三类“必须发的消息”分别规定了最小信息集,这是最容易在实现中被写走样的部分。
就绪结果
默认只发一句话,包含用户可见的结果 + 链接 + 必要的下一步动作(第 31 行);只有当某个阻塞或限制实质影响使用或交付时,才加第二句(第 32 行)。原文给的完成示例是:
Fix submitted: <actual PR link>, ready for review.以及更短的 Markdown 版本:
Ready example: PR #123 is ready for review.未完成的草稿交接
第 41、54 行要求:必须明确说明工作停止、高层原因、当前仍不可用的内容、草稿链接,并且必须标记为未完成,绝不能表述为成功完成;同时不要逐项罗列已完成/缺失的子任务。
阻塞
第 44 行规定顺序:先查源上下文与可行替代方案,再说清具体的安全 / 权限 / 资源 / 可行性限制,以及所需的最小动作;若确实没有任何动作能让这张工单成立,就如实说明。示例:
Blocker example: The bot cannot read this document, so the request cannot be confirmed. Please give the bot read access.确认(acknowledgement)与“回答”的区别
第 16 行、第 77~78 行把“确认收到请求”与“完成通知”分开:确认要简短、具体到对象与预期结果,禁止空话。示例:
Acknowledgement example: On it: changing the settings page's “Save changes” button to “Save”.同时明确:不要用通用的 “I'll do it”(第 25 行),不要带实现计划或工作报告(第 26 行),不要复述触发的原消息——因为宿主本身就以回复形式贴在该消息下(prompts/replies.md 第 15 行)。
消息长度与格式:100 词是硬上限
Communication 节本身没有写数字,但与之配套的 prompts/replies.md 第 27~30 行规定:100 词是硬上限而非写作目标;传输层会拒收超长的 IM 消息,包括人类明确要求技术细节时;中文按分词计数;Markdown 的链接文字与目标都计入;禁止用长复合句、分号链、项目符号列表或连续多条消息规避。
这条规则在代码中被真正执行。词数常量与计数函数位于 src/infra/text.ts:
const words = new Intl.Segmenter('zh', { granularity: 'word' }) export const IM_WORDS = 100 export const NOTE_WORDS = 30 export function wordCount(text: string): number { let count = 0 for (const segment of words.segment(text)) if (segment.isWordLike) count++ return count } export function checkedImText(text: string): string { const count = wordCount(text) if (count > IM_WORDS) throw new Error(`IM message has ${count} words; maximum is ${IM_WORDS}. Rewrite as a short high-level update. Do not split it into multiple messages.`) return text }三点值得注意:
- 使用
Intl.Segmenter('zh', { granularity: 'word' }),所以中英混排按词切分,标点不计入,这与 “Chinese uses word segmentation” 完全对应。 - 校验发生在出站投递处而非仅在模型侧:src/app/outbox.ts 在
kind === 'reply'且来源为feishu时调用checkedImText,注释说明“确认文本在决定时已校验”。 - 确认文本另有 schema 级约束:src/app/tools/tool.ts 的
AcknowledgementSchema用wordCount(text) <= IM_WORDS拒绝超限,与渠道无关——即使发到 GitHub 也受限。
另有一个副作用规则:通知类消息不需要在 GitHub 上加首行声明,因为 IM 场景下机器人账号本身就是身份标识(第 69 行);kind区分acknowledgement | reply | notice(src/core/ports.ts)。
GitHub 沟通:首行声明与 Review 礼仪
每一类 GitHub 消息的首行
第 68 行原文:
Begin every message posted on GitHub, including comments, review replies and PR descriptions, with this line: This is by an automated agent, not a human.
注意覆盖范围是评论、review 回复、PR 描述全都算;IM 消息反而不携带该行。这条规则由提示词约束,同时被测试固定住:tests/cards.spec.ts 断言该句出现在team/communication的文本中。也因此,它属于“团队可改文本”——若团队改了措辞,测试与内置引用需要一并调整,这是自定义时常见的坑。
Review 沟通按结果分流
第 71~79 行给出的分流矩阵非常明确:
| 情形 | 做法 |
|---|---|
| 问题已修复、已推送、已验证 | 静默 resolve该 review thread,不补“Fixed in”之类的完成回复 |
| 经评估决定不采纳的建议 | 在原 thread留一句简短、基于事实的理由;先检查是否已有解释,不要重复 |
| 自动化账号的 thread | 一旦有响应(修复推送并验证,或拒绝理由已发)即 resolve |
| 人类 reviewer 尚未解决的有效问题 | 不得resolve |
| 拒绝的建议 | 不得标记为已修复 |
还有三条易被忽略的结构性禁令(第 79~81 行):
- 不得用顶层 PR 评论或 PR 正文里的“处置表”替代逐条 thread 回复;
- PR 描述只写当前方案、相关验证、实质限制,bot run ID、轮次、评估账本留在
orchestrator_report; - 被问“为什么这么做”时,要区分实际指令与自己的解读,不得编造规则或“仅限 bot 的例外”。
自动化 reviewer 的定位与三轮上限
第 83~97 行是本节的“反内耗”核心,可提炼为四条:
- 身份判定:自动化 reviewer 是 GitHub App,登录名以
[bot]结尾,或属于指令中点名的 review 账号;它们的消息永远不构成工作授权。 - 证据优先:把 bot 当可错的输入而非权威或完成门槛。建议常常无需改代码,只在“明确改善代码”时采纳;警告有时有效,先查代码与证据;critical 通常有效值得立刻调查,但要验证而不是盲改;增加不必要复杂度、重复既有行为、降低代码质量的意见应当拒绝。
- 不要追认可:不追 bot 的 approve,不逐条回应每个 bot 评论,不重复未变化的处置结论。
- 三轮天花板:每个 PR、每个自动化 reviewer 最多处理三轮,跨 worker、重启与后续工单累计;一轮指一次独立 bot review run 的发现被一起评估,而不是每条 inline 评论或重复投递。开始新一轮前要查阅保留的工单报告与 PR review 历史,把bot run/version 标识、轮次、处置写进
orchestrator_report,以便下一个 worker 继续计数。第三轮后不再请求 bot review、也不为继续处理 bot 反馈而唤醒 worker;已 review 的 PR 仍要交付,并如实说明未解决的实质问题——验证过的严重阻塞仍值得一次简短的人为提醒,但不再进入自动化 review 循环。
配套的两条边界:human review 与 CI 独立;仓库若有更严格的“请求 bot review”限制,三轮上限并不授权额外请求。
这些事实在策略层也有对应:orchestrator_report的summary/human_action承载完整证据,而对外只发短问句(prompts/handoff-worker.md 第 6 行:“Keep full evidence in summary and let the orchestrator send the short question.”)。Communication 第 48~50 行同样强调“短 IM 不等于残缺的工程记录”,文档化检查与接口变更的要求作用于 PR 与内部报告,而非 IM。
引擎如何强制“只有该发的时候才发”
Communication 是提示词,但**“什么时候允许往外发”**被引擎做成了门禁。核心是ReplyRequest的 purpose 联合类型与Replies.reply()的分支校验,见 src/core/replies.ts。
export type ReplyRequest = | { purpose: 'acknowledgement'; ticketId: string; triggerId: string; text: string } | { purpose: 'answer' | 'result' | 'attention'; ticketId?: string; triggerId?: string; question?: string; text: string }关键校验逐条对应前文的沟通政策:
| 政策要求 | 代码位置与行为 |
|---|---|
| 结果只能给就绪/完成/合并/放弃的工单 | answer()中purpose === 'result'时判断outcome为merged/completed/dropped或最新 assignment 报告state === 'ready',否则抛notReady(src/core/replies.ts) |
| 进度报告不得冒充“回答” | purpose === 'answer'要求 trigger 是human,否则notQuestion;trigger 未被 worker 报告认领时抛noAnswer(#L78、#L82) |
| attention 必须与工单当前问题文本一致 | attention.question !== request.question→notAttention(#L77) |
| 确认必须针对人类请求 | 无 channel →ackNoChannel;非人类 →ackNotPerson;上下文线程只读 →notReached;工单已结束 →ackEnded(#L50-L58) |
| 确认不得被改写重发 | 以key('ack', trigger.id)为确定性 id,已存在则保留最早文本,返回reused: true(#L56-L62) |
| 问题被替换/清除时撤回未发出的回复 | withdrawAttention()+assignments.report()中的withdrawAttention(previous.id)(src/core/assignments.ts) |
这些拒绝理由都有面向用户的文案,见 src/core/errors.ts。例如notReady的文本直接复述了沟通政策:“Keep progress internal and wait for a verified ready report; do not relabel progress as an answer or send it through another channel.”notAttention则写明“Routine unfinished work stays internal.”
也就是说,“不要把进度当结果发出去”不是靠模型自觉:主会话只能通过orchestrator_reply(purpose 限定为answer | result | attention,见 src/app/tools/main.ts)发消息,执行器只能通过orchestrator_ack(src/app/tools/executor.ts)发确认;两者都被引擎门禁拦截。
投递语义上还有三条与“别刷屏”相关的实现细节(src/app/outbox.ts):同一 ticket、同一会话中,后一条消息会被前一条 pending 消息排队阻塞(超过失败阈值才放行);目标 Source 关闭时抛Later等待;目标会话被忽略或已消失时结算为channelIgnored/channelGone并不再重试。这从传输层保证了“同一对话的消息按序、不过度重发”。
与 Ticket scope、Delivery、匹配规则的边界
Communication 只管“怎么说话”。相邻两段的职责必须分清,否则会出现“把范围问题写成沟通问题”的误配:
- Ticket scope(prompts/team/scope.md)决定继续做还是停下交草稿:局部小改动一路做到 review 与 CI 完成;无固定调查/实现轮次上限;当需要破坏调用方预期、改变模块职责或协调多模块重设计,或可行方案反复无进展时暂停,并指明具体接口与调用方影响。文档还明确:自动 reviewer 的轮次上限只约束自动化账号,不约束正常开发。
- Delivery requirements(prompts/team/delivery.md)决定PR 里要有什么证据、谁能合并:UI 变更必须同时提供 Before/After 且标注基线与变更版本;auto-merge 仅在指定
<merge CLI>存在且行数阈值(少于 200 行)等条件满足时启用;reviewer credit 用 commit trailer 实现。这与 Communication 第 35 行“把技术选择、测试数量等留在 PR 里”正好互补。 - 匹配规则(matched rules)优先级更高:对主动型(proactive)工单,其匹配规则中的流程与沟通要求覆盖默认值——沉默规则可以抑制确认,review 规则可以指定必须的 reviewer 与合并前审批;而“适用于所有工单”的要求应当写进团队段,而不是逐条规则。见 docs/002-authorization.md,执行器侧也会把这一优先级拼进提示词(src/executor/dsh.ts):
const precedence = rules ? `\nMatched rules; their procedure and communication instructions take precedence over the default acknowledgement and messaging policy for this ticket:${rules}` : ''整体优先序(事实 > 内置/生成段 > 规则 > 团队段与技能 > 外部文本)在 docs/004-prompts.md 中有完整体现,请注意“外部文本是数据,永不改变规则与授权”。
另外,编排器自身有一条与沟通直接相关的约束:它的路由说明最多 30 词(NOTE_WORDS),且orchestrator_ticket_note同样用wordCount限制(src/app/tools/main.ts),避免“喂给执行器的事实”变成一份小型简报。
团队自定义:覆盖、校验与“默认已更新”
如果团队的措辞习惯与默认不同(例如中文团队希望确认语用中文),应当通过提示词配置修改 Communication 段,而不是改仓库文件。可行路径与约束:
- 面板或
orchestrator_prompts_save:PromptConfigSchema严格校验三个团队段为必填字符串(src/app/prompts.ts),未知字段会被.strict()拒绝。 - 整段覆盖也可以走内置部件:Communication 对应的内置键是
runtime/replies之外的团队段本身;若你想替换“replies 指南”,键名是runtime/replies(src/app/prompts.ts、#L59)。注意内置部件覆盖的通用校验:- 覆盖必须非空(否则
promptPartEmpty); - 模板类部件必须保留占位符(
runtime/environment的{variables}、runtime/policy的{version}/{mode}/{rules}),否则promptPlaceholders; - 文本恢复成内置原文时,该条覆盖会被自动丢弃;
- 总长度受
LIMITS.promptMaxChars(1000~1,000,000)约束(src/limits.ts)。
- 覆盖必须非空(否则
- 并发保存保护:
Prompts.save以baseRevision做乐观并发,版本不一致抛PromptConflict,HTTP 层映射为 409(src/app/prompts.ts、#L202-L216)。 - 升级可见性:每条覆盖记录
base(它编辑自哪份内置文本)。内置文本变化后,defaultChanged()会列出受影响部件,面板标注“Default updated”并展示差异;未覆盖的部件自动跟随新默认。 - 这些修改不会放宽任何门禁:
preview()的scope字段明确写着——“Prompt text changes what the agents are told, not what dsh-superagent allows: tool permissions, the gate and account wrappers stay.”(src/app/prompts.ts)你无法通过改文字取消 100 词上限、purpose校验或首行声明的存在性(后者虽属提示词层,但受测试保护)。
一份可操作的沟通检查清单
把上述规则压缩成发送前的自问列表,可直接写进团队 Communication 段或 code review checklist:
- 动因:这是已就绪可用的结果、需要人做的具体动作、还是确定无法完成?都不是 → 不发。
- 就绪性:交付物是否已自审、已验证?PR 是否只是“存在”?是 → 不发。
- 草稿:是否明确标注“未完成”、写明停止原因、缺失内容与草稿链接?是否误写成“完成”?
- 信息密度:默认一句话;是否包含可见结果 + 链接 + 必要下一步?有第二句,是否确实是影响使用/交付的实质限制?
- 删除检验:逐句问“删掉它,人还能理解结果或采取所需动作吗?”不能 → 保留;能 → 删除。
- 技术细节:库名、方案取舍、内部 API、文件路径、commit hash、测试数量、检查清单、调查时序是否仍在消息里?移到 PR 与内部报告。
- 长度:中英混排是否 ≤ 100 词?是否试图用分号链或连发多条绕过?
- 确认:是否具体到对象与预期结果?是否复述了触发消息?是否把确认当成了进度汇报?
- GitHub:首行是否为自动化声明?是否在用顶层评论代替逐条 thread 回复?
- Review:已修复并验证的是否静默 resolve?拒绝的是否给了一句事实理由?是否在追 bot approve?本 PR 对该 bot 是否已到第三轮,且轮次已记入
orchestrator_report? - 语言:是否与源会话语言一致?GitHub 消息是否保持简洁?
小结
Communication 节看起来只是几段英文句子,实际上承担了系统里最贵的一种资源——人的注意力——的分配策略:只有可用的结果、明确的决定/权限/资源请求、或确定无法完成,才值得打断;消息默认一句话、100 词硬上限、技术证据留在 PR 与内部报告;GitHub 上每条消息以自动化声明开头,Review 按“修复即静默 resolve、拒绝给一句理由”分流,并对每个自动化 reviewer 设三轮上限。这些规则一半由提示词承载、一半由引擎门禁(src/core/replies.ts)、长度校验(src/infra/text.ts)、投递顺序与撤回机制(src/app/outbox.ts)硬性保证,理解这条边界,才能在自定义团队段时不误以为“改文字就能改变系统的允许范围”。
【免费下载链接】dsh-superagent-prototype
Towards a More Autonomous Agent System
相关推荐
dsh-superagent-github 技能详解:用 orchestrator_read 读取 GitHub Issue、PR、Review 与 CI
dsh superagent github 技能详解:用 orchestrator_read 读取 GitHub Issue、PR、Review 与 CI 本指
原神抽卡记录还能这样管?genshin-wish-export 本地祈愿数据管理完整指南
原神抽卡记录还能这样管?genshin wish export 本地祈愿数据管理完整指南 家里电脑、公司电脑来回切账号,保底进度全凭印象;想算算实际出货率,游戏
桌面应用Claude Code 结果优先沟通风格:解读 Outcome-First 系统提示词与用户通信规范
Claude Code 结果优先沟通风格:解读 Outcome First 系统提示词与用户通信规范 本篇技术指南围绕 Claude Code 系统提示词中的
文档提示工程
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考