Beaver Backend 可视化

基于 app-instance/backend 当前代码结构绘制,适合配合讲解使用:先给零基础读者建立概念,再逐页展开 Task、自学习、Skill/Tool、Memory/Session 和 Agent Team。

项目对比分析 范围: backend 入口: Web / CLI / Gateway / MCP 核心: shared AgentLoop

先把它当成一个“帮用户完成任务的后台工厂”

如果你完全没接触过后端、agent、skills、tools,先看这一页。它不要求你理解代码细节。

整体理解:用户一句话如何变成后台执行

用户说需求网页、命令行或其他入口收到一句话
入口接住把请求整理成后端内部格式
判断类型普通聊天还是需要跟踪的任务
执行任务选择技能、工具并调用模型
保存过程记录 session、task、run 和反馈
返回结果把最终答复展示给用户

这个后端在做什么

用户在前端发一句话,后端负责判断这句话是不是一个任务、要不要查资料或改文件、需不需要拆给多个小助手处理,最后把结果和过程记录下来。

为什么要分这么多层

因为“接收请求”“决定怎么做”“调用模型”“使用工具”“保存记忆”“学习新技能”是不同职责。分开以后,问题更容易定位,也方便单独替换或测试。

最重要的一句话

所有真正执行 agent 的地方,最后都会回到同一个 AgentLoop。这保证主 agent 和 sub-agent 用同一套运行规则。

看图时抓住四类东西

入口负责接话,服务层负责安排,运行内核负责执行,能力层提供工具、技能、记忆和外部连接。

用户

在网页、命令行或其他渠道输入一句话,比如“帮我整理这个项目的后端架构”。

入口层

把这句话接住,整理成后端能理解的请求格式。

服务层

判断这是不是一个任务。如果只是闲聊,就简单回答;如果需要执行,就创建或继续一个 Task。

运行内核

准备上下文、挑选技能和工具、调用大模型,并在模型要求使用工具时执行工具。

能力层

提供文件读写、搜索、记忆、MCP、定时任务、外部集成等具体能力。

状态层

记录这次对话、任务、工具结果、验证结果和用户反馈,方便继续任务或沉淀经验。

Backend

前端背后的服务程序。用户看不见它的界面,但所有保存、调用模型、执行工具都在这里发生。

Agent

可以根据目标自己决定下一步动作的模型运行单元,不只是简单问答。

Task

一个需要跟踪结果的工作项,例如实现功能、分析代码、修复问题。

Skill

给 agent 的专门说明书,告诉它处理某类任务时应该遵循什么步骤和标准。

Tool

agent 可以调用的具体动作,比如读文件、写文件、搜索、执行命令、访问 MCP。

Memory

系统保存的历史、经验、任务结果和反馈,让后续运行可以参考。

Demo:一句普通需求如何被后台处理

适合开场讲解:先不讲代码,只讲用户输入、后台判断、最终输出。

输入

{
  "user_message": "帮我总结 backend 的 Task 机制",
  "channel": "web"
}

后台理解

{
  "is_task": true,
  "reason": "需要阅读代码并产出解释",
  "needs_tools": ["read_file", "search_files"],
  "needs_memory": true
}

预期输出

{
  "answer": "Task 是一张可追踪工作单...",
  "task_created": true,
  "saved_to_session": true,
  "can_continue_later": true
}

模块分层与依赖方向

这一页只展示大模块位置和依赖方向,适合先建立全局地图。

入口 服务 运行内核 能力 状态

四层架构:从入口到能力

InterfacesWeb、CLI、Gateway、MCP 等入口
Services把请求安排成内部工作流
Engine统一 AgentLoop 执行模型调用和工具循环
CapabilitiesSkills、Tools、Memory、Permissions

Interfaces 薄入口

Application Services

Shared Runtime

Capabilities + State

Demo:同一个请求经过四层架构

用一条请求把每层职责串起来,说明每层只做自己的事。

输入

POST /api/chat
{
  "session_id": "web-demo-001",
  "message": "请分析这个项目的后端结构"
}

层级流转

{
  "interfaces": "接收 HTTP 请求",
  "services": "判断是否进入 Task mode",
  "engine": "调用模型并执行工具",
  "capabilities": "提供 skill、tool、memory"
}

预期输出

{
  "session_id": "web-demo-001",
  "task_id": "task_arch_001",
  "message": "后端可以分为入口层、服务层..."
}

Task 的概念:从一句话到可跟踪工作

这一页围绕 Intent Agent、主 Agent、Sub-agent 和 Task 展示。讲解重点是:不是所有聊天都是 Task,只有需要执行、追踪和反馈的工作才进入 Task mode。

Task 概念图:谁负责什么

用户消息可能是闲聊,也可能是工作请求
Intent Agent只判断路由,不回答问题
Task需要追踪的工作单
主 Agent负责最终答案和整体一致性
Sub-agent只处理被拆出去的局部工作
验收反馈满意、修改或放弃都会更新任务状态
1

用户输入

用户可能只是问一句普通问题,也可能要求系统完成一件事,例如“分析后端架构”“修复测试”“整理技能文档”。

2

Intent Agent 判断意图

MainAgentRouter 只做路由,不回答用户。它判断当前消息是 simple_chatnew_taskcontinue_taskclose_task 还是 abandon_task

3

TaskService 创建或恢复任务

如果要进入 Task mode,TaskService 会创建 TaskRecord,保存目标、状态、run 列表、反馈、验证结果和事件流。

4

主 Agent 负责最终回答

主 Agent 通过 AgentLoop 运行,负责综合上下文、技能、工具结果和 team 输出,最终给用户一个完整答复。

5

Sub-agent 只处理局部工作

复杂任务会先交给任务规划器判断是否拆分。Sub-agent 处理调研、检查、实现片段等局部任务,结果再交回主 Agent 综合。

6

验证和反馈让 Task 闭环

每次 Task run 后会记录 validation。用户点击满意、要求修改或放弃时,会更新 Task 状态,并影响后续学习候选。

TaskRecord 里有什么

  • task_idsession_id、目标和描述。
  • status 表示 open、running、awaiting_feedback、closed 等状态。
  • run_ids 连接每次模型运行。
  • feedbackvalidation_result 记录结果质量。

Task CRUD

  • Create:TaskService.create_task
  • Read:GET /api/tasksGET /api/tasks/{task_id}
  • Update:start run、append run、record validation、add feedback。
  • Delete:DELETE /api/tasks/{task_id}

讲解抓手

  • Intent Agent 是分流员。
  • Task 是工作单。
  • 主 Agent 是总负责人。
  • Sub-agent 是临时分工人员。
  • Validation 和 feedback 是验收记录。

Demo:Task 从创建到等待反馈

这组数据可以用来解释 Task 不是一句回复,而是一张有状态的工作单。

输入

{
  "session_id": "web-demo-001",
  "message": "分析 backend 的 Task 机制,并给我讲解稿"
}

关键数据格式

{
  "router_decision": {
    "action": "new_task",
    "short_title": "Task机制讲解"
  },
  "task": {
    "task_id": "task_001",
    "status": "awaiting_feedback",
    "run_ids": ["run_001"],
    "skill_names": ["backend-reader"]
  },
  "validation_result": {
    "accepted": true,
    "score": 0.91
  }
}

预期输出

{
  "task_id": "task_001",
  "task_status": "awaiting_feedback",
  "answer": "Task 机制可以理解为...",
  "feedback_options": [
    "satisfied",
    "revise",
    "abandon"
  ]
}

自学习:从 Task 反馈到 Skill 生命周期

这一页围绕 Task、Skill、自学习 Skill 的 CRUD 展开。讲解重点是:系统不会自动发布新技能,必须经过候选、草稿、安全检查、评估、审核和发布。

自学习闭环:成功经验如何变成可复用 Skill

Task 成功有结果、验证和用户满意反馈
Learning Candidate系统发现这次经验值得沉淀
Skill Draft生成一个待审核的技能草稿
Safety / Eval安全检查和效果评估
Review人工 approve 或 reject
Publish发布成可选择的新版本 Skill
1

Task 产生证据

每次 Task run 都会写入 run record、激活过的 skill receipt、tool 使用结果、validation 和用户反馈。

2

满意反馈触发候选

当用户反馈 satisfied 且 validation 通过时,SkillLearningService 可以基于这次成功经验生成 learning candidate。

3

候选生成 Draft

POST /api/skills/candidates/{candidate_id}/draft 会合成技能草稿,同时生成 safety report 和 eval report。

4

人工 Review

草稿可 submit、approve 或 reject。高风险内容不能静默发布,发布接口需要显式确认。

5

Publish / Disable / Rollback

通过后进入 published skill;后续可以 disable 或 rollback 到指定版本。Worker 只生成和评估,不自动 approve/publish。

Candidate CRUD

  • List:GET /api/skills/candidates
  • Read:GET /api/skills/candidates/{candidate_id}
  • Create:由满意 Task 反馈或 worker run-once 生成。
  • Update:合成 draft、regenerate draft、写 audit event。

Draft / Review CRUD

  • List:GET /api/skills/drafts
  • Read:draft、safety、eval 三类详情接口。
  • Update:submit、approve、reject。
  • Delete:底层 DraftService.delete_draft 支持删除草稿。

Published Skill CRUD

  • Create:publish 生成新版本。
  • Read:skills list、detail、version、file、download。
  • Update:disable、rollback。
  • Delete:DELETE /api/skills/{name} 删除或归档技能入口。

Demo:一次满意反馈如何变成 Skill 草稿

适合讲“自学习不是自动上线”,它只是生成候选和草稿,后面仍要审核。

输入

POST /api/chat/feedback
{
  "session_id": "web-demo-001",
  "run_id": "run_001",
  "feedback_type": "satisfied",
  "comment": "这次后端讲解结构很好"
}

关键数据格式

{
  "candidate": {
    "candidate_id": "cand_001",
    "status": "candidate",
    "trigger_run_id": "run_001",
    "evidence": ["Task 通过验证", "用户满意"]
  },
  "draft": {
    "draft_id": "draft_001",
    "skill_name": "backend-explainer",
    "status": "draft",
    "proposal_kind": "new_skill"
  }
}

预期输出

{
  "learning_candidate_created": true,
  "draft_created": true,
  "safety_report": "passed",
  "eval_report": "passed",
  "next_step": "submit_review"
}

Skill 和 Tool:如何选技能、选工具,以及 Skill 里的 tool 字段

这一页关注 Skill 选择器、工具选择器,以及 skill 中工具提示字段如何影响工具暴露。

Skill / Tool 选择链路

任务描述本轮要解决的问题
Skill 召回embedding 找到候选 Skill
Skill 精选LLM 选择真正激活的 Skill
tool_hintsSkill 建议常用工具
Tool 选择always tools + hints + embedding top-k
Tool Schema只把选中的工具暴露给模型
1

Skill 选择器先看任务

SkillAssembler 读取所有可选 skill 摘要,用 embedding 召回候选,再让辅助模型从候选中选出本轮真正激活的 skill。

2

激活 Skill 变成上下文

被选中的 skill 会变成 SkillContext,写入 system prompt,并生成 SkillActivationReceipt 方便后续学习和审计。

3

Skill 的 tool_hints 影响工具选择

Skill 版本里有 tool_hints。如果某个 skill 明确提示需要 read_filepatch_file 等工具,工具选择器会优先加入这些工具。

4

工具选择器再补充工具

ToolAssembler 先加入 always tools,再加入 skill hints,再通过 embedding 从 registry 中召回更多相关工具。

5

ToolRegistry 导出 schema

ToolRegistry 不执行工具,只把选中的 ToolSpec 导出成 provider 可消费的 function schema。

6

ToolExecutor 执行调用

模型返回 tool call 后,ToolExecutor 执行工具,并把 tool result 写回 session history,供下一轮模型继续使用。

Skill 中关键字段

  • name:技能唯一名。
  • description:选择器理解技能用途。
  • content:真正注入给 agent 的指导正文。
  • tool_hints:建议本 skill 常用哪些工具。
  • tagsowners:分类和治理信息。

ToolSpec 中关键字段

  • name:模型调用函数名。
  • description:模型理解工具何时可用。
  • input_schema:参数结构。
  • toolset:所属工具集。
  • always_available:是否每轮都暴露。

选择顺序

  • Skill:候选召回 -> LLM shortlist -> LLM final -> 注入上下文。
  • Tool:always tools -> skill tool_hints -> embedding top-k。
  • 最终:只把选中的工具 schema 给模型,减少噪音和误用。

Demo:Skill 选择器和工具选择器如何配合

用一个 Skill 的 frontmatter 解释 tool_hints 为什么会影响本轮可用工具。

输入

{
  "task_description": "阅读 backend 代码并解释 Task 机制"
}

关键数据格式

---
name: backend-explainer
description: Explain backend architecture
tool_hints:
  - search_files
  - read_file
  - session_search
---
先定位入口,再追踪服务层和运行内核。

预期输出

{
  "activated_skills": [
    "backend-explainer"
  ],
  "selected_tools": [
    "memory",
    "session_search",
    "search_files",
    "read_file"
  ],
  "tool_schema_count": 4
}

Memory 和 Session:CRUD、装载与运行时快照

这一页解释会话、记忆和运行记录如何创建、读取、更新、归档,以及 AgentLoop 如何装载它们。

Memory / Session 装载和写回

EngineLoader创建状态组件
Session保存对话消息和事件
Memory Snapshot每次 run 捕获一份快照
AgentLoop用快照组装上下文并执行
Run Memory记录运行证据和 skill effect
Feedback反馈反写到任务和学习数据
1

EngineLoader 装载状态组件

EngineLoader.load 创建 SessionManager、curated MemoryStoreMemoryServiceRunMemoryStoreSkillLearningStore

2

Session 保存对话过程

每次 run 都会确保 session 存在,并追加 system、user、assistant、tool 等消息,同时记录 event payload、usage、run_id 和上下文可见性。

3

MemoryService 捕获快照

AgentLoop 每次运行都会调用 capture_snapshot_for_run。并行 team run 各拿自己的 frozen snapshot,避免互相覆盖。

4

RunMemoryStore 保存运行证据

run record 记录输入、输出、激活 skill、验证、反馈;skill effect 记录某个 skill 在这次 run 中的效果。

5

API 提供 Session CRUD

前端通过 sessions API 创建、查看、归档会话,也可以读取 session process 和 debug chat logs。

Session CRUD

  • Create:POST /api/sessions/{session_id} 或 run 时 ensure_session
  • Read:GET /api/sessionsGET /api/sessions/{session_id}
  • Update:append_messageupdate_usageupdate_system_prompt
  • Delete/Archive:DELETE /api/sessions/{session_id} 或 archive。

Memory / Run CRUD

  • Create:append run record、append skill effect、curated memory item。
  • Read:session search、memory tool、run list、skill effects。
  • Update:validation、feedback、success ratio、performance snapshot。
  • Archive:通过 session end reason 或 skill/version 状态保留历史。

装载顺序

  • 配置解析 workspace。
  • 初始化 curated memory store。
  • 创建 session 和 run stores。
  • 注入 ToolContext services。
  • 运行时按 run 捕获 memory snapshot。

Demo:Session、Message、Memory Snapshot 的关系

适合讲“为什么能继续对话”,以及“为什么并行 sub-agent 不会互相污染记忆”。

输入

POST /api/sessions/web-demo-001

POST /api/chat
{
  "session_id": "web-demo-001",
  "message": "继续解释刚才的 Task"
}

关键数据格式

{
  "session": {
    "id": "web-demo-001",
    "source": "web",
    "message_count": 12
  },
  "message": {
    "role": "user",
    "run_id": "run_002",
    "content": "继续解释刚才的 Task"
  },
  "memory_snapshot": {
    "captured_for_run": "run_002",
    "frozen": true
  }
}

预期输出

{
  "session_loaded": true,
  "history_used": true,
  "run_id": "run_002",
  "assistant_message_saved": true
}

一次用户请求如何流过后端

从 WebSocket/HTTP 进入,到 AgentLoop 选择 skills/tools,最后写回 session 和 run memory。

请求主链:技术视角

HTTP / WS接口收到用户请求
AgentService统一收口 direct / running 模式
Router判断 simple chat 或 Task mode
Planner选择 single 或 team
AgentLoop模型调用和工具循环
Validation记录验证、反馈和学习证据
1

接口接收请求

interfaces/web/app.py 提供 /api/chat/ws/{session_id}、tasks、files、skills、cron 等入口,只做参数转换和响应拼装。

2

AgentService 收口

接口层不直接 new loop,而是调用 AgentService.process_directsubmit_direct,由 service 管理 direct/running mode。

3

Intent Agent 路由

MainAgentRouter 用辅助模型判断 simple chat、继续任务、新建任务、关闭或放弃任务;simple chat 会关闭 skill/tool assembly。

4

Task mode 规划

TaskService 创建或恢复任务,任务规划器决定单 agent 还是 team;team 模式先运行 sub-agent,再交给主 agent synthesis。

5

EngineLoader 装配运行时

统一加载 session manager、memory service、skills loader、tool registry、tool executor、skill learning pipeline、agent registry、MCP manager。

6

AgentLoop 运行主链

捕获 memory snapshot,组装 prompt,选择 skills 和 tools,调用 provider;若返回 tool calls,则执行 tool loop 并把结果追加回上下文。

7

验证、反馈和学习沉淀

Task 结果进入 validation 和 feedback gate;满意反馈会更新 run record、skill effects,并可能生成 assisted learning candidate。

Demo:完整 /api/chat 输入输出

这可以作为接口级例子:用户输入什么,后端可能返回什么。

输入

POST /api/chat
{
  "session_id": "web-demo-001",
  "message": "帮我画出 Task、自学习、Skill 和 Memory 的关系",
  "thinking_enabled": true
}

关键内部事件

[
  {"event_type": "intent_agent_decision", "action": "new_task"},
  {"event_type": "task_execution_planned", "mode": "team"},
  {"event_type": "skill_activation_snapshotted", "skills": ["backend-explainer"]},
  {"event_type": "tool_selection_snapshotted", "tools": ["search_files", "read_file"]},
  {"event_type": "task_validation_snapshotted", "accepted": true}
]

预期输出

{
  "session_id": "web-demo-001",
  "run_id": "run_003",
  "task_id": "task_002",
  "task_status": "awaiting_feedback",
  "message": "可以把这四者理解为..."
}

Agent Team:什么时候拆分、怎么编排、如何回到主 Agent

这一页展示 Agent Team 的完整概念:注册的 agent 能力、Task planner 的 team plan、ExecutionGraph 的三种策略、每个节点的 skill 绑定,以及最终 synthesis。

Agent Team 执行图

Task复杂工作进入任务模式
Team PlanPlanner 生成执行图
Skill Binding为每个节点绑定 Skill 或临时指导
Scheduler按 sequence、parallel 或 DAG 推进
Sub-agents节点回到同一个 AgentLoop 执行
Main Synthesis主 Agent 综合所有节点输出
1

先判断是否值得组队

任务规划器只在独立调研、评审、实现切片、分阶段检查能明显提升结果时选择 team,否则保持 single agent。

2

生成 ExecutionGraph

team plan 会生成 ExecutionGraph,包含 strategy、nodes、node task、depends_on、expected_output 和 skill_query。

3

为节点绑定 Skill

TaskSkillResolver 为每个 node 选择 published skill;如果没有合适 skill,就合成 one-run ephemeral guidance。

4

LocalAgentRunner 执行节点

每个 sub-agent 节点都会通过 LocalAgentRunner 调回同一个 AgentLoop,只是 session_id、source、execution_context 不同。

5

主 Agent 综合输出

Team 的 node outputs 不直接作为最终答案,而是进入主 Agent 的 synthesis context,由主 Agent 负责最终一致性、取舍和用户回答。

Sequence

node Anode Bmain synthesis

上游输出作为下游 dependency output;任一节点失败,后续节点被标记 blocked。

Parallel

node Anode Bnode Csynthesis

适合独立调研、并行检查或拆分实现面;由 asyncio.gather 并发运行。

DAG

researchdesignreview

显式 depends_on 控制依赖,scheduler 按 ready batch 推进并检测循环依赖。

Skill Binding

skill querypublished skill/ephemeral guidance

TaskSkillResolver 优先 pin 已发布 skill;缺失时合成 one-run guidance,不自动发布。

Agent Team CRUD

  • List:GET /api/agentsGET /api/subagents
  • Create:POST /api/agentsPOST /api/subagents
  • Update:PATCH /api/agents/{agent_id}PUT /api/subagents/{agent_id}、disable。
  • Delete:DELETE /api/agents/{agent_id}DELETE /api/subagents/{agent_id}

节点输入里有什么

  • 父 task id 和父 run id。
  • 节点自己的 task 和 expected output。
  • 依赖节点的输出。
  • pinned skills 或 ephemeral guidance。
  • 节点角色、约束和 skill selection context。

失败如何处理

  • Sequence 中前序失败会阻塞后续节点。
  • DAG 中依赖失败会阻塞依赖它的节点。
  • Parallel 节点独立运行,失败会进入 team summary。
  • 主 Agent 会看到失败摘要,再决定如何向用户说明。

Demo:Agent Team 把复杂任务拆成三个节点

这个例子适合讲 sequence、parallel、DAG 之前先让用户理解“节点输出最后还要由主 Agent 综合”。

输入

{
  "task_id": "task_002",
  "user_message": "检查后端架构讲解是否完整,并补上缺口"
}

关键数据格式

{
  "mode": "team",
  "strategy": "dag",
  "nodes": [
    {"node_id": "read", "task": "阅读现有文档", "depends_on": []},
    {"node_id": "check", "task": "检查缺失主题", "depends_on": ["read"]},
    {"node_id": "draft", "task": "补写讲解内容", "depends_on": ["check"]}
  ]
}

预期输出

{
  "team_success": true,
  "node_results": [
    {"node_id": "read", "success": true},
    {"node_id": "check", "success": true},
    {"node_id": "draft", "success": true}
  ],
  "main_synthesis": "已补充 Task、自学习、Skill/Tool、Memory/Session 和 Agent Team 示例。"
}

能力层和状态边界

这些层围绕 AgentLoop 工作,但各自保持独立职责。

Skills

  • SkillsLoader 读取 published skill 和 selection candidates。
  • SkillAssembler 通过 embedding 召回和 LLM 决策激活 skill。
  • draft、review、publisher、learning pipeline 支持候选生成、审核和发布。

Tools

  • ToolRegistry 只负责注册、查找和导出 provider schema。
  • ToolAssembler 结合 always tools、skill hints 和 embedding top-k。
  • ToolExecutor 执行 tool call,结果写入 session history。

Memory

  • 每个 run 捕获自己的 frozen memory snapshot,避免并行 team run 串扰。
  • session manager 保存消息、事件 payload、usage、归档状态。
  • run memory 保存 receipts、validation、feedback、skill effects。

Providers

  • ProviderBundle 分离 main、auxiliary、embedding runtime。
  • router、planner、skill selection 可走 auxiliary provider。
  • 主回答、tool loop 和 synthesis 走 main provider。

Integrations

  • MCP manager 连接外部 MCP server,并把 tools 注册进 registry。
  • Outlook、WhatsApp、A2A、authz 保持在 integrations 边界内。
  • Web API 只暴露集成状态、连接测试和数据读取入口。

Cron

  • CronService 在 FastAPI lifespan 中随 AgentService 启停。
  • notification 生成通知结果,task mode 生成可反馈的 TaskRecord。
  • 用户 engage 后可把定时结果转成继续编辑的任务。

Demo:一次运行会同时用到哪些能力

适合收尾时复盘:一次 Task 运行不是只调用模型,而是多个能力层一起工作。

输入

{
  "task": "生成后端架构讲解页",
  "session_id": "web-demo-001"
}

能力调用

{
  "providers": ["main", "auxiliary", "embedding"],
  "skills": ["backend-explainer"],
  "tools": ["search_files", "read_file", "write_file"],
  "memory": ["session_history", "run_record"],
  "integrations": ["mcp_optional"]
}

预期输出

{
  "artifact": "backend-visualization.html",
  "session_updated": true,
  "run_memory_written": true,
  "skill_effect_recorded": true
}