From edba4102f18227fa433c03e04f23adbc3e3fa4f3 Mon Sep 17 00:00:00 2001 From: aalvii Date: Mon, 17 Aug 2026 02:20:32 +0800 Subject: [PATCH] feat: add focus mode to reduce human interruption --- README.md | 3 +++ README_ZH.md | 3 +++ docs/usage.md | 3 +++ src/index.ts | 22 +++++++++++++++++++--- 4 files changed, 28 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 78a8c9a4a5..e4923320e0 100644 --- a/README.md +++ b/README.md @@ -92,10 +92,13 @@ Defaults work without extra setup. A trusted profile can override member behavio memberModel: deepseek-v4 memberMaxDepth: 1 maxMembers: 8 + focusMode: true ``` `memberProvider` is the sub-agent runtime backend (`spawn` / `fork`), not an LLM provider. Cross-LLM-provider routing uses the optional `provider` + `model` fields of `agent_teams_add_member`; `memberModel` is only a model default for all members. +`focusMode` (default `false`) is a prompt-level guideline: when enabled, it asks the captain to only interrupt the human on completion, failure, or a decision that genuinely needs the user, and to batch the final team summary. It is not a hard notification filter — a model may still surface important updates. Set `true` to enable it. + ## Boundaries - One captain leads one active team at a time. diff --git a/README_ZH.md b/README_ZH.md index 9e69aac44c..4ead10c220 100644 --- a/README_ZH.md +++ b/README_ZH.md @@ -92,10 +92,13 @@ dsh web memberModel: deepseek-v4 memberMaxDepth: 1 maxMembers: 8 + focusMode: true ``` 这里的 `memberProvider` 指子 Agent 的运行后端(`spawn` / `fork`),不是 LLM provider。跨 LLM provider 由 `agent_teams_add_member` 的可选 `provider` + `model` 参数表达;`memberModel` 只是所有成员的模型默认覆盖。 +`focusMode`(默认 `false`)是 prompt 层引导:开启后让队长尽量只在“完成 / 失败 / 真正需要人决策”时打扰你,并把最终结果批量总结。它不是硬性通知过滤器,模型仍可能上报重要更新。设为 `true` 开启。 + ## 使用边界 - 一个队长同一时间只能带一个活动团队。 diff --git a/docs/usage.md b/docs/usage.md index 97fc18a81c..bddbbe5dfa 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -70,10 +70,13 @@ memberModel: deepseek-v4 # 可选:成员模型覆盖 memberMaxDepth: 1 # 成员再委派深度上限(0 = 禁止) maxMembers: 8 # 团队人数上限 + focusMode: true # 专注模式(prompt 层引导):尽量只在完成/失败/需决策时打扰人 ``` 最终优先级为:成员显式 `provider` + `model` / `model` → `memberModel` → 队长当前路由。思考强度默认继承队长当前值,并在目标 provider/model 上创建前校验;不兼容时成员创建会明确失败。最终生效的 provider/model/思考强度会写入 `team.json`,供状态查询和成员冷恢复使用。 +`focusMode`(默认 `false`)是专注模式,属于 **prompt 层引导**:开启后队长被要求只在“任务完成 / 任务失败 / 真正需要人决策”三类事件时向用户汇报,不刷过程进度,并把最终结果批量总结。它不是硬性通知过滤,模型仍可能上报重要更新。设为 `true` 开启。 + ## 使用协议 插件提示段会指导模型按协议执行:建团队 → 按角色拉成员 → 拆任务并声明依赖 → 共享调度器自动领取并唤醒空闲成员 → 队长监控/引导 → 阻塞时先安全转派或接管 → 汇报后 `agent_teams_delete`。成员之间可以直接互发消息,无需队长中转。成员若在中断、异常结束或进程重启后变成 `idle/ready`,但磁盘上仍持有 `claimed/in_progress` 任务,调度器会撤销旧 capability、生成新 attempt 并重新唤醒同一成员。 diff --git a/src/index.ts b/src/index.ts index 69ec9c6a5f..f6897cfa61 100644 --- a/src/index.ts +++ b/src/index.ts @@ -71,6 +71,12 @@ export interface Config { maxMembers?: number /** Prompt-section order for the usage policy (default `117`, after delegation policy). */ promptSectionOrder?: number + /** + * Focus mode (default `false`): a prompt-level guideline that asks the captain + * to only surface completion, failure, or decisions that need the user, and to + * batch the final summary. It is not a hard notification filter. + */ + focusMode?: boolean } export const Config: z = z.object({ @@ -80,10 +86,20 @@ export const Config: z = z.object({ memberMaxDepth: z.natural().default(1), maxMembers: z.natural().min(1).default(8), promptSectionOrder: z.natural().default(117), + focusMode: z.boolean().default(false), }) /** The model-facing usage policy: when and how to drive AgentTeams. */ -function usageSectionText(toolNames: string): string { +function usageSectionText(toolNames: string, focusMode: boolean): string { + const focusProtocol = focusMode + ? ` +Focus mode is ON. Follow these rules to protect the human's attention: +1. Notify the user only on three event kinds: a task completed, a task failed, or a decision genuinely needs the user. Do not send progress pings, status refreshes, or routine member messages as they happen. +2. Keep the human-visible task list short. Only put tasks that need human domain knowledge or final judgment on the main line; push everything else to background/autonomous work. +3. When agents are running, do not start extra deep tasks just to fill waiting time. Let the human rest; batch the final team summary instead of streaming intermediate updates. +4. If a task is blocked or needs a human decision, mark it clearly as needs-decision and wait. Do not repeatedly re-trigger the same interruption. +` + : '' return `When the user asks to run something with AgentTeams (e.g. "use AgentTeams to do X"), you are the captain of a multi-agent team. Follow this protocol: 1. Call agent_teams_create with a team name and the goal as description. You become the captain and may lead one team at a time. 2. Call agent_teams_add_member once per role the goal needs (researcher, engineer, reviewer, ...). Members are durable subagents: they wait for your messages, then work a full turn. By default each member snapshots your current provider, model, and reasoning effort. Never ask the user to choose these per member; only pass provider/model when the user explicitly requests a different route for that role. @@ -92,7 +108,7 @@ function usageSectionText(toolNames: string): string { 5. If work is blocked, stale, or needs takeover, always call agent_teams_reassign_task first. Reassign to another idle member, or use assignee=captain before doing it yourself. Reassignment revokes the old attempt and waits for that member to quiesce, preventing late results from overwriting the new attempt. 6. Tasks carry attempt_id capabilities. Members must use the current attempt_id for updates; stale-attempt errors mean ownership changed. Poll status until every required task is terminal and every member is idle/ready. 7. Present the team's results to the user, then agent_teams_delete the team unless the user wants to keep working with it. - +${focusProtocol} Tools: ${toolNames}` } @@ -126,7 +142,7 @@ export function apply(ctx: Context, config: Config): void { ctx.systemPrompt.section({ name: 'agent-teams:usage', order: config.promptSectionOrder ?? 117, - text: usageSectionText(toolNames), + text: usageSectionText(toolNames, config.focusMode ?? true), }) registerAgentTeamsTools(ctx, resolved)