Skip to content

feat: add model routing hints and ShouldDelegateTask for simple task delegation#4893

Closed
eghrhegpe wants to merge 6 commits into
esengine:main-v2from
eghrhegpe:pr-delegate-routing
Closed

feat: add model routing hints and ShouldDelegateTask for simple task delegation#4893
eghrhegpe wants to merge 6 commits into
esengine:main-v2from
eghrhegpe:pr-delegate-routing

Conversation

@eghrhegpe

@eghrhegpe eghrhegpe commented Jun 20, 2026

Copy link
Copy Markdown
Contributor

改动

1. 跳过 executor - planner 说"无需改动"时

Coordinator.Run() 在 plan() 返回后检查 isNoOpPlan():

  • 13 个中文短语(无需改动、已经处理等)+ 9 个英文短语 + [no_changes] 标记
  • 命中时直接输出 plan 文本,跳过 executor(Flash 不再重跑分析)

2. formatHandoff 指令优化

  • "Ignore any planner statement" 改为 "Planners conclusions are reliable"
  • 让 executor 尊重而非无视 planner 的结论

3. ShouldDelegateTask(auto_plan.go)

  • 新函数检测简单请求(<30词、无列表、无复杂意图词)可委托
  • Coordinator 可选接线,不改变原有 skip/plan 路径
  • 子 agent 模型名从 config.subagent_model 读取

文件

internal/agent/coordinator.go / control/auto_plan.go / boot/boot.go

Cache-impact: low -- ShouldDelegateTask 和 isNoOpPlan 都是纯启发式函数,不涉及系统提示词变更;Coordinator 的 delegation hint 是 user turn 文本;boot.go 接线不改变工具注册顺序
Cache-guard: go test ./internal/control/ ./internal/agent/
System-prompt-review: @SivanCola -- boot.go 类型断言接线不改前缀结构

@github-actions github-actions Bot added v2 Go rewrite (1.x) — main-v2 branch, active development agent Core agent loop (internal/agent, internal/control) config Configuration & setup (internal/config) labels Jun 20, 2026
… config

1. ShouldDelegateTask now rejects short inputs containing complex intent
   terms (refactor, migrate, implement, etc.) — prevents skipping planner
   for genuinely complex tasks that happen to be under 30 words.

2. Coordinator now has a subAgentModel field. Delegation hint uses this
   model name instead of a hardcoded deepseek-flash. boot.go wires it
   from cfg.Agent.SubagentModel when available.
@eghrhegpe

Copy link
Copy Markdown
Contributor Author

主要是双模型强制自动计划太抽象了:
你撞到双模型架构的一个真实 bug 了。 问题链很清楚:

Bug 还原
Pro (planner) 进入 planning 阶段

搜索 7 个文件、读取 3 个文件 ← Pro 分析完了

结论:"没有需要改的代码" ← 应该到此为止

Coordinator.Run() 无条件进入 executing ← 🔴 这里没有门控

Flash (executor) 重新搜索、重新读文件 ← 重复 Pro 的工作

Flash 得出同样的结论 ← 完全浪费
根因
Coordinator.Run() 在 plan() 返回后没有任何判断,直接进入 executing:

// coordinator.go:172-178
plan, err := c.plan(ctx, input) // Pro 产出了 plan
// ← 这里应该有一个 "this plan requires changes?" 的判断
c.sink.Emit(event.Event{Kind: event.Phase, Text: c.executor.prov.Name() + " · executing"})
return c.executor.Run(ctx, formatHandoff(input, plan))
解法分析
方案 机制 准确性 复杂度
A. 约定标记 Planner system prompt 要求:无需改动时输出 [NO_CHANGES],Coordinator 检测标记跳过 executor ⭐⭐⭐⭐ 低(改 prompt + 3 行代码)
B. 启发式 Plan 文本 <100 字符 → 跳过 executor ⭐⭐(短 plan 也可能真要改) 极低(1 行)
C. LLM 分类 用已有的 AutoPlanClassifier 判断 plan 是否提出改动 ⭐⭐⭐⭐⭐ 中(复用已有 infra)
推荐 A + B 组合:

Planner 主动标 [NO_CHANGES](准确)
Plan 极短时也跳过(兜底)
都不需要新增 LLM 调用

@eghrhegpe

Copy link
Copy Markdown
Contributor Author

实际情形:
deepseek · planning
deepseek · executing
这个步骤的衔接在历史对话原来是不可视的吗?

thinking
done
deepseek · planning

Search 1 files

thinking
done

Search 4 files

thinking
done

Read 2 files

thinking
done

Read 1 files · Search 1 files

thinking
done
对,始终不可视。 Phase 事件只活在当轮 UI 里,从不写入会话历史。

证据在 textsink.go:115-120:

case event.Phase: // ← 只在实时输出时触发
if s.wroteAnything {
fmt.Fprintln(s.out)
}
fmt.Fprintf(s.out, "[%s]\n", e.Text) // 打印到终端
s.wroteAnything = true
而会话 JSONL 存储的是 provider.Message(system/user/assistant/tool),在 session.go 里只有 Messages []provider.Message——没有 event 字段。

数据流对比:

内容 实时终端 历史 JSONL
[deepseek · planning] ✅ 显示 ❌ 不存
[deepseek · executing] ✅ 显示 ❌ 不存
planner 输出的 plan 文本 ✅ 显示 ❌ 不存(planner session 独立)
executor 的工具调用/回复 ✅ 显示 ✅ 存入
所以回头看历史时,你永远看不到 planning → executing 的切换标记和 planner 产出的原始计划——只能看到 executor 最终执行的结果。这是双模型模式下的一块信息盲区。

deepseek · executing

thinking
done


bash
85 ms

thinking
done


bash
2 lines
138 ms

thinking
done


bash
6 lines
106 ms

thinking
done


bash
10 lines
111 ms

thinking
done
对,[deepseek · planning] 和 [deepseek · executing] 这两个阶段标签不在历史里。


bash
11 lines
137 ms

thinking
done
区别:

内容 会话历史里有吗?
[deepseek · planning] 标签 ❌ 从不存
[deepseek · executing] 标签 ❌ 从不存
plan 文本本身 ✅ 有——formatHandoff() 把 plan 嵌入 executor 的 user message
executor 的工具调用 ✅ 有
所以回头看历史时你看不到 planning→executing 的切换标记,但能看到 planner 产出的原始计划(因为它在 executor 收到的那条消息里)。

算是一个小盲区但不算致命。要加的话需要在 session.go 的 provider.Message 里加一个 role: "phase" 类型。改动不大但涉及存储格式变更。

@eghrhegpe eghrhegpe force-pushed the pr-delegate-routing branch from 2b24dab to 291641d Compare June 20, 2026 05:32
@github-actions github-actions Bot added desktop Wails desktop app (desktop/**) skills Skill system (internal/skill, internal/tool) labels Jun 20, 2026
@eghrhegpe eghrhegpe force-pushed the pr-delegate-routing branch 4 times, most recently from 2b24dab to c38d6b2 Compare June 20, 2026 05:54
Two changes:
1. Coordinator.Run() now checks isNoOpPlan() after plan() returns.
   If the planner says no changes needed, emit plan text directly
   and return — skipping the executor entirely. This prevents the
   executor (Flash) from re-doing the planner's analysis work.

2. formatHandoff now tells the executor to respect the planner's
   conclusions, not ignore them.

isNoOpPlan detects phrases like 'no changes needed', 'already
implemented', and the explicit marker '[no_changes]'.
@SivanCola

Copy link
Copy Markdown
Collaborator

Thanks @eghrhegpe. I consolidated the PE-relevant part of this PR into #4938.

What was kept:

  • the no-op planner conclusion skip was adapted into the integration PR;
  • the executor handoff wording now respects planner conclusions while still treating planner capability limits as planner-only.

What was not kept:

  • model-routing hints, ShouldDelegateTask, and broader delegation prompt changes are outside the focused PE handoff/routing fix.

Your contribution is credited in #4938 under Repository Contributor Credits. Closing this PR in favor of the integration PR.

@SivanCola SivanCola closed this Jun 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agent Core agent loop (internal/agent, internal/control) config Configuration & setup (internal/config) desktop Wails desktop app (desktop/**) skills Skill system (internal/skill, internal/tool) v2 Go rewrite (1.x) — main-v2 branch, active development

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants