feat(beaver): 完成Task Team功能v1实现,重构后端架构支持统一内核
新增内部Task系统,包括验证、反馈门控机制,实现自动质量验证 (通过率>=0.75)和用户反馈闭环(satisfied/revise/abandon)。 实现Agent Team v1协调器,支持sequence/parallel/dag执行策略, sub-agent复用主AgentLoop,每个run使用独立memory snapshot。 建立Skill学习pipeline,包含draft/审核/发布/回滚完整生命周期, 通过Task验证通过且用户满意才生成学习候选。 重构目录结构,移除third_party依赖,建立统一engine内核, 所有agent共享运行时基础组件。 更新ContextBuilder清理provider消息字段,增强SkillContext版本管理, 集成TaskExecutionPlanner和TaskSkillResolver实现技能解析机制。
This commit is contained in:
@ -4,6 +4,96 @@
|
||||
|
||||
目标是:**按运行时主链路,一步一步把 `backend-old` 的能力迁进新的 `beaver` 后端,并且始终保证我们先打通主链,再扩外围。**
|
||||
|
||||
文档分工:
|
||||
|
||||
1. `flow.md`
|
||||
- 只保留树形运行结构
|
||||
- 只回答“现在 runtime 怎么接、模块怎么连”
|
||||
2. `施工指南.md`
|
||||
- 保留施工顺序、阶段目标、完成标准、迁移动作
|
||||
3. `change.md`
|
||||
- 保留长期蓝图、设计动机、参考项目边界、架构判断
|
||||
|
||||
---
|
||||
|
||||
## 0. 当前施工状态(2026-05-07)
|
||||
|
||||
当前新后端已经完成的不只是最小 `AgentLoop` 主链,而是已经把 Main Agent 自动 Task 化、反馈学习闭环、Agent Team v1 轻量 coordinator,以及 Task mode 内部 team 执行规划链路接入到了内部服务层。
|
||||
|
||||
已完成:
|
||||
|
||||
1. `AgentService.process_direct/submit_direct` 前置 Main Agent 路由。
|
||||
- `simple`:直接走原有单轮回答,不创建 Task。
|
||||
- `task`:内部自动创建或复用 Task。
|
||||
2. 内部 Task 子系统已落地。
|
||||
- `beaver/tasks/models.py`
|
||||
- `beaver/tasks/store.py`
|
||||
- `beaver/tasks/service.py`
|
||||
- `beaver/tasks/router.py`
|
||||
- `beaver/tasks/validation.py`
|
||||
3. `AgentLoop.process_direct()` 已支持内部参数:
|
||||
- `task_id`
|
||||
- `task_mode`
|
||||
- `attempt_index`
|
||||
- `learning_candidate_enabled`
|
||||
4. `RunRecord` 已记录:
|
||||
- `task_id`
|
||||
- `attempt_index`
|
||||
- `validation_result`
|
||||
5. Task 模式完成后会自动验证。
|
||||
- 通过 `ValidationService.validate_task_result(...)` 生成结构化 `ValidationResult`
|
||||
- 验证失败自动修订一次
|
||||
- 第一次失败尝试会从可见上下文隐藏,避免用户刷新后看到被系统判失败的草稿
|
||||
6. 聊天反馈接口已落地。
|
||||
- `POST /api/chat/feedback`
|
||||
- 通过 `run_id -> task_id` 找到内部 Task
|
||||
- `satisfied / revise / abandon` 三种反馈
|
||||
- 反馈状态投影回最近 assistant 消息,刷新后保留
|
||||
7. 前端已做最小反馈控件。
|
||||
- 最新 assistant Task 结果下显示“满意 / 需要修改 / 放弃”
|
||||
- REST 和 WebSocket 路径都会携带或刷新 `run_id/task_id/validation_result`
|
||||
8. 学习触发已经收紧。
|
||||
- Task 模式 run 不再直接生成成功学习候选
|
||||
- 只有“自动验证通过 + 用户点击满意”才触发成功学习候选
|
||||
- “放弃”写 Failure Memory,不生成成功 Skill draft
|
||||
9. Agent Team v1 已落地为 Beaver 自有轻量 coordinator。
|
||||
- 新增 `AgentDescriptor / DelegationEnvelope / ExecutionNode / ExecutionGraph / TeamRunResult`
|
||||
- 新增 `TeamService.run_team(...)` 作为内部服务入口
|
||||
- 新增 `LocalAgentRunner`,sub-agent 复用主 `AgentLoop.process_direct()` / `submit_direct()`
|
||||
- 支持 `sequence / parallel / dag` 三个执行原语
|
||||
- `parallel` 和 DAG 同层节点保持真并发
|
||||
- sub-agent 使用 per-run memory snapshot,避免并发串记忆
|
||||
- 支持 pinned skill 继承,open skills 继续由 `SkillAssembler` 补充
|
||||
- 支持 per-node `provider_bundle_factory`
|
||||
- 父 `Task` 前置校验,sub-agent run_ids 回填父 Task
|
||||
- 节点级异常归一成 `NodeRunResult`,summary 只聚合成功输出并列出失败节点
|
||||
10. Agent Team 已接入 Task mode 内部执行链。
|
||||
- 新增 `beaver/tasks/planner.py`
|
||||
- `TaskExecutionPlanner` 使用 LLM JSON 规划 `single / team`
|
||||
- team node 只声明 `skill_query / required_capabilities`,不声明固定 specialist 人设
|
||||
- 新增 `beaver/tasks/skill_resolver.py`
|
||||
- `TaskSkillResolver` 为 generic sub-agent 选择 published skill;未命中时生成 draft-only skill,并作为本次 run 的 ephemeral pinned instruction 使用
|
||||
- 只允许 v1 已实现的 `sequence / parallel / dag`
|
||||
- planner 失败或 graph 非法时降级为 `single`
|
||||
- team run 先作为 sub-agent 内部执行,输出注入主 Agent synthesis run
|
||||
- 用户可见最终回答仍由主 Agent 生成,再进入验证、反馈和学习门控
|
||||
- 隐藏事件记录 `task_execution_planned / task_team_run_completed / task_team_run_failed`
|
||||
11. Skill Learning 后台 pipeline 已落地为 assisted learning,而不是自动上线。
|
||||
- candidate 状态扩展为 `open / queued / synthesizing / draft_ready / safety_failed / eval_failed / review_pending / approved / rejected / published / failed / superseded`
|
||||
- `SkillLearningWorker` 支持按配置后台扫描,也支持 `POST /api/skills/learning/run-once`
|
||||
- worker 自动到 draft/safety/eval 为止,永不自动 approve/publish
|
||||
- 每个 draft 发布前必须有 safety report;critical/safety failed 直接阻断
|
||||
- eval failed 阻断 publish;provider 不可用时记录 `skipped_provider_unavailable`
|
||||
- 前端 skills 页已提供候选、草稿、安全报告、评估报告、审核、发布、禁用、回滚入口
|
||||
|
||||
当前仍未完成:
|
||||
|
||||
1. Agent Team 不暴露产品级聊天路由或显式 Task API;当前只作为 Task 内部 sub-agent 执行策略。
|
||||
2. `moa / hierarchy / heavy / group_chat / forest / maker / router` 仍只是预留策略,不是 v1 完整行为。
|
||||
3. 自动验证还是 LLM validator,不是 replay sandbox。
|
||||
4. Skill Learning 当前是 assisted pipeline,不做低风险自动发布;自动发布/灰度发布仍是未来阶段。
|
||||
5. `/api/agents` 和 agent registry 可作为未来外部 agent/A2A 管理面保留,但不参与 Task sub-agent 选择。
|
||||
|
||||
---
|
||||
|
||||
## 1. 施工总原则
|
||||
@ -55,6 +145,38 @@
|
||||
|
||||
不允许再出现“CLI 一套 loop、delegation 一套 loop、team 一套 loop”的情况。
|
||||
|
||||
### 1.5 参考项目怎么用,边界先写死
|
||||
|
||||
这版施工指南对应的是 `2026-05-06` 已重新核对后的参考口径。我们确认过的公开入口:
|
||||
|
||||
1. `OpenHarness`
|
||||
- <https://github.com/HKUDS/OpenHarness>
|
||||
2. `hermes-agent`
|
||||
- <https://github.com/NousResearch/hermes-agent>
|
||||
3. `swarms`
|
||||
- <https://github.com/kyegomez/swarms>
|
||||
|
||||
后续施工时,这三个项目只按下面的方式使用:
|
||||
|
||||
1. `OpenHarness`
|
||||
- 参考它的 harness 分层和统一 loop 组织方式
|
||||
- 用来校正目录边界:`engine / tools / skills / permissions / memory / coordinator / interfaces`
|
||||
- 不照搬它的 CLI/TUI、commands、plugin 生态,也不追求目录一模一样
|
||||
2. `hermes-agent`
|
||||
- 参考它的 memory / session / session_search / skills 关系
|
||||
- 重点借鉴:durable memory、frozen snapshot、FTS5 transcript search、显式 skill 注入、session lineage
|
||||
- 不把自动 skill 学习闭环、完整渠道网关、全部远端 backend 一次性纳入当前施工范围
|
||||
3. `swarms`
|
||||
- 只作为后续多智能体 execution backend / strategy 来源
|
||||
- 重点借鉴:sequential / hierarchy / rearrange / router 这类编排形态
|
||||
- 不允许它定义 Beaver 的主 runtime、session、tool、provider 契约
|
||||
|
||||
把这条边界写死的原因很简单:
|
||||
|
||||
1. 当前阶段先把单 agent 主链做稳
|
||||
2. 多智能体回迁时只能挂到 Beaver 自己的 coordinator/backend 抽象下面
|
||||
3. 不再恢复 `third_party/swarms` 那种由第三方目录反向定义平台结构的做法
|
||||
|
||||
---
|
||||
|
||||
## 2. 从运行时视角看,系统到底怎么工作
|
||||
@ -908,14 +1030,457 @@ filesystem 这一版只做只读,不做写文件 / shell:
|
||||
- `skill_view`
|
||||
- `SkillAssembler`
|
||||
- `ToolAssembler`
|
||||
2. 还没完成长期智能体治理:
|
||||
2. 已完成学习闭环的第一层门控:
|
||||
- `RunRecord`
|
||||
- `SkillActivationReceipt`
|
||||
- `SkillEffectRecord`
|
||||
- `SkillLearningCandidate`
|
||||
- `TaskRecord`
|
||||
- `TaskEvent`
|
||||
- `ValidationResult`
|
||||
- `/api/chat/feedback`
|
||||
3. 还没完成长期智能体治理:
|
||||
- 智能体定期整理 / 提示记忆
|
||||
- 复杂任务完成后自主创建技能
|
||||
- 复杂任务完成后自动合成 skill draft 的后台 pipeline
|
||||
- 技能在使用过程中自我提升
|
||||
- FTS5 + LLM 摘要的跨会话回忆增强
|
||||
- Honcho 风格辩证用户建模
|
||||
- agentskills.io 开放标准兼容
|
||||
|
||||
这里要特别说明:这些“还没完成”的点里,**最不应该被误解成可有可无附件**的,就是
|
||||
Hermes 的 learning loop,也就是 Beaver 这里预想要落成的 `skills 学习能力`。
|
||||
|
||||
Hermes 官方公开说明里,明确把这些能力作为它的核心区别:
|
||||
|
||||
1. built-in learning loop
|
||||
2. creates skills from experience
|
||||
3. skills self-improve during use
|
||||
4. nudges itself to persist knowledge
|
||||
5. FTS5 session search for cross-session recall
|
||||
|
||||
参考:
|
||||
|
||||
1. <https://github.com/NousResearch/hermes-agent>
|
||||
2. <https://github.com/NousResearch/hermes-agent-self-evolution>
|
||||
|
||||
所以这里不是“我们没打算做”。当前阶段已经把 learning loop 的第一层接回主链:
|
||||
|
||||
1. 复杂任务自动进入内部 Task。
|
||||
2. Task run 必须经过自动验证。
|
||||
3. 成功学习候选必须等待用户满意反馈。
|
||||
4. 失败/放弃进入 Failure Memory。
|
||||
|
||||
当前已补齐 assisted learning pipeline:后台 skill draft synthesis、safety report、轻量 eval report、review/publish UI 已接入。它仍不是“全自动自学习系统”,因为自动发布、灰度发布、长期线上效果自动回滚仍保留为未来阶段。
|
||||
|
||||
### 5.3 skills 生命周期与学习闭环
|
||||
|
||||
这一步建议明确单列出来,不和 `5.2 skills 最小接入` 混为一谈。
|
||||
|
||||
`5.2` 解决的是:
|
||||
|
||||
1. skill 能被加载
|
||||
2. skill 能被选择
|
||||
3. skill 能注入当前 run
|
||||
4. skill frontmatter 能影响工具选择
|
||||
|
||||
`5.3` 要解决的是:
|
||||
|
||||
1. skill 如何被创建
|
||||
2. skill 如何被修订
|
||||
3. skill 如何被审核
|
||||
4. skill 如何被发布/禁用/回滚
|
||||
5. skill 的效果如何被记录与比较
|
||||
6. 哪个 skill 版本参与了哪次运行,如何留痕
|
||||
|
||||
### 5.3.1 第一批文件清单
|
||||
|
||||
先不要一上来做“自动改 skill”。第一批先把 skill 作为**可版本化、可审核、可留痕的能力对象**
|
||||
落成稳定边界。
|
||||
|
||||
建议先补这些文件:
|
||||
|
||||
1. `beaver/skills/specs/models.py`
|
||||
- 定义 `SkillSpec`
|
||||
- 定义 `SkillVersion`
|
||||
- 定义 `SkillReviewState`
|
||||
- 定义 `SkillDraft`
|
||||
- 定义 `SkillActivationReceipt`
|
||||
2. `beaver/skills/specs/serialization.py`
|
||||
- skill metadata/frontmatter 规范化
|
||||
- dataclass <-> dict/json 转换
|
||||
- 摘要哈希、正文哈希、版本指纹
|
||||
3. `beaver/skills/specs/storage.py`
|
||||
- 负责 `drafts/reviews/published/archive` 目录读写
|
||||
- 负责原子写入和版本索引
|
||||
4. `beaver/skills/drafts/service.py`
|
||||
- 创建 draft
|
||||
- 基于已有 skill version 生成修订 draft
|
||||
- 列出 / 读取 draft
|
||||
5. `beaver/skills/reviews/service.py`
|
||||
- 提交审核
|
||||
- 审核通过
|
||||
- 审核拒绝
|
||||
- 记录审核意见
|
||||
6. `beaver/skills/publisher/service.py`
|
||||
- draft -> published version
|
||||
- 禁用 skill
|
||||
- 回滚到历史版本
|
||||
- 更新“当前生效版本”指针
|
||||
7. `beaver/memory/runs/models.py`
|
||||
- 定义 `RunRecord`
|
||||
- 定义 `RunOutcome`
|
||||
- 定义 `SkillEffectRecord`
|
||||
8. `beaver/memory/runs/store.py`
|
||||
- 持久化 run receipts
|
||||
- 支持按 skill/version 查询历史效果
|
||||
9. `beaver/memory/skills/models.py`
|
||||
- 定义 `SkillPerformanceSnapshot`
|
||||
- 定义 `SkillLearningCandidate`
|
||||
10. `beaver/memory/skills/store.py`
|
||||
- 聚合 skill 版本的效果统计
|
||||
- 记录待学习/待修订候选
|
||||
|
||||
已有目录可直接接住这批文件:
|
||||
|
||||
1. `beaver/skills/drafts/`
|
||||
2. `beaver/skills/reviews/`
|
||||
3. `beaver/skills/publisher/`
|
||||
4. `beaver/memory/runs/`
|
||||
5. `beaver/memory/skills/`
|
||||
|
||||
建议新增:
|
||||
|
||||
1. `beaver/skills/specs/`
|
||||
|
||||
### 5.3.2 建议的磁盘布局
|
||||
|
||||
第一版先用 workspace 文件存储,不急着上数据库。
|
||||
|
||||
建议目录:
|
||||
|
||||
```text
|
||||
<workspace>/skills/
|
||||
├─ <skill-name>/
|
||||
│ ├─ skill.json # SkillSpec 稳定元数据
|
||||
│ ├─ current.json # 当前生效版本指针
|
||||
│ ├─ versions/
|
||||
│ │ ├─ v0001/
|
||||
│ │ │ ├─ SKILL.md
|
||||
│ │ │ └─ version.json
|
||||
│ │ └─ v0002/
|
||||
│ ├─ drafts/
|
||||
│ │ └─ draft-<id>.json
|
||||
│ ├─ reviews/
|
||||
│ │ └─ review-<id>.json
|
||||
│ └─ archive/
|
||||
└─ _index/
|
||||
├─ published.json
|
||||
├─ drafts.json
|
||||
└─ disabled.json
|
||||
```
|
||||
|
||||
`memory/runs/` 这边建议先用:
|
||||
|
||||
```text
|
||||
<workspace>/memory/runs/
|
||||
├─ runs.jsonl
|
||||
└─ skill-effects.jsonl
|
||||
```
|
||||
|
||||
这样第一版的优点是:
|
||||
|
||||
1. 容易调试
|
||||
2. 容易做 review/publish 流程
|
||||
3. 不和 session SQLite 强绑定
|
||||
4. 后面真要迁到 SQLite 或对象存储,模型层也不用重写
|
||||
|
||||
### 5.3.3 第一批核心数据结构
|
||||
|
||||
第一批数据结构建议严格控制在“运行时必需 + 生命周期必需”,不要先把智能学习策略混进去。
|
||||
|
||||
1. `SkillSpec`
|
||||
- 代表一个稳定的 skill 身份,不代表某个具体正文版本
|
||||
- 最少字段:
|
||||
- `name`
|
||||
- `display_name`
|
||||
- `description`
|
||||
- `created_at`
|
||||
- `updated_at`
|
||||
- `current_version`
|
||||
- `status`
|
||||
- `tags`
|
||||
- `owners`
|
||||
- `source_kind`
|
||||
- `lineage`
|
||||
2. `SkillVersion`
|
||||
- 代表某个已发布或待发布的具体版本
|
||||
- 最少字段:
|
||||
- `skill_name`
|
||||
- `version`
|
||||
- `content_hash`
|
||||
- `summary_hash`
|
||||
- `created_at`
|
||||
- `created_by`
|
||||
- `change_reason`
|
||||
- `parent_version`
|
||||
- `review_state`
|
||||
- `frontmatter`
|
||||
- `summary`
|
||||
- `tool_hints`
|
||||
- `provenance`
|
||||
3. `SkillDraft`
|
||||
- 代表尚未生效的候选修改
|
||||
- 最少字段:
|
||||
- `draft_id`
|
||||
- `skill_name`
|
||||
- `base_version`
|
||||
- `proposed_content`
|
||||
- `proposed_frontmatter`
|
||||
- `created_at`
|
||||
- `created_by`
|
||||
- `trigger_run_id`
|
||||
- `trigger_session_id`
|
||||
- `reason`
|
||||
- `status`
|
||||
4. `SkillReviewState`
|
||||
- 第一版先用枚举,不急着做复杂状态机
|
||||
- 最少值:
|
||||
- `draft`
|
||||
- `in_review`
|
||||
- `approved`
|
||||
- `rejected`
|
||||
- `published`
|
||||
- `disabled`
|
||||
- `archived`
|
||||
5. `SkillActivationReceipt`
|
||||
- 这是 learning loop 的关键 receipt
|
||||
- 只要 run 用到了某个 skill,就应落一条 receipt
|
||||
- 最少字段:
|
||||
- `run_id`
|
||||
- `session_id`
|
||||
- `skill_name`
|
||||
- `skill_version`
|
||||
- `content_hash`
|
||||
- `activated_at`
|
||||
- `activation_reason`
|
||||
- `tool_hints`
|
||||
6. `RunRecord`
|
||||
- 代表一次运行的可学习摘要
|
||||
- 最少字段:
|
||||
- `run_id`
|
||||
- `session_id`
|
||||
- `task_id`
|
||||
- `attempt_index`
|
||||
- `task_text`
|
||||
- `started_at`
|
||||
- `ended_at`
|
||||
- `success`
|
||||
- `finish_reason`
|
||||
- `validation_result`
|
||||
- `feedback`
|
||||
- `activated_skills`
|
||||
7. `SkillEffectRecord`
|
||||
- 连接 `RunRecord` 与 skill version 的效果记录
|
||||
- 最少字段:
|
||||
- `run_id`
|
||||
- `skill_name`
|
||||
- `skill_version`
|
||||
- `success`
|
||||
- `feedback_score`
|
||||
- `notes`
|
||||
- `created_at`
|
||||
8. `SkillPerformanceSnapshot`
|
||||
- 是聚合结果,不是原始 receipt
|
||||
- 最少字段:
|
||||
- `skill_name`
|
||||
- `skill_version`
|
||||
- `activation_count`
|
||||
- `success_count`
|
||||
- `failure_count`
|
||||
- `latest_used_at`
|
||||
- `last_feedback_score`
|
||||
9. `SkillLearningCandidate`
|
||||
- 描述一个“值得生成 draft”的候选
|
||||
- 最少字段:
|
||||
- `candidate_id`
|
||||
- `kind`
|
||||
- `new_skill`
|
||||
- `revise_skill`
|
||||
- `merge_skills`
|
||||
- `retire_skill`
|
||||
- `source_run_ids`
|
||||
- `source_session_ids`
|
||||
- `related_skill_names`
|
||||
- `reason`
|
||||
- `evidence`
|
||||
- `status`
|
||||
|
||||
### 5.3.4 第一批服务边界
|
||||
|
||||
第一版服务边界建议保持克制:
|
||||
|
||||
1. `DraftService`
|
||||
- `create_new_skill_draft(...)`
|
||||
- `create_revision_draft(...)`
|
||||
- `list_drafts(...)`
|
||||
- `get_draft(...)`
|
||||
2. `ReviewService`
|
||||
- `submit_for_review(draft_id, ...)`
|
||||
- `approve(draft_id, ...)`
|
||||
- `reject(draft_id, ...)`
|
||||
3. `SkillPublisher`
|
||||
- `publish(draft_id, ...)`
|
||||
- `disable(skill_name, ...)`
|
||||
- `rollback(skill_name, target_version, ...)`
|
||||
4. `RunMemoryStore`
|
||||
- `append_run_record(...)`
|
||||
- `append_skill_effect(...)`
|
||||
- `list_skill_effects(skill_name, version=None, limit=...)`
|
||||
5. `SkillLearningStore`
|
||||
- `record_learning_candidate(...)`
|
||||
- `list_learning_candidates(status=...)`
|
||||
- `update_performance_snapshot(...)`
|
||||
|
||||
### 5.3.5 第一批 runtime 接入点
|
||||
|
||||
先不要让 learning loop 自己乱改线上 skill。第一批只接这些点:
|
||||
|
||||
1. `engine/loop.py`
|
||||
- run 结束时写 `RunRecord`
|
||||
- 对本轮激活 skill 写 `SkillActivationReceipt`
|
||||
2. `skills/assembler/task_assembler.py`
|
||||
- 输出 skill name 时,尽量能带上当前 version/hash
|
||||
3. `skills/catalog/loader.py`
|
||||
- 只向 runtime 暴露已发布版本
|
||||
- 不默认暴露 draft / rejected / archived
|
||||
4. `tools/builtins/skill_view.py`
|
||||
- 默认看 published
|
||||
- 必要时增加看 draft/review 的管理模式
|
||||
|
||||
建议把这段 runtime 接入过程明确理解成下面这条树形主链:
|
||||
|
||||
```text
|
||||
用户输入 task
|
||||
│
|
||||
├─ AgentService._process_with_main_agent(...)
|
||||
│ ├─ MainAgentRouter.classify(...)
|
||||
│ │ ├─ simple -> 原有单轮回答,不创建 Task
|
||||
│ │ └─ task -> 创建或复用内部 Task
|
||||
│ └─ TaskService.create_task/get_latest_open_task(...)
|
||||
│
|
||||
├─ AgentLoop.boot()
|
||||
│ └─ EngineLoader.load()
|
||||
│ ├─ SessionManager
|
||||
│ ├─ MemoryStore
|
||||
│ ├─ MemoryService
|
||||
│ ├─ RunMemoryStore
|
||||
│ ├─ SkillLearningStore
|
||||
│ ├─ ToolRegistry
|
||||
│ ├─ ToolAssembler
|
||||
│ ├─ ToolExecutor
|
||||
│ ├─ SkillsLoader
|
||||
│ ├─ SkillAssembler
|
||||
│ ├─ SkillSpecStore
|
||||
│ ├─ DraftService
|
||||
│ ├─ ReviewService
|
||||
│ ├─ SkillPublisher
|
||||
│ ├─ EvidenceSelector
|
||||
│ ├─ SkillDraftSynthesizer
|
||||
│ ├─ SkillLearningService
|
||||
│ ├─ TaskService
|
||||
│ ├─ ValidationService
|
||||
│ └─ ContextBuilder
|
||||
│
|
||||
├─ AgentLoop.process_direct(task, task_id, task_mode, attempt_index)
|
||||
│ ├─ skill_assembler.assemble(...)
|
||||
│ │ └─ 返回带 `skill_name/version/content_hash/tool_hints` 的 activated_skills
|
||||
│ │
|
||||
│ ├─ 为每个 activated skill 构造 `SkillActivationReceipt`
|
||||
│ ├─ sessions.append_message(
|
||||
│ │ event_type="skill_activation_snapshotted",
|
||||
│ │ hidden,
|
||||
│ │ payload={receipts, activation_messages},
|
||||
│ │ )
|
||||
│ │
|
||||
│ ├─ tool_assembler.assemble(...)
|
||||
│ ├─ ContextBuilder.build_messages(...)
|
||||
│ ├─ provider/chat/tool loop
|
||||
│ ├─ sessions.append_message(event_type="run_completed" 或 "run_failed", hidden)
|
||||
│ │
|
||||
│ └─ AgentLoop._record_skill_learning(...)
|
||||
│ ├─ 构造 `RunRecord`
|
||||
│ ├─ 构造 `SkillEffectRecord[]`
|
||||
│ ├─ 默认只记录 receipts/effects,不生成学习候选
|
||||
│ ├─ Task 模式下先只记录 receipts,不立即生成成功学习候选
|
||||
│ ├─ 非 Task 模式也只走普通 run receipt 记录
|
||||
│ ├─ skill_learning_service.collect_run_receipts(...)
|
||||
│ │ ├─ RunMemoryStore.append_run_record(...)
|
||||
│ │ ├─ RunMemoryStore.append_skill_effect(...)
|
||||
│ │ ├─ SkillLearningService.rescore_skill_versions()
|
||||
│ │ │ └─ SkillLearningStore.update_performance_snapshot(...)
|
||||
│ │ └─ build_learning_candidates 只在显式门控允许时触发
|
||||
│ └─ sessions.append_message(
|
||||
│ event_type="skill_effects_snapshotted",
|
||||
│ hidden,
|
||||
│ payload={run_record, skill_effects, learning_candidates},
|
||||
│ )
|
||||
│
|
||||
├─ ValidationService.validate_task_result(...)
|
||||
│ ├─ 生成 `ValidationResult`
|
||||
│ ├─ TaskService.record_validation(...)
|
||||
│ ├─ RunMemoryStore.update_run_record(validation_result=...)
|
||||
│ ├─ sessions.append_message(event_type="task_validation_snapshotted", hidden)
|
||||
│ └─ 验证失败时自动重试一次
|
||||
│
|
||||
└─ /api/chat/feedback
|
||||
├─ satisfied + validation accepted -> close Task + build learning candidates
|
||||
├─ revise -> needs_revision,下条用户消息复用 Task
|
||||
└─ abandon -> abandoned + Failure Memory
|
||||
```
|
||||
|
||||
这里要特别强调:
|
||||
|
||||
1. `engine/loop.py` 第一版只负责记录 receipts / effects,默认不生成 candidates
|
||||
2. 成功学习候选只由 `AgentService.submit_feedback(... satisfied ...)` 在验证通过后触发
|
||||
3. `SkillLearningService` 第一版只负责生成候选,不负责自动上线
|
||||
4. `SkillDraftSynthesizer` 不应默认跑在 hot path 里,而应由显式后台流程或管理入口触发
|
||||
|
||||
### 5.3.6 第一批完成标准
|
||||
|
||||
先不要把“自学习”理解成“自动上线修改”。第一批完成标准只要达到下面这些就够:
|
||||
|
||||
1. skill 已经不是无版本 Markdown 文件,而是 `SkillSpec + SkillVersion`
|
||||
2. runtime 能明确记录“这次 run 用了哪版 skill”
|
||||
3. 系统能基于验证通过且用户满意的 Task 结果生成学习候选
|
||||
4. draft 必须经过 review/publish 才能进入正式 catalog
|
||||
5. rollback/disable 至少有最小实现
|
||||
6. published skill catalog 与 draft/review 状态严格隔离
|
||||
|
||||
最小闭环建议先做成:
|
||||
|
||||
1. run 结束后记录:
|
||||
- 本次激活了哪些 skill
|
||||
- skill 版本号/摘要哈希
|
||||
- 结果是否成功
|
||||
- 自动验证结果
|
||||
- 用户反馈
|
||||
2. Task 自动验证通过后等待用户点击“满意”
|
||||
3. 满意后允许 agent 或后台流程生成 learning candidate / `skill draft`
|
||||
4. draft 不直接生效,先进入 review/publish 流程
|
||||
5. 只有发布后的 skill version 才进入正式 runtime catalog
|
||||
|
||||
为什么这一步不能直接排到第一优先级:
|
||||
|
||||
1. 没有稳定 session / event stream,就没有可靠训练材料
|
||||
2. 没有稳定 skill catalog / activation 记录,就不知道“哪版 skill 起了作用”
|
||||
3. 没有 review / publish / rollback,就会把自我修改直接变成生产风险
|
||||
|
||||
为什么这一步又不能被一直拖着不做:
|
||||
|
||||
1. `skills` 是 Beaver 借 Hermes 的核心目标之一,不只是 prompt 包装
|
||||
2. 如果长期只有 `load/select/inject`,那 Beaver 的 `skills` 仍然更像静态文档目录
|
||||
3. 后续多 agent、procedure reuse、memory governance 都会反过来依赖 skill 生命周期
|
||||
|
||||
---
|
||||
|
||||
## 6. 第三施工阶段:把 direct run 扩成标准 runtime
|
||||
@ -1117,12 +1682,19 @@ app-instance 镜像也已经切到新 Beaver 后端:
|
||||
- Web 层现在已经有最小正式 schema:
|
||||
- `WebChatRequest`
|
||||
- `WebChatResponse`
|
||||
- `WebChatFeedbackRequest`
|
||||
- `WebChatFeedbackResponse`
|
||||
- `WebStatusResponse`
|
||||
- Web 请求处理时:
|
||||
- 用结构化 schema 校验输入
|
||||
- 只允许走 `await service.submit_direct(...)`
|
||||
- 将常见 runtime / config 错误收成明确的 HTTP 层错误
|
||||
- 外部注入但尚未进入 running mode 的 service,返回 `503`
|
||||
- `/api/chat/feedback`
|
||||
- 不暴露 Task 创建/管理 API
|
||||
- 只接收 `session_id/run_id/feedback_type/comment`
|
||||
- 后端通过 `run_id -> task_id` 找内部 Task
|
||||
- 同一 run 的重复同类反馈幂等,不同反馈会被拒绝
|
||||
- `/api/ping`
|
||||
- 返回 `status/running/mode`
|
||||
- 不会为了 health check 额外 boot runtime
|
||||
@ -1283,59 +1855,109 @@ app-instance 镜像也已经切到新 Beaver 后端:
|
||||
1. `backend-old/nanobot/agent/subagent.py`
|
||||
2. `backend-old/nanobot/agent/delegation.py`
|
||||
|
||||
这一阶段的范围:
|
||||
这一阶段的 v1 已完成范围:
|
||||
|
||||
1. 先支持 `spawn_subagent`
|
||||
2. 先支持 local delegation
|
||||
3. 暂不急着接 swarms team
|
||||
1. 先支持 local delegation,不引入独立 sub-agent runtime。
|
||||
2. `LocalAgentRunner` 调用现有 `AgentLoop.process_direct()` / `submit_direct()`。
|
||||
3. sub-agent 通过 `parent_session_id` 建立 session lineage。
|
||||
4. sub-agent run 通过父 `task_id` 归入当前主 agent Task。
|
||||
5. pinned skills 由主 agent 显式委派,sub-agent 必须注入。
|
||||
6. open skills 继续复用现有 `SkillAssembler`。
|
||||
|
||||
完成标准:
|
||||
|
||||
1. 主 agent 可以调用子 agent
|
||||
2. 子 agent 与主 agent 复用同一个 `AgentLoop`
|
||||
3. 只是 profile / toolset / prompt context 不同
|
||||
1. 主 agent 的当前 Task 可以包住 team run。
|
||||
2. 子 agent 与主 agent 复用同一个 `AgentLoop` 主链。
|
||||
3. 子 agent 不拥有独立 task store、独立 skill learning store、独立 runtime。
|
||||
4. sub-agent run receipt 自然进入主 Task 的学习门控。
|
||||
5. 学习候选仍必须等验证通过 + 用户满意,不因 team run 自动生成。
|
||||
|
||||
---
|
||||
|
||||
## 8. 第五施工阶段:接回群组讨论和流程化 team
|
||||
|
||||
这阶段才开始回收旧 `agent_team` 和 `swarms bridge` 的成果。
|
||||
这阶段已经先落地 Beaver 自己的 Agent Team v1,不再直接回接旧 `third_party/swarms` runtime。
|
||||
|
||||
### 8.1 先做 team types / planner / policy
|
||||
### 8.1 已落地的 team core
|
||||
|
||||
实现:
|
||||
已实现:
|
||||
|
||||
1. `beaver/coordinator/team/types.py`
|
||||
2. `beaver/coordinator/planner/swarms.py`
|
||||
3. `beaver/coordinator/backends/swarms/policy.py`
|
||||
1. `beaver/coordinator/models.py`
|
||||
- `AgentDescriptor`
|
||||
- `DelegationEnvelope`
|
||||
- `ExecutionNode`
|
||||
- `ExecutionGraph`
|
||||
- `NodeRunResult`
|
||||
- `TeamRunResult`
|
||||
2. `beaver/coordinator/local.py`
|
||||
- `LocalAgentRunner`
|
||||
- sub-agent 复用主 `AgentLoop.process_direct()` / `submit_direct()`
|
||||
- 禁止 `provider_bundle + node model/provider_name` 静默混用
|
||||
3. `beaver/coordinator/execution/scheduler.py`
|
||||
- `TeamGraphScheduler`
|
||||
- 支持 `sequence / parallel / dag`
|
||||
- 同层节点保持真并发
|
||||
- 节点级异常归一成 `NodeRunResult`
|
||||
- summary 只聚合成功输出,并列出 `Failed nodes`
|
||||
4. `beaver/services/team_service.py`
|
||||
- `TeamService.run_team(...)`
|
||||
- 执行前校验 `parent_task_id`
|
||||
- 执行后把 sub-agent `run_ids` 回填父 Task
|
||||
|
||||
### 8.2 再做 bridge / adapter
|
||||
### 8.2 当前 v1 策略边界
|
||||
|
||||
实现:
|
||||
当前只实现三个执行原语:
|
||||
|
||||
1. `beaver/coordinator/backends/swarms/bridge.py`
|
||||
2. `beaver/coordinator/backends/swarms/adapter.py`
|
||||
3. `beaver/coordinator/backends/swarms/runtime.py`
|
||||
1. `sequence`
|
||||
- 前一个成功节点输出进入下一个节点 dependency context。
|
||||
2. `parallel`
|
||||
- 同层节点并发执行。
|
||||
- 每个节点可通过 `provider_bundle_factory(node)` 拿 fresh provider bundle。
|
||||
3. `dag`
|
||||
- 按依赖拓扑分批执行。
|
||||
- 依赖失败节点的后续节点标记为 `blocked`。
|
||||
|
||||
以下策略只预留枚举,不在 v1 实现完整行为:
|
||||
|
||||
1. `moa`
|
||||
2. `hierarchy`
|
||||
3. `heavy`
|
||||
4. `group_chat`
|
||||
5. `forest`
|
||||
6. `maker`
|
||||
7. `router`
|
||||
|
||||
### 8.3 swarms 的新定位
|
||||
|
||||
注意:
|
||||
|
||||
1. 不再引入 `third_party/`
|
||||
2. 不再允许旧式 `sys.path` 注入
|
||||
3. `swarms` 必须作为 adapter/backend,而不是平台内部结构
|
||||
1. 不再引入 `third_party/`。
|
||||
2. 不再允许旧式 `sys.path` 注入。
|
||||
3. v1 不依赖 `swarms` runtime。
|
||||
4. swarms 的架构形态只作为策略参考,后续高级 preset 可以生成 Beaver `ExecutionGraph` 或 step loop。
|
||||
5. 如果以后确实要接 swarms,也必须作为 adapter/backend,而不是平台内部结构。
|
||||
|
||||
### 8.3 最后做 orchestrator
|
||||
### 8.4 当前 Task 内部 team 融合状态
|
||||
|
||||
实现:
|
||||
已经实现:
|
||||
|
||||
1. `beaver/coordinator/team/orchestrator.py`
|
||||
2. `beaver/coordinator/team/target_resolver.py`
|
||||
3. `beaver/coordinator/team/provisioning.py`
|
||||
1. `AgentService` 在 Task mode 内部按需调用 `TeamService`。
|
||||
2. `TaskExecutionPlanner` 通过 LLM JSON 规划 `single / team`。
|
||||
3. team 输出不直接面向用户,而是注入主 Agent synthesis run。
|
||||
4. `ValidationService` 可接收 `team_summaries` 辅助验证最终结果。
|
||||
5. 最小 observability 已落地为隐藏 session events,但不新增独立 team task store。
|
||||
|
||||
后续仍要做:
|
||||
|
||||
1. 将 `moa / hierarchy / heavy / group_chat / forest / maker / router` 作为 strategy preset 编译成 `ExecutionGraph` 或 step loop。
|
||||
2. 增加更清晰的 agent registry / target resolver。
|
||||
3. 补产品级过程视图,让前端能展示 Task 内部 team 规划和 sub-agent 执行过程。
|
||||
|
||||
这一阶段完成后,才算真正恢复:
|
||||
|
||||
1. 群组讨论
|
||||
2. 流程化 team
|
||||
3. skills 约束下的 multi-agent 执行
|
||||
1. 群组讨论。
|
||||
2. 高级 swarms 风格策略。
|
||||
3. skills 约束下的多 agent 执行。
|
||||
|
||||
---
|
||||
|
||||
@ -1437,6 +2059,81 @@ app-instance 镜像也已经切到新 Beaver 后端:
|
||||
3. `beaver/skills/resolver/runtime.py`
|
||||
4. `engine` 接入改动
|
||||
|
||||
### 提交 6:Main Agent 自动 Task 化与反馈验证闭环
|
||||
|
||||
文件:
|
||||
|
||||
1. `beaver/tasks/models.py`
|
||||
2. `beaver/tasks/store.py`
|
||||
3. `beaver/tasks/service.py`
|
||||
4. `beaver/tasks/router.py`
|
||||
5. `beaver/tasks/validation.py`
|
||||
6. `beaver/services/agent_service.py`
|
||||
7. `beaver/engine/loop.py`
|
||||
8. `beaver/engine/session/*`
|
||||
9. `beaver/interfaces/web/app.py`
|
||||
10. `beaver/interfaces/web/schemas/chat.py`
|
||||
11. `frontend/app/(app)/page.tsx`
|
||||
12. `frontend/components/chat-workbench/MessageList.tsx`
|
||||
13. `frontend/lib/api.ts`
|
||||
14. `frontend/lib/store.ts`
|
||||
15. `frontend/types/index.ts`
|
||||
|
||||
目标:
|
||||
|
||||
1. 聊天入口自动判断 simple / task。
|
||||
2. 不提供显式 Task 创建 API。
|
||||
3. Task 模式自动验证并失败重试一次。
|
||||
4. 用户反馈决定 Task close / revise / abandon。
|
||||
5. 成功学习候选必须由“验证通过 + 用户满意”触发。
|
||||
|
||||
### 提交 7:Agent Team v1 轻量 Coordinator
|
||||
|
||||
文件:
|
||||
|
||||
1. `beaver/coordinator/models.py`
|
||||
2. `beaver/coordinator/local.py`
|
||||
3. `beaver/coordinator/execution/scheduler.py`
|
||||
4. `beaver/services/team_service.py`
|
||||
5. `beaver/engine/loop.py`
|
||||
6. `beaver/services/memory_service.py`
|
||||
7. `tests/unit/test_agent_team_v1.py`
|
||||
|
||||
目标:
|
||||
|
||||
1. 定义 Beaver 自己的 team execution models。
|
||||
2. sub-agent 复用主 `AgentLoop.process_direct()` / `submit_direct()`。
|
||||
3. 支持 `sequence / parallel / dag`。
|
||||
4. `parallel` / DAG 同层节点保持真并发。
|
||||
5. 每个 run 使用独立 memory snapshot。
|
||||
6. 支持 pinned skill 继承和 open skill assembly。
|
||||
7. 支持 per-node provider bundle factory。
|
||||
8. parent Task 前置校验,sub-agent run_ids 回填父 Task。
|
||||
9. 节点异常归一成 `NodeRunResult`,不炸掉整次 team run。
|
||||
10. summary 只聚合成功输出,并清晰列出失败节点。
|
||||
|
||||
### 提交 8:Agent Team 与 Task mode 执行策略融合
|
||||
|
||||
文件:
|
||||
|
||||
1. `beaver/tasks/planner.py`
|
||||
2. `beaver/services/agent_service.py`
|
||||
3. `beaver/engine/loader.py`
|
||||
4. `beaver/tasks/validation.py`
|
||||
5. `beaver/coordinator/local.py`
|
||||
6. `tests/unit/test_task_execution_planner.py`
|
||||
7. `tests/unit/test_task_mode_feedback.py`
|
||||
|
||||
目标:
|
||||
|
||||
1. Task mode 每个 attempt 先规划 `single / team`。
|
||||
2. planner 只接受 `sequence / parallel / dag`,异常或非法 graph 降级 `single`。
|
||||
3. team run 使用 `TeamService.run_team(...)`,并归入父 Task。
|
||||
4. team 输出注入主 Agent synthesis run,不直接返回用户。
|
||||
5. 最终仍只围绕主 Agent synthesis run 做验证、反馈和学习门控。
|
||||
6. running mode 下 sub-agent 通过 `AgentLoop.submit_direct()` 执行,direct mode 下继续用 `process_direct()`。
|
||||
7. 隐藏事件记录规划和 team 执行结果。
|
||||
|
||||
---
|
||||
|
||||
## 11. 第一阶段验收清单
|
||||
@ -1455,6 +2152,61 @@ app-instance 镜像也已经切到新 Beaver 后端:
|
||||
|
||||
如果这 9 条没过,不要进入下一阶段。
|
||||
|
||||
当前 Main Agent / Task 闭环还应额外验收:
|
||||
|
||||
1. 简单问题不创建 Task。
|
||||
2. 复杂请求自动创建 Task。
|
||||
3. 同 session 的修订反馈会复用未关闭 Task。
|
||||
4. Task run 完成后必定写 `task_validation_snapshotted`。
|
||||
5. 验证失败自动重试一次。
|
||||
6. 首次失败草稿不会留在可见上下文。
|
||||
7. `/api/chat/feedback` 能通过 `run_id` 找到内部 Task。
|
||||
8. 同一 run 的重复同类反馈幂等,冲突反馈拒绝。
|
||||
9. `satisfied` 只有在验证通过后触发成功学习候选。
|
||||
10. `abandon` 写 Failure Memory,不生成成功 Skill draft。
|
||||
11. 前端最新 assistant Task 结果显示反馈按钮。
|
||||
12. WebSocket 和 REST 路径都能保留 `run_id/task_id/validation_result`。
|
||||
|
||||
当前 Agent Team v1 还应额外验收:
|
||||
|
||||
1. `LocalAgentRunner` 复用主 `AgentLoop.process_direct()` / `submit_direct()`。
|
||||
2. pinned skill 能注入 sub-agent context。
|
||||
3. `sequence` 能传递上游输出。
|
||||
4. `parallel` 多节点能真并发执行。
|
||||
5. `dag` 遵守依赖,失败节点阻断下游。
|
||||
6. parent Task 不存在或 session 不匹配时,执行前拒绝。
|
||||
7. valid parent Task 会回填 sub-agent `run_ids`。
|
||||
8. provider factory 节点异常会归一成失败节点,不取消其它节点。
|
||||
9. `provider_bundle + node model/provider_name` 不会被静默忽略。
|
||||
10. summary 不把失败输出混入成功摘要。
|
||||
11. direct run 和 team run 默认只写 receipts/effects,不生成 learning candidates。
|
||||
12. Task mode team plan 会先产生 sub-agent runs,再产生主 Agent synthesis run。
|
||||
13. 父 Task 的 `run_ids` 同时包含 sub-agent runs 和主 Agent synthesis run。
|
||||
14. team summary 进入主 Agent execution context,而不是直接作为用户最终回答。
|
||||
15. team 节点失败时仍由主 Agent synthesis 生成最终回答。
|
||||
16. 验证失败重试时会重新规划,并隐藏第一次主 Agent synthesis 草稿。
|
||||
|
||||
当前 Task Skill Resolver / Process / Learning Pipeline 还应额外验收:
|
||||
|
||||
1. planner team JSON 支持 `skill_query / required_capabilities`,不要求 agent role。
|
||||
2. `TaskSkillResolver` 命中 published skill 时,写入 `ExecutionNode.inherited_pinned_skills`。
|
||||
3. sub-agent run 的 published pinned skill receipt 记录 `activation_reason=pinned_delegation`。
|
||||
4. 未命中 skill 时创建 draft-only skill,并写入 `ExecutionNode.inherited_pinned_skill_contexts`。
|
||||
5. draft-only skill receipt 记录 `activation_reason=generated_missing_skill`。
|
||||
6. missing skill draft 不自动 approve/publish,不进入 runtime skill catalog。
|
||||
7. plan event 写入 `skill_queries / selected_skill_names / generated_skill_draft_ids / skill_resolution_report`。
|
||||
8. `/api/sessions/{session_id}/process` 能把隐藏 Task/team/validation 事件投影成 `processRuns / processEvents`。
|
||||
9. ChatWorkbench 桌面端有 `ProcessLane`,移动端有 `Process` tab。
|
||||
10. process view 展示 selected skills、generated draft id、ephemeral skill used,不展示 specialist agent selection。
|
||||
11. team 部分失败时,process view 显示失败节点,但最终回答仍来自主 Agent。
|
||||
12. `SkillLearningPipelineService` 能串起 candidate -> draft -> safety/eval -> review -> approve/reject -> publish。
|
||||
13. rejected draft 不能 publish。
|
||||
14. draft 在 publish 前不能进入 runtime skill catalog。
|
||||
15. publish 必须要求 approved review + safety passed + eval not failed;high risk 需要显式确认。
|
||||
16. rollback / disable 必须通过 publisher 写入 skill spec,而不是直接改 Markdown。
|
||||
17. 后端全量单测应通过:`uv run pytest`。
|
||||
18. 前端至少通过:`npm run typecheck`、`npm test`、`npm run lint`。
|
||||
|
||||
---
|
||||
|
||||
## 12. 施工时要避免的错误
|
||||
|
||||
Reference in New Issue
Block a user