团队模式
Spark Work 团队模式(Team Mode):Host Agent 把子任务分派给多个 Member Agent,每个 Member 有独立模型/工具/Skills,事件流式展示分派、回复与完成。
团队模式(Team Mode)让一个HostAgent 把子任务分派给多个MemberAgent,协作过程以群聊式事件流呈现。Host 和 Member 不是主从关系: 每个成员是一个独立 Agent,有自己的 Provider、模型、Skills 和提示词,跑自己的 turn。
1. 启用团队模式
入口在会话本身,不在设置里:
- 在会话输入栏的 Agent 选择器里选**「团队模式」**。
- 输入栏上方会出现团队横幅:
团队模式 · Host:<主持人名> · 成员 N, 右侧「管理成员」按钮直接打开右侧 Inspector。 - Inspector 顶部是**「团队成员」**区块:主持人单独一行(点击可换主持人), 成员逐行开关,底部「邀请成员」加入候补 Agent。
团队模式下输入栏会隐藏模型切换:Host 和各成员一律用自己在 Agent 里配置的模型。@提及只在团队模式生效:被 @ 的成员会直接执行这一轮, 此时不会给它挂 spark_team派发工具(避免「被点名的人再转派」)。
团队配置的持久化是两层的:sessions.metadata.team是会话级权威来源 (写库走 team:update);localStorage 里的spark-agent:composer-prefs只记住「上次用过的 Host 和成员」,作为下次显式开启团队时的预填,不会把enabled带过去——这也是新会话默认单 Agent 起步的原因。
2. 团队配置字段与默认值
| 字段 | 含义 | 默认值 / 限制 |
|---|---|---|
enabled | 该会话是否处于团队模式 | 默认false |
hostAgentId | 用户直接对话的主持 Agent | 缺失时回落platform-manager-agent(Spark助手) |
memberAgentIds | 本会话授权可被派发的成员(不含 Host) | IPC 校验最多 20 个 |
maxDepth | 最大链式派发深度 | 默认 1;界面与 IPC 只允许 1 / 2 / 3 |
allowNesting | 成员能否再派发下一层 | 默认false |
dispatchTimeoutMs | 单次派发超时 | 缺省 600000(10 分钟),上限 1800000(30 分钟);会话级字段,界面不暴露 |
maxDiscussionRounds | 一场讨论最多推进多少轮 | 默认 6,硬上限 20;界面可选 1/3/4/6/8/12/20 |
enablePeerMessaging | 是否允许成员之间互发消息 | 默认false(实验性,界面文案「允许成员互相留言(实验性)」) |
threadContextTokenBudget | 注入成员的讨论快照 token 预算 | 默认 6000,可配 500 ~ 40000;会话级字段,界面不暴露 |
teamId | 来源的长期团队 id | 临时团队为undefined |
注意maxDepth有个细微差别:界面和 IPC schema 卡在 3,但读取会话配置时会把数值钳到 1~10。也就是说存量数据里若出现过更大的值,运行时仍会按读到的值执行,只有新写入受 3 限制。
3. 长期团队(可复用预设)
入口:左侧**「助手」→ Teams 标签**(与 Agents 标签并列)。字段包括团队名、描述、 头像、主持人、成员、团队专属 Prompt、是否启用。
- 团队专属 Prompt:会作为
[Team Instructions]段注入主持人, 位置紧跟[Team Roster]之后。长期团队被删除时该段自动消失,不报错。 - 嵌套调用:勾选「允许成员发起下一层 dispatch」后才可选最大深度(1/2/3)。
- 讨论协作:讨论轮次上限与「允许成员互相留言(实验性)」。
- 会话侧也能反向操作:Inspector 的「团队成员」区块支持把当前成员/嵌套配置保存为长期团队(创建新团队)或写回来源团队,以及解除关联变成临时团队。
长期团队存在agent_teams表(平台 MCP 的teams_* 工具管理同一份数据)。 应用一个已保存团队后,会话的teamId 指向它,但运行期仍以会话自己的sessions.metadata.team为准。
4. 分派链路
4.1 Host 的一次派发发生了什么
- 运行时给 Host 注入进程内 MCP server
spark_team,工具名形如mcp__spark_team__agent_dispatch。同时注入[Orchestration Mode]提示词和orchestration_status事件, 告诉它「本轮你是编排宿主」。 - Host 工具集不会被剥夺:提示词明确说 Host 保留完整工具(Edit/Write/Bash 等), 但职责是协调——实质工作优先派给成员,自己只做汇总、跑快速验证和小修。
agent_dispatch(串行)与agent_dispatch_batch(一次最多 10 个并行任务) 把任务交给TeamDispatchService。校验项:成员是否在本会话授权名单里、 嵌套深度是否超限、本 turn 预算是否用完。- 校验通过后写入
team_dispatches表,发出team_dispatch_requested与team_member_status。 串行派发先入 turn 队列(状态pending,出队才转working), 批次派发走parallel路径真正并发。 - 成员跑自己的 turn,流式输出被打上
team_member_message(带dispatchId), UI 渲染成独立的群成员消息气泡。 - 完成后发出
team_dispatch_completed,Host 拿到结构化TeamA2AReply(state/content/error/usage), 决定继续派发还是合成最终答复。
agent_dispatch的参数:targetAgentId(支持用成员名模糊解析)、instruction(最长 8000 字)、inputs、attachments(最多 10 条)、expectedOutput(text / json / code / mixed)、timeoutMs(5000 ~ 600000)。
4.2 成员这一轮看到什么
- Host 给的
instruction;inputs以[Inputs]段落成 JSON 正文。 [Attachments]:文本直接内联,file_ref / image_ref 提示用 Read 工具读取。[Expected output]:期望产出形态。[Discussion So Far]:当前讨论线程的截断快照,按threadContextTokenBudget裁剪(默认 6000 token)。- Living Ledger 摘要:当前 discussion 里未过期的 active 事实,带状态、权威等级、 版本号和来源。
- 成员的
Task与SendMessage工具始终禁用: A2A 只走spark_team,避免模型用 SDK 原生子代理体系抢走协作流量。
4.3 成员的模型与执行器怎么定
成员这一轮生效的 Provider / 模型按固定优先级解析:
- Provider:
member.providerProfileId优先;没配就沿用会话当前的 Provider。 - 模型:成员的
modelId优先;没配时看会话当前模型——只有它在该 Provider 的modelIds白名单里(或白名单为空)才继承,否则回退到 Provider 的defaultModel。 - 本地 CLI Provider 例外:直接沿用宿主机 CLI 自己的模型配置。
- 执行器和权限模式同理:成员自己配了就用成员的,否则跟着会话(团队模式即主持人)走。
讨论内同一成员的 SDK 会话可以续接(continueSession):无讨论、Codex 成员或 resume gate 判定不安全时,每次派发用全新的sdkSessionId。
5. 预算、超时与嵌套限制
| 限制 | 真实数值 | 超出后的行为 |
|---|---|---|
| Host 每 turn 派发次数 | 10 次(batch里每个任务各计一次) | 返回错误文案Dispatch budget exceeded (10 per turn), 并发通知宿主准备一个续跑 turn |
| 成员同步咨询次数(peer call) | 20 次 / turn,独立预算,不挤占派发预算 | 返回Peer call budget exceeded (20 per turn) |
| 单次派发超时 | 任务级timeoutMs> 会话dispatchTimeoutMs> 默认 600 秒;上限 1800 秒 | 该次派发以timeout失败 |
| 嵌套深度 | currentDepth > 0时需要allowNesting,且depth < maxDepth | 返回depth_exceeded,文案带最大深度 |
| 单讨论消息总量 | 40 条(广播 + 定向 @ 累计) | 返回message_budget_exceeded |
正文@自动转发跳数 | 6 跳(约 3 个完整往返) | 停止自动转发,需要模型显式调用agent_message |
| 同轮同一对成员往返 | 双向合计 8 条 | 拒绝继续互 ping,提示推进轮次或收尾 |
| 同步咨询链深 | 3 层 | 不再向下传递咨询 |
取消会话或点「停止」会中止该会话所有在飞的派发:取消句柄按sessionId归属, 不会误伤其他会话正在跑的成员。
6. 事件流与界面呈现
团队模式相关的 AgentEvent(与 SDK 原生的subagent_*无关):
| 事件 | 作用 | 界面表现 |
|---|---|---|
team_dispatch_requested | Host 发起一次派发,带task | 「Host → Member」调用卡片 |
team_member_status | pending / working / idle / completed / failed | 成员状态行 / 运行中标记 |
team_member_message | 成员流式与完整输出,带dispatchId、mode、segmentId | 成员消息气泡,按dispatchId合并 delta |
team_dispatch_completed | 收尾,带结构化reply | 状态 chip 收口 |
team_peer_message | 成员之间的对等消息(广播或定向 @) | 成员互发气泡;自动转发产生的副本降级为轻量提示 |
team_round_advanced | 讨论轮次推进,带round与maxRounds | 轮次分割线 |
team_discussion_concluded | 收尾原因concluded / canceled / max_rounds | 讨论结束态 |
orchestration_status | 本轮是否处于编排宿主态(source: team | workflow) | 编排态标识 |
历史派发可以按会话或按 turn 查:IPC 通道是team:list-dispatches(sessionId+ 可选turnId+limit,默认 50、上限 200), 返回每次派发的入参、状态、回复与起止时间。
Inspector 里还有一个「显示团队思考、命令和工具日志」开关:关掉后主持人消息里的纯过程段会被隐藏, 只保留结论,群聊视图更干净。
7. 讨论线程、轮次与成员互聊
每个「Host + 成员 + 主题」组合对应一条讨论记录:team_discussions表, 状态 active → concluded | canceled,主题取当轮用户消息前 240 字。 讨论线程存在 team_thread_messages表,消息分四类:host_dispatch、member_reply、peer_message、round_summary。
- 推进轮次:Host 调
team_round_advance,round_index加一并写入一条 本轮小结。超过maxDiscussionRounds(默认 6,硬上限 20)会被拒绝。 - 收尾:Host 调
team_conclude;会话取消时也会收尾。收尾后的 discussion 不再接受推进或对等消息。 - 互聊:
enablePeerMessaging=true时成员才会拿到agent_message。它的投递语义有两种:call同步触发对方执行一次 turn,note只写线程不定向唤醒。 - 翻历史:
team_thread_read支持按轮次、按发送者、分页读全文, 用于补上快照里被裁掉的部分。这个工具只要存在真实讨论就会注入,不受互聊开关限制。 - 成员能否拿到派发工具,是三个条件各自独立的:嵌套(
allowNesting&&depth < maxDepth)决定agent_dispatch*;互聊开关决定agent_message;有讨论就决定team_thread_read。
8. Outcome Room 与 Living Ledger
团队共识不散落在聊天流里,而是写进结构化「活账本」。面板位置:右侧 Inspector 中 「团队成员」区块正下方的 Outcome Room 面板,随会话里第一个真实讨论出现。
- Room 与作用域:每个会话一个 room,id 为
team-room:{sessionId};记录再按 discussion 隔离。 - 记录字段:
logicalKey / value / status / authority / confidence / sourceRefs、版本号、操作者与时间、过期时间与纠错关联。事件日志追加写入, 当前投影可在事务内重放重建,历史不物理删除。 - 状态:
proposed / active / rejected / superseded / invalid / expired / deleted / conflict。默认上下文只返回未过期的 active 与 proposed 记录; 每个 (room, discussion) 的当前 key 上限 100 条。 - 权威等级:
user-confirmed > system-observed > agent-inferred。 低等级 actor 不能改更高等级记录的当前版本;成员 turn 一律以agent-inferred身份落账。 - 面板动作:proposed 可
confirm / reject / correct / invalidate; active 可correct / invalidate;终态(rejected / invalid / expired / deleted)可restore。每次提交都带expectedVersion,版本不匹配直接冲突, 不静默覆盖。 - Agent 侧工具:
spark_team暴露 8 个账本工具——team_ledger_read / team_ledger_propose / team_ledger_confirm / team_ledger_reject / team_ledger_correct / team_ledger_invalidate / team_ledger_tombstone / team_ledger_restore。成员只拿到 read 与 propose,其余治理工具只有可信的 host / system / user 上下文可见。 - 写入限额:账本值必须是纯 JSON,嵌套深度 ≤ 10、节点数 ≤ 200、序列化 体积 ≤ 8000 字节。
9. 类型化交接与 Steering Gate
- Typed Handoff:字段为
purpose / inputs / expectedOutput / acceptanceCriteria / deadline / sensitivity(sensitivity 取值public / internal / confidential / restricted), 并可带artifactRefs / evidenceRefs与附件引用。 状态机:draft → submitted → accepted,接受方可request_clarification或reject,完成后complete, 过程中可cancel。 - Steering Gate:针对
ledger / record / artifact / handoff / task五类目标创建闸门,带触发条件、影响等级(low / medium / high / critical)、 预算快照与推荐动作。状态机:waiting → approved | revise | stopped | expired。 - 工具面:
team_p1_read、team_handoff_create、team_steering_gate_create,以及交接迁移工具team_handoff_submit / accept / request_clarification / reject / complete / cancel、 闸门决策工具team_steering_gate_approve / revise / stop / expire。 - 权限边界:
capability = 'agent'时只返回 read + create 三个工具; 执行治理迁移必须由 system 或 user capability 完成。每次迁移带expectedVersion,并以唯一opId幂等。 - 数据落在
team_handoffs/team_handoff_events与team_steering_gates/team_steering_gate_events, 均由session_id + room_id + discussion_id限定作用域。
10. 其它讨论级工具族
只要存在真实讨论,spark_team还会挂上这几组工具(数量按讨论粒度):
| 工具族 | 工具 |
|---|---|
| 任务图 | team_task_graph_read / create_node / add_edge / retry / reassign(reassign需要 user 或 system 权限) |
| 审议 | team_deliberation_read / propose / add_evidence / add_alternative / add_risk / vote / decide / resolve(decide、resolve需要治理权限) |
| 证据与成本 | team_evidence_cost_read / team_evidence_add / team_evidence_verify / team_evidence_invalidate / team_cost_record_usage / team_cost_set_budget |
| 回放与剧本 | team_replay_read / diff / fork、team_playbook_list / propose / publish / apply / archive |
11. 最佳实践与排查
- 成员控制在 3~5 个:每次派发都是一次真实 turn,数量和成本线性增长。
- 把每个成员的定位写进它的 Agent 提示词,避免 Host 与成员互相抢活。
- 在团队专属 Prompt 里写清派工规则(先派谁、什么时候汇总),比在聊天里反复纠正便宜。
- 成员没被派发时依次检查:会话
memberAgentIds里有没有它、Agent 是否启用、 嵌套场景下allowNesting与maxDepth是否放行。 - 出现
Dispatch budget exceeded说明单 turn 10 次已经用满: 拆小任务粒度,或等宿主发起续跑 turn,而不是继续加派发。 - 想让长期策略可复用,把配置「保存为长期团队」,而不是每次在 Inspector 里重勾成员。
速查表
| 项目 | 内容 |
|---|---|
| 分派工具 | mcp__spark_team__agent_dispatch / agent_dispatch_batch |
| 单轮派发预算 | 10 次 / turn(batch 里每个任务各计一次) |
| 成员互聊预算 | 20 次 peer call / turn;单讨论消息上限 40 条 |
| 派发超时 | 默认 600s,上限 1800s;工具参数 timeoutMs 范围 5000~600000 |
| 嵌套 | allowNesting 默认 false;maxDepth 默认 1,界面与 IPC 最多 3 |
| 讨论轮次 | maxDiscussionRounds 默认 6,硬上限 20 |
| 讨论快照预算 | threadContextTokenBudget 默认 6000(500~40000) |
| 持久化 | sessions.metadata.team / agent_teams / team_dispatches / team_discussions |
| 账本 room | team-room:{sessionId}(每个 (room, discussion) 当前 key 上限 100) |
上手清单:在 Spark Work 里跑一场团队协作
开启团队模式、勾选成员、让 Host 派发并查看事件流与账本
- 先在「助手 → Agents」里准备好成员 Agent,各自配好模型、Skills 与提示词
- 在会话输入栏的 Agent 选择器里选「团队模式」,确认主持人
- 点横幅上的「管理成员」或打开右侧 Inspector,在「团队成员」里邀请成员
- 需要成员再派发下一层时,展开「高级」勾选「允许 Member 嵌套调用」并选最大深度
- 需要成员互聊时再勾「允许成员互相留言(实验性)」,并按需调整讨论轮次上限
- 给 Host 发任务,Host 会通过 mcp__spark_team__agent_dispatch 派发子任务
- 在群聊时间线里看成员消息、状态行与轮次分割线;必要时关掉团队过程日志只看结论
- 在 Inspector 的 Outcome Room 面板里 confirm / correct 需要固化的结论
- 想复用这套配置,在「团队成员」区块保存为长期团队,之后到「助手 → Teams」管理
常见问题
Host 和 Member 会共享上下文吗?
不会自动共享完整对话。成员拿到的是 Host 写的 instruction、inputs、附件、期望产出,加上当前讨论线程的截断快照和 Living Ledger 摘要。在真实讨论里,同一成员的 SDK 会话可以续接(continueSession),但 Host 与成员的对话历史是各自独立的。
成员之间能互相派发任务吗?
要看两个开关。嵌套派发需要 allowNesting=true 且 depth < maxDepth(界面最多 3 层);成员之间的对等消息需要 enablePeerMessaging=true,此时成员才拿到 agent_message 工具。两者互相独立:开了互聊但没有嵌套,成员也只能拿到 agent_message 和 team_thread_read。
为什么我的成员没被调度?
按顺序检查:该 Agent 是否启用、是否在会话的 memberAgentIds 里(Inspector「团队成员」勾选)、是否是嵌套场景但 allowNesting 为 false 或已到 maxDepth、本轮派发是否已经用满 10 次预算。失败原因会作为错误文案返回给 Host,也可以在群聊时间线里看到失败状态行。
一次能派发多少个任务?
agent_dispatch_batch 一次最多提交 10 个任务,但每个任务各计一次预算,而单 turn 派发预算正好是 10 次;超出的派发会返回 Dispatch budget exceeded 并触发续跑。serial 的 agent_dispatch 每个 turn 也共享同一份预算。
成员模型为什么和我选的不一样?
成员生效模型优先级是:成员 Agent 自己的 modelId → 会话当前模型(仅当它在该 Provider 的模型白名单里)→ Provider 默认模型。本地 CLI Provider 直接沿用 CLI 自己的模型。Provider 同理:成员没配就用会话的。
Outcome Room 的账本和聊天记录有什么区别?
聊天记录是线性时间流;账本是带版本的结构化状态。每条记录有 status、authority(user-confirmed > system-observed > agent-inferred)、来源和 version,支持 confirm / reject / correct / invalidate / restore,写入用 expectedVersion 做 CAS 防并发覆盖,历史事件只追加不删除。