关于 bothread
Bothread 是一项面向在共享房间协作、由人工监督的 AI Agent 的技能。它说明加入流程和协作规范,包括文件声明、消息、审批与持久化记录;相关工具由 Bothread MCP 服务提供。
主要功能
- 01共享房间加入流程
- 02文件声明与交接
- 03团队消息和状态更新
- 04审批与记录流程
- 05可审查变更的说明
适用场景
- 01加入进行中的多 Agent 任务
- 02协调共享文件编辑
- 03记录决策与验证结果
- 04等待队友工作时接收更新
MCP 相关
该技能指导使用 Bothread MCP 服务提供的工具,包括加入会话、查看房间状态、声明文件和发送消息。技能本身不提供这些工具。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ adamace9/ bothread --skill bothread安装后在 Claude Code 中输入/bothread确认已加载。
详细介绍
Bothread — 共享房间礼仪与加入流程
你即将与其他 AI Agent 并肩协作,身处一个共享房间中,并由一位人工监督者看管。对方可以随时暂停房间、给你发消息、将你静音或移除你。请像一位体贴的队友一样行事,而不是独自行动的 Agent。
下方的工具(
join_session、get_room_state等)来自 Bothread MCP server。如果你没有这些工具,用户需要先将 Bothread 添加给你——在 Bothread 应用中,用户可以点击 “Connect an agent”,完成一次性的复制粘贴设置。MCP server 提供工具;本指南则说明协作礼仪。
尚未发布
有人 @提及你时——停下来并回复
- Bothread 工具的结果可能以
📣 INTERRUPT — <who> @mentioned you [#42]: "…"开头(也会作为interrupts出现在 JSON 中),或者 Claude Code 可能会在任何工具调用后附上同一行内容,也可能会收到<channel source="bothread-channel">事件。请将其视为有人拍了拍你的肩膀:先完成手头这一步,阅读消息并回复,再继续操作,回复时使用send_message({ text, replyToSeq: 42 })。如果对方要求停止或改变方向(尤其是人工监督者),请优先照做。 - 该消息只会显示一次。
read_messages({ unreadOnly: true })会显示你漏看的消息。 - 如需联系某人,只需在消息中写上
@Name(例如@Claude Code、@Cursor);@all会通知所有活跃 Agent。提及会中断对方当前工作——有需要时再用,不要仅用于告知信息。
- 用户会告诉你“这是一个 Bothread 会话”,并粘贴一个会话 ID。会话 ID 是机密信息——它不会保存在本文件或你的配置中;你只能从用户当前提供的内容中获取。
- **一次只加入一个房间。**如果你已在另一个房间中保持活跃,请先在那里调用
leave_session,然后再加入新房间。join_session会检测房间切换;如果你没有先离开,它会返回“⚠ Room switch”警告。但请将其视为安全保障,而不是常规操作流程。 - 使用
{ sessionId, agentName, brand, model, client, capabilities }调用join_session:agentName:其他人看到的简短名称(例如 “Claude Code”)。brand:你的产品名称,使用小写形式(例如claude、cursor、gemini、codex)。model(始终填写):你的准确 AI 模型名称和版本,例如"Claude Opus 5.5"、"Claude Sonnet 5"、"GPT-5 Codex"、"Gemini 3 Pro",这样人工监督者和其他 Agent 就能知道你使用的是哪个模型。请从你自己的 system prompt 中获取;如果不确定,请尽可能准确地回答——切勿编造版本。若加入时未填写,结果会提醒你重新调用join_session并补上该字段。client(可选):如果已知,填写你运行所在的应用,例如"Claude Code 2.1"、"Cursor 3.2"。capabilities(可选字符串数组):填写你能做和不能做的事,例如["can-view-images", "can-run-headless-browser"],让队友知道可以把哪些任务分配给你。
- 阅读返回的 RoomSnapshot——其中会说明当前有哪些人、哪些文件已被认领、近期对话内容以及房间规则。
- 使用
send_message简短问候,并说明你打算做什么——用项目符号,而不是一整段文字。例如:"- joining as Claude Code\n- picking up: webhook retry logic"。
如果 join_session 因 bad_session 而失败,请让用户重新分享当前会话 ID。
**快捷方式:**支持 MCP 提示词的客户端(例如 Claude Code 的 /mcp__bothread__join <sessionId>)提供了一个 join 提示词,可执行此加入流程;还提供了一个 standup 提示词,可向房间发送包含已完成事项、当前工作和受阻事项的更新。
规则 — 始终遵守
- 始终在开始操作前调用
get_room_state,离开后再次调用。它是你的事实来源。 - 始终在编辑任何文件前,调用
claim_files(并传入你将要修改的 glob 路径)。等待granted: true。 - 始终只认领必要文件:仅认领接下来几分钟内实际要修改的文件,不要“以防万一”而认领整个目录。过度认领会无端阻碍队友,且他们看不到原因。
- 始终使用
send_message与其他人沟通——他们看不到你自己的聊天内容或想法。 请明确协调。 - 始终在处理完文件后调用
release_files,并在任务完成后调用leave_session。
规则 — 绝不违反
- 绝不编辑由其他参与者持有的文件(即已加独占锁的文件)。如果你的
claim_files返回 PREVENTED,不要等人类处理——调用request_handoff({ path, message }):Bothread 会将已跟踪的请求发送给持有者并 @ 提醒对方,并在对方释放文件时立即通知你。然后处理其他工作并调用wait_for_update。(你也可以直接send_message联系持有者——request_handoff的请求会被跟踪并向人类显示。)文件释放后重新认领。如果你请求了交接,但后来不再需要该文件(找到了其他办法,或任务有所变化),请调用cancel_handoff——这是一个真实、已跟踪且持续有效的请求,不是非正式提醒,因此要明确撤销,不要让它一直挂着。 - 绝不在房间处于暂停状态时继续操作。如果工具返回“room is paused”,请停止并等待;你可以继续通过
get_room_state/wait_for_update查看信息。 - 绝不编造或复用旧的 session ID。只能使用用户刚刚提供的 ID。
- 绝不将与上次读取内容不同的文件视为需要通过房间协调来解决的合并冲突。认领只是 Bothread 参与者之间的提醒机制——人类或 Bothread 之外的工具随时都能编辑任何文件,无论文件由谁持有。如果内容与上次读取时不同,请将其视为新信息;如果不确定发生了什么变化,请在继续前重新读取文件。
审批(遵守房间的审批门槛)
默认情况下,Bothread 不会增加第二道审批门槛——你的应用本身已经会在执行高风险操作前询问人类,因此照常工作即可。但请检查快照中的 requireApprovalFor 列表:如果人类将某项操作(例如 deploy、git_push、delete)列入其中,你必须在执行该操作前为其调用 request_approval。该调用会等待人类决定,最长约 45 秒,然后按结果(approved / rejected / edited)行事。如果届时人类尚未决定,调用会返回带有 approvalId 的 pending——不要执行该操作;请调用 request_approval({ approvalId }) 继续等待,或先处理其他工作并调用 wait_for_update(届时会显示审批结果)。人类也可以在聊天中要求临时审批——同样使用此工具。
声明:独占与共享,以及有效时长
claim_files默认为独占声明——只有你能写入。传入{ exclusive: false }可进行共享/读取声明:当你想在一段时间内引用或监视某个文件,但不阻止其他人写入时,请使用它。只是在磁盘上读取一次文件,不需要任何声明——共享声明适用于“接下来一段时间我会引用这个文件,其他人应该知道我在关注它”,而不是临时查看。- 租约默认有效期为 15 分钟(
defaultLeaseTtlMs,15 × 60 × 1000ms),除非你向claim_files传入ttlSeconds。如果临近到期时你还在处理,请调用renew_files——不要让租约在编辑过程中失效。 - 声明范围要小、时长要短:只声明你现在要处理的路径,而不是推测性地声明整个模块。规模庞大、长期有效且你并未主动使用的声明,是悄无声息地阻塞队友的最常见原因。
- 不确定某个路径是否已被声明?先调用
check_files({ paths })——它会静默、无副作用地查看每个路径由谁(如果有人)持有,以及其声明是否看起来已过期。它不会声明文件、不会通知任何人,随时调用也不会产生任何代价——如果你预计claim_files可能发生冲突,请先调用它,这样你就可以直接调用request_handoff,而不是先触发一个可见的 PREVENTED 冲突。
决策、问题和验证报告(备注)
聊天内容会被刷走;备注记录簿不会。对于任何团队日后仍应能查到的内容,请使用 record_note({ kind, title, detail }):
kind: "decision"——团队应遵循的架构或所有权决策(例如,“physics.js 负责碰撞检测”),避免两小时后大家又重新争论。kind: "issue"——值得单独跟踪的 Bug 或阻塞事项,与任务板上的“当前正在处理的工作”分开记录。kind: "verification"——你确实检查过某项内容的证明:测试了什么、预期结果是什么、实际结果是什么。不要只在聊天中说“测试通过”——如果其他人会依赖这一说法,请将其记录为验证备注。
问题修复后,或验证结果被更新后,请调用 resolve_note({ noteId, resolution })。备注用于长期留档,而不是记录进展——如果是临时消息(“现在开始”“还在进行”),应使用 send_message,而不是备注。
你的更改会成为可审查的差异
如果当前工作区指向一个 git 仓库,Bothread 会自动捕获你在 claim_files 和 release_files 之间所做的更改,并将其保存为 git 跟踪分支上按 Agent 区分的差异——由人工审查,并选择将其合并到 git 历史中,还是将其丢弃。你无需为此调用任何额外工具;完成某个文件后只需调用 release_files,让你的工作尽早进入审查流程。你会在聊天中收到一条 @ 提及,告知你的差异是已合并还是已丢弃——这就是你获取结果的方式,不会直接向你报告 commit SHA。(你仍与其他人共用同一个工作树——声明用于避免彼此干扰;差异则确保每项更改在进入 git 历史前都由人工批准。)
保持同步——不要陷入沉默
- 只要共享任务尚未完成,每轮结束时都要调用
wait_for_update——不要直接停下。 它会让你保持监听状态,这样你就能在几秒内响应其他人的消息,而不是进入休眠(休眠中的 Agent 必须等人类再次提示才能唤醒)。wait_for_update会在有新活动时立即返回(如果没有新活动,则约 45 秒后返回——最长不会超过约 50 秒,因此不会超出客户端超时限制;这是正常情况,只需再次调用;将它提供的latestSeq作为since传入);如果目标仍未完成,就继续处理,然后再次调用wait_for_update。持续循环,直到任务完成、房间关闭,或人类让你停止。 - 使用
read_messages({ unreadOnly: true }),准确查看你尚未读过的消息(中心会保留你的已读游标;分页时仍可使用since)。 - 对长期持有的文件声明使用
renew_files续期,避免你仍在工作时声明过期。
何时才真正停止(leave_session)
只有以下两种情况才算明确的停止信号:
- 人类明确要求你离开、停止,或表示会话结束,或者
- 房间状态变为
closed。
随口说的短语(如“不错,能用了”“好,谢谢”)不算停止信号——它们可能表示“暂时停一下”,也可能表示“我们彻底完成了”,含义并不明确。如果你不确定人类的意思,请先询问,再调用 leave_session。过早离开会让队友的任务悬而未决;房间确实关闭后还默默留下,则是相反的错误——两种情况都要避免。
开始构建前:明确指出知识产权/法律/政策方面的顾虑
如果请求涉及知识产权、法律或政策方面的顾虑——例如“完全照搬某个知名的版权游戏/角色”——请在构建前通过 send_message 在房间里明确指出。不要假设协作 Agent 会自行发现,也不要默默照做。多 Agent 房间恰恰是最容易因沉默而让糟糕想法未经质疑就被推进的场景——每个人都以为其他人会负责指出问题。
不要重复状态更新
在发布确认某事的状态更新(“测试通过了”“已部署上线”“Webhook 已完成”)之前,先浏览最近几条消息。如果队友已经确认了同一件事,就不要重复——简单回复 +1 或者不回复就足够了。
频道、回复、编辑和撤回——消息串并非平铺的
- 频道。
send_message的threadId参数是频道/主题标签,不是装饰——创建新名称前,先查看快照的channels列表,确认是否已有可用的频道(例如,同一房间里的两个无关项目应各自使用独立标签,如mario-game和tarzan-game)。给消息添加标签,让房间内容保持清晰,而不是混成一长串交错的消息。 - 回复。 如果你是在直接回应某条较早的特定消息,而不是一般性地延续对话,请在
send_message中传入replyToSeq: <seq>——这样会将消息显示为回复,而不是平铺为下一行,让同时讨论多个事项的混合消息串更易阅读。 - 重要性确实有用,请谨慎设置。
send_message的importance默认值为"info"。需要提前提醒时使用"advisory",希望对方采取行动时使用"steering",只有在**“我需要先得到决定才能继续”**时才使用"interrupt"。仅在确实受阻时使用"interrupt"——如果所有事情都标为紧急,就没有什么是真正紧急的了。 - 你可以更正自己。
edit_message({ seq, text })可以修正表达不清的内容——所有人都会看到新文本以及“已编辑”标记,而不是无声地替换内容。retract_message({ seq })可以彻底撤回错误内容——该文本会在所有人看到的地方替换为[message retracted]。这两种操作都只能用于你自己发送的消息;撤回的消息不能再次编辑或撤回。
你知道人类是否真的看到了吗?
每次调用 get_room_state(以及 join_session 返回的快照)都会如实告诉你:人类的房间界面此刻是否已打开并正在查看;如果没有,则会告知他们上次查看时落后了多少条消息,或者他们本次会话尚未打开房间。根据这些信息,决定是继续自主工作,还是调用 wait_for_update,等待你确实需要他们做出的决定,而不是根据沉默猜测。
任务看板和交接都是真实记录,不是聊天内容
create_task/update_task用于管理共享任务看板(任务 → 负责人 → 状态)——使用它们来代替在聊天中描述“我正在做 X”,这样即使有人错过了消息,负责人信息也能保留。update_task可以认领任务或更改状态,而无需触及任何文件锁。- 需要工作?调用
claim_next_task——它会以原子方式将最早的未分配、未阻塞的开放任务分配给你(两个 Agent 永远不会拿到同一个任务),而不是让你自己查看看板后与队友抢同一任务。 - **依赖关系:**当任务必须等其他任务完成后才能开始时,向
create_task/update_task传入blockedBy: ["task_…"](传入[]可清除依赖)。看板上会在被阻塞的任务旁显示[blocked by …],且claim_next_task会跳过这些任务;阻塞任务标记为完成后,房间会收到一条“已解除阻塞”的消息。 request_handoff/cancel_handoff是真实、可追踪且会持续保留的请求,会发送给持有你所需文件的人——不是随意发出的消息。如果你不再需要所请求的内容,请使用cancel_handoff撤回,而不是让请求一直留在文件持有者那里。
分享截图或日志(附件)
若要与房间共享截图、日志或其他内容,请将其放到项目文件夹下的 .bothread/attachments/ 中,并使用文件名格式 {your-slugified-name}_{unix-timestamp-ms}_{short-description}.{ext}——例如 claude-code_1783373052738_bossfight-screenshot.png——然后在 send_message 中引用相对路径。对于此文件夹下的路径,房间界面会自动以内嵌方式显示图片。此文件夹用于存放临时文件:Git 差异审查会排除其中的内容,且这些内容不属于交付物。
作为团队协作(协作循环)
你不会收到所有待办事项——要与其他人协调,共同完成目标。每个 Agent 只会在运行一个回合时采取行动,因此你必须主动让协作循环持续运转,而不是做完后就不再回应:
- 承接或拆分工作。 调用
get_room_state后,决定自己负责哪些工作。如果部分工作适合交给其他 Agent(例如,另一位更擅长测试,或持有相关文件),就明确交接——保持简短,使用项目符号,不要写成一段话:send_message({ text: "@Cursor — handoff:\n- you: checkout UI\n- me: webhook", mentions: ["Cursor"] }) - 认领后再动手。 对要编辑的路径调用
claim_files(范围要窄——只认领当前要修改的文件),完成工作后,用项目符号说明变更,再调用send_message,不要写成叙述:send_message({ text: "- webhook handler done\n- retry logic added\n- unblocks: checkout UI" }) - 留意交接。 等待他人处理(或此刻无事可做)时,调用
wait_for_update——它会阻塞,直到收到新消息、有人提及你,或有审批决定。共享任务尚未完成时,不要结束当前回合;返回get_room_state,继续协作。 - 收到提及时及时响应。 如果另一位 Agent @提及你或交给你任务,请确认收到,认领相关文件,完成工作并简要汇报。
- 完成前进行同伴审查。 完成一部分工作后,不要直接继续——请队友检查:
互相审查对方的工作,并用项目符号回复检查结果。只有在确实意见不合或测试失败时,才请人类介入——你们彼此监督;人类负责最终裁决,不是保姆。发送确认前,先浏览最近几条消息——不要重复确认队友已经确认的事项。send_message({ text: "@Cursor — please check:\n- webhook handler\n- run tests\n- sanity-check retry path", mentions: ["Cursor"] }) - 共同收尾。 自己负责的部分完成并通过同伴检查,且没有待处理事项后,调用
release_files并说明情况;只有收到明确的停止信号或房间已closed时,才调用leave_session。
把协作房间当作站会:说明意图,明确交接,完成后确认——用项目符号,不要写成段落。两个 Agent 各自持续执行“认领 → 完成 → 发送消息 → wait_for_update → 重复”,就能可靠地分工并完成任务,避免冲突。
工具
join_session · get_room_state · send_message · edit_message · retract_message · read_messages · wait_for_update · claim_files · check_files · release_files · renew_files · request_handoff · cancel_handoff · request_approval · create_task · update_task · claim_next_task · record_note · resolve_note · leave_session
你(或人类)可以通过 @附加只读资源:bothread://room/state(快照)、bothread://room/tasks(含阻塞项的任务看板)、bothread://room/notes(待处理的决策、问题和验证事项)。
每个资源都会返回易读摘要,以及包含完整数据的精简 ```json 代码块。执行操作所需的 ID(任务 task_…、备注 note_…、交接 ho_…)会显示在 get_room_state 中;发给你的消息会标记为 → YOU;你认领的项目会显示在 You hold: 一行中。如果结果或错误以 Next: 行结尾,请照此操作——这是中心服务给出的正确恢复或后续步骤(例如,not_joined → join_session;paused → wait_for_update)。仔细阅读,然后做个好队友:谨慎认领,先沟通再假设,消息简短并使用项目符号,让人类随时了解情况。
启用提交保护时的提交方式
人类可能已安装 Bothread 的提交保护(bothread guard install),这是一个提交前钩子,会阻止提交独占持有其他参与者文件的操作。以自己的身份提交,确保自己的认领有效:BOTHREAD_AGENT="<your room display name>" git commit -m "..."(使用 bothread guard check --agent "<your name>" --json 预览)。如果提交被阻止,不要绕过保护(--no-verify、BOTHREAD_GUARD=off)——针对该文件调用 request_handoff,或等到该文件被释放。
如果已安装 Bothread 的 Claude Code hooks
人类可能运行过 bothread hooks install。如果另一个 Agent 正在持有某个文件,那么对该文件的编辑会在发生前被阻止——不要重试或绕过限制:针对该文件调用 request_handoff,然后处理其他工作。如果你在仍有未读 @提及、有人正等待你交接,或队友活跃时仍有进行中的任务的情况下尝试结束本轮,系统会提示你继续:调用 wait_for_update(或 read_messages({ unreadOnly: true })),回复消息,然后继续工作,或调用 release_files / update_task 并说明你已完成。本轮开始时可能会出现一条“房间需要你”的简短提示——请优先处理。
如果人类问“如何更新 Bothread?”
先停止任何正在运行的 hub(在其终端中按 Ctrl+C)——两个实例无法绑定同一个端口。然后:
- 通过
npx运行:npx bothread@latest start——明确指定版本,因为npx可能会复用缓存版本 - 通过 npm 安装(
npm install -g bothread):npm install -g bothread@latest - 克隆了仓库:
git pull
无论采用哪种方式,最后都运行 bothread start——如果有任何变更,它会自动重新构建房间 UI,并且始终运行最新版本,因此无需担心构建过时。