对象:jiuwenswarm !9475(头 62939fe82)+ agent-core !3556(头 bfab1226)。现有代码以 develop 为准:jiuwenswarm 9843516a16,agent-core 5a35c39f。2026-11-04 整理。
用户输入 ────────────────► USER_INPUT ──────────────► 成员(忙则插入)
队友私信 / 广播 / 群聊 @ ─► 邮箱 ─► 每 30s 或来信触发 POLL_MAILBOX
│
▼
MessageHandler._process_unread_messages(use_steer=True)
(群聊走 GroupMessageHandler:只投 @ 到的人,没 @ 只记录)
│
▼
deliver_input(text, use_steer) ─► harness.send(immediate=use_steer)
│
┌────────────────────┼─────────────────────┐
成员空闲 成员忙 + steer 成员忙 + 非 steer
开新一轮 插入(下次模型调用前) 排队(本轮结束后)
看板巡视 / 催办 / 调度器交接 / checkpoint ── 不走这条判断,调用点写死用插入还是排队
停止按钮 / pause / abort ─────────────── 唯一能撤掉当前一轮的手段(abort 会回滚)
handlers/message.py:211 默认 use_steer=True;native_harness.py:867-926 规定空闲开新一轮,忙时 steer 插入,否则进 FIFO 排队,PAUSED 时热恢复后插入。handlers/AGENTS.md「维度 3」规定:改派、取消、返工用插入;催办、巡视用排队(stale_task.py、checkpoint.py、scheduling/scheduler.py)。steer_batch_size(F_78)在管,非 Leader 成员每次模型调用最多插入 2 条。| 层 | 是什么 | 位置 |
|---|---|---|
| 团队 | lifecycle: persistent(默认)。Leader 跨轮常驻,停止后保留状态,下次冷恢复或热恢复 | config.yaml:1701;agent-core schema/team.py:92、recovery_manager.py:40-116 |
| 成员 | 11 个状态(READY/BUSY/PAUSED/STOPPED/DORMANT…)。F_118 新增 lifetime:常驻 / shutdown / dormant。DORMANT 不随团队恢复,被点名才醒 | schema/status.py:13-56、tools/member_options.py |
| Group 群聊 | 花名册、回执、mode 存在 group.json。专家团加入时建子团队,强制 persistent | jiuwenswarm group_service.py、agents/swarm/group_chat.py:36-108 |
view_expert_groups 用它做 BM25 排序。组织层还有一套 required_capabilities 能力匹配,用于跨团队派任务。@member/@all,群聊里 mentions,没 @ 的只记录不唤醒。dispatch_mode:autonomous(成员看板认领,Leader 空闲时自我催办)和 scheduled(TeamScheduler 以 Leader 身份往邮箱发开工、送审、返工、催办的模板消息)。scheduled 下面有三个子开关:验收、成员互发消息(F_126,默认关)、子任务(F_128)。modes.team.jiuwen_team.*(config.yaml:1796 起)。设置页里团队相关开关都在 「实验」模块:团队组织、调度模式和它的三个子开关(experimental/definition.ts:81-106)。调度模式系列(F_119/122/126/128/129)、Leader 只在需要决策时唤醒(F_121)、成员 lifetime(F_118)、专家目录和按需拉起(F_125)、外部 CLI 和第三方成员(F_117/127)、模型组 model group、模板消息 meta(F_124)、群聊固定 runtime mode、passive human 只能在群聊里。(只按提交标题归类,没有逐条读 diff)
我们新增的能力只有三样:① 监工判断(有没有关系、要不要打断);② 安全打断重规划(停在安全点,保留上下文,作废旧计划,带新消息重来);③ 只记录(广播和自己无关时,不进上下文)。按现有结构,它们应该这样挂:
邮箱排空 ─► deliver_input(use_steer) ← 现有唯一投递点
▲
│ 只在这里插一个可选钩子:
│ 队友私信 / 群聊 @ / 团队广播 → 问监工 → 选 打断重规划 | 插入 | 排队 | 只记录
│ 其余全部(用户、Leader 广播、模板消息、看板、催办、cron、非文本) → 原路,不问
│ 监工失败 / 超时 / 关闭 → 原路(= 现在的忙时插入)
│
harness: 空闲开轮 │ 插入 │ 排队 │ 新:interrupt(介于插入和 abort 之间,不回滚) │ pause │ abort
| 和谁 | 应有的关系 | 理由 |
|---|---|---|
| 维度 3(插入/排队写死在调用点) | 扩展:只把邮箱里队友类消息从"写死插入"改成"按监工判断",别的调用点一个不动 | 避免和巡视、催办、调度器交接抢同一条决策 |
| 原有兜底 | 监工失败 = 原有行为(忙时插入),不是排队 | "关了或挂了就和没装一样",评审才放心 |
| 停止 / pause / abort | 复用。interrupt 是第三种打断,说明里要写清它和这三者的区别。全员停工用现有停止按钮和 pause,不再在提示词里另起一套 | 现有后端已经能停,提示词只能"请求" |
| 调度模式 | 并列:调度器模板消息原样投递。要写明 F_126 关闭时成员只能找 Leader,私信场景基本只落在 Leader 身上 | 评审会问"开了调度模式会不会乱" |
| 持久化 | 复用:team_rules 是宿主配置,恢复时以当前配置为准。DORMANT/PAUSED 由原闸门挡住。interrupt 清空的 task_plan 会写进存档,要写明。专家团子团队是否继承要明确定一个,并测过 | 持久团队跨 session,状态会被带走 |
| tag / @ | tag 无关;@ 复用(群聊没 @ 只记录是原有行为,不重新实现) | — |
| steer_batch_size | 复用:插入的条数仍受它限制 | — |
| 模型 | llm 档用团队主模型,jev 档用决策模型页的共享 Jev。不另起模型配置 | 已和模型组、决策模型对齐 |
| 配置和设置页 | 配置放 modes.team.jiuwen_team.team_rules,和 dispatch_mode 并列。设置项放在「实验 → 团队」里,紧挨调度模式 | 团队开关都集中在一处 |
| 仓库 | 改动 | 和现有的关系 |
|---|---|---|
| agent-core !3556 39 文件 +3135/-40 |
新目录 team_rules/:classifier(问监工)、policy(场景→动作表)、router(接管邮箱行)、scheduler(每成员一个判断队列)、config、handlers | 新增 |
handlers/message.py:把 deliver_input 抽成 _deliver_message 钩子 | 改动小,关闭时行为不变 | |
dispatcher.py:开启时在装配阶段把 Message/GroupMessageHandler 换成 TeamRules 版;PollController 加 enqueue;kernel 关闭时 aclose | 照 reliability handler 的现成模式做 | |
native_harness / control / protocol / state / team_harness:新增 interrupt()、work_summary() | 新原语,和 pause 共用 PAUSING 状态 | |
schema/blueprint.py 加 TeamAgentSpec.team_rules;team_agent.py 恢复时用当前配置覆盖 | 和 lifecycle、dispatch_mode 并列 | |
core/foundation/llm/system_one/providers.py、browser_move/decision/{config,jev_client}.py | 超出团队范围,说明里没写 | |
| jiuwenswarm !9475 12 文件 +595/-5 |
common/team_rules.py(新)+ config_loader.py:把 mode 解析成连接,塞进 spec(SDK 不支持就跳过) | 接线 |
config.yaml 顶层加 team_rules: {mode: off} | 位置和其他团队配置不一致 | |
| 设置页「智能体」模块加「Group 团队规则 → 监工模式」下拉;config_set_handlers/config_service 读写 | 和团队开关(在「实验」)分在两处 | |
config.yaml 给 agent_leader 加 system_prompt:全员停工规则 | 和现有停止/pause 重叠;设计模式下被覆盖,不生效 |
| # | 问题 | 证据 | 改法 |
|---|---|---|---|
| 1 | 悄悄改了默认行为:开启后,队友私信在忙时,监工判"不打断"或者判断失败,都从原来的插入降成排队。说明里却写成"照常投递" | agent-core team_rules/policy.py:20 "busy -> APPEND";develop message.py:211 默认 steer | 失败时一律回到原有行为(插入)。"不打断"要么也保持插入,要么在说明里明写"这是有意降级"并给理由 |
| 2 | "只能变轻"的原则和实现对不上:以现状为基线,打断重规划比插入更重 | issue「两条原则」第 1 条 vs 场景表 | 原则改成:基线 = 现有行为;监工可以升一级(打断)或降一级(排队、只记录),只降不升的约束只用在广播 |
| 3 | Leader 全员停工重复造轮子,而且设计模式下不生效 | jiuwenswarm agents/swarm/assembly.py:245,350 整段覆盖 Leader 的 system_prompt | 从这个 PR 拿掉;需要的话另提,并复用后端停止和 pause |
| 4 | 设置入口和配置位置不统一 | 团队开关在 experimental/definition.ts:81-106、modes.team.jiuwen_team.*;PR 放在 Agent 模块和顶层 | 挪到「实验 → 团队」、modes.team.jiuwen_team.team_rules |
| 5 | 名字容易混:"Group 团队规则"像只管群聊,其实团队私信也管;team_rules/scheduler.py 和 TeamScheduler 重名;分支和老提交还叫 duplex,和实验里的"任务对话全双工"撞名 | — | scheduler.py 改名 batcher;对外名称见第四节待定 |
| 6 | 超出范围的改动:浏览器 JEV 配置重构、system_one providers | agent-core diff | 拆成单独 PR,或在说明里写清为什么必须一起改 |
| 7 | 持久化相关没说明、没验证:interrupt 清空的 task_plan 会写进存档;专家团子团队会不会继承监工 | native_harness._commit_interrupt;group_chat.py:100-103 由 model_dump 复制 spec | 写明行为,再补一条专家团实测 |
| 8 | 说明里没有"和现有机制的关系" | issue #5251、两个 PR 描述 | 把本页第一、二节压成一张关系表放进 issue |
| 9 | F_130 文档范围不准:写了 group_chat/message_handler.py(没改),漏了 kernel、team_agent、i18n | agent-core F_130 | 照第三节第 1 小节的改动表改 |
来源:两路只读调研,对照 develop 和 PR diff。关键几条我亲自复核过:message.py:211、policy.py:20、assembly.py:245/350、experimental/definition.ts、config.yaml:1699-1804。没核过的:第一节第 5 小节逐条 diff;专家团子团队是否真的继承监工;外部成员的运行状态判断。