Beaver Backend 可视化
基于 app-instance/backend 当前代码结构绘制,适合配合讲解使用:先给零基础读者建立概念,再逐页展开 Task、自学习、Skill/Tool、Memory/Session 和 Agent Team。
先把它当成一个“帮用户完成任务的后台工厂”
如果你完全没接触过后端、agent、skills、tools,先看这一页。它不要求你理解代码细节。
整体理解:用户一句话如何变成后台执行
这个后端在做什么
用户在前端发一句话,后端负责判断这句话是不是一个任务、要不要查资料或改文件、需不需要拆给多个小助手处理,最后把结果和过程记录下来。
为什么要分这么多层
因为“接收请求”“决定怎么做”“调用模型”“使用工具”“保存记忆”“学习新技能”是不同职责。分开以后,问题更容易定位,也方便单独替换或测试。
最重要的一句话
所有真正执行 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
}模块分层与依赖方向
这一页只展示大模块位置和依赖方向,适合先建立全局地图。
四层架构:从入口到能力
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 判断意图
MainAgentRouter 只做路由,不回答用户。它判断当前消息是 simple_chat、new_task、continue_task、close_task 还是 abandon_task。
TaskService 创建或恢复任务
如果要进入 Task mode,TaskService 会创建 TaskRecord,保存目标、状态、run 列表、反馈、验证结果和事件流。
主 Agent 负责最终回答
主 Agent 通过 AgentLoop 运行,负责综合上下文、技能、工具结果和 team 输出,最终给用户一个完整答复。
Sub-agent 只处理局部工作
复杂任务会先交给任务规划器判断是否拆分。Sub-agent 处理调研、检查、实现片段等局部任务,结果再交回主 Agent 综合。
验证和反馈让 Task 闭环
每次 Task run 后会记录 validation。用户点击满意、要求修改或放弃时,会更新 Task 状态,并影响后续学习候选。
TaskRecord 里有什么
- task_id、session_id、目标和描述。
- status 表示 open、running、awaiting_feedback、closed 等状态。
- run_ids 连接每次模型运行。
- feedback 和 validation_result 记录结果质量。
Task CRUD
- Create:TaskService.create_task。
- Read:GET /api/tasks、GET /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 产生证据
每次 Task run 都会写入 run record、激活过的 skill receipt、tool 使用结果、validation 和用户反馈。
满意反馈触发候选
当用户反馈 satisfied 且 validation 通过时,SkillLearningService 可以基于这次成功经验生成 learning candidate。
候选生成 Draft
POST /api/skills/candidates/{candidate_id}/draft 会合成技能草稿,同时生成 safety report 和 eval report。
人工 Review
草稿可 submit、approve 或 reject。高风险内容不能静默发布,发布接口需要显式确认。
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 选择器先看任务
SkillAssembler 读取所有可选 skill 摘要,用 embedding 召回候选,再让辅助模型从候选中选出本轮真正激活的 skill。
激活 Skill 变成上下文
被选中的 skill 会变成 SkillContext,写入 system prompt,并生成 SkillActivationReceipt 方便后续学习和审计。
Skill 的 tool_hints 影响工具选择
Skill 版本里有 tool_hints。如果某个 skill 明确提示需要 read_file、patch_file 等工具,工具选择器会优先加入这些工具。
工具选择器再补充工具
ToolAssembler 先加入 always tools,再加入 skill hints,再通过 embedding 从 registry 中召回更多相关工具。
ToolRegistry 导出 schema
ToolRegistry 不执行工具,只把选中的 ToolSpec 导出成 provider 可消费的 function schema。
ToolExecutor 执行调用
模型返回 tool call 后,ToolExecutor 执行工具,并把 tool result 写回 session history,供下一轮模型继续使用。
Skill 中关键字段
- name:技能唯一名。
- description:选择器理解技能用途。
- content:真正注入给 agent 的指导正文。
- tool_hints:建议本 skill 常用哪些工具。
- tags、owners:分类和治理信息。
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 装载状态组件
EngineLoader.load 创建 SessionManager、curated MemoryStore、MemoryService、RunMemoryStore 和 SkillLearningStore。
Session 保存对话过程
每次 run 都会确保 session 存在,并追加 system、user、assistant、tool 等消息,同时记录 event payload、usage、run_id 和上下文可见性。
MemoryService 捕获快照
AgentLoop 每次运行都会调用 capture_snapshot_for_run。并行 team run 各拿自己的 frozen snapshot,避免互相覆盖。
RunMemoryStore 保存运行证据
run record 记录输入、输出、激活 skill、验证、反馈;skill effect 记录某个 skill 在这次 run 中的效果。
API 提供 Session CRUD
前端通过 sessions API 创建、查看、归档会话,也可以读取 session process 和 debug chat logs。
Session CRUD
- Create:POST /api/sessions/{session_id} 或 run 时 ensure_session。
- Read:GET /api/sessions、GET /api/sessions/{session_id}。
- Update:append_message、update_usage、update_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。
请求主链:技术视角
接口接收请求
interfaces/web/app.py 提供 /api/chat、/ws/{session_id}、tasks、files、skills、cron 等入口,只做参数转换和响应拼装。
AgentService 收口
接口层不直接 new loop,而是调用 AgentService.process_direct 或 submit_direct,由 service 管理 direct/running mode。
Intent Agent 路由
MainAgentRouter 用辅助模型判断 simple chat、继续任务、新建任务、关闭或放弃任务;simple chat 会关闭 skill/tool assembly。
Task mode 规划
TaskService 创建或恢复任务,任务规划器决定单 agent 还是 team;team 模式先运行 sub-agent,再交给主 agent synthesis。
EngineLoader 装配运行时
统一加载 session manager、memory service、skills loader、tool registry、tool executor、skill learning pipeline、agent registry、MCP manager。
AgentLoop 运行主链
捕获 memory snapshot,组装 prompt,选择 skills 和 tools,调用 provider;若返回 tool calls,则执行 tool loop 并把结果追加回上下文。
验证、反馈和学习沉淀
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 执行图
先判断是否值得组队
任务规划器只在独立调研、评审、实现切片、分阶段检查能明显提升结果时选择 team,否则保持 single agent。
生成 ExecutionGraph
team plan 会生成 ExecutionGraph,包含 strategy、nodes、node task、depends_on、expected_output 和 skill_query。
为节点绑定 Skill
TaskSkillResolver 为每个 node 选择 published skill;如果没有合适 skill,就合成 one-run ephemeral guidance。
LocalAgentRunner 执行节点
每个 sub-agent 节点都会通过 LocalAgentRunner 调回同一个 AgentLoop,只是 session_id、source、execution_context 不同。
主 Agent 综合输出
Team 的 node outputs 不直接作为最终答案,而是进入主 Agent 的 synthesis context,由主 Agent 负责最终一致性、取舍和用户回答。
Sequence
上游输出作为下游 dependency output;任一节点失败,后续节点被标记 blocked。
Parallel
适合独立调研、并行检查或拆分实现面;由 asyncio.gather 并发运行。
DAG
显式 depends_on 控制依赖,scheduler 按 ready batch 推进并检测循环依赖。
Skill Binding
TaskSkillResolver 优先 pin 已发布 skill;缺失时合成 one-run guidance,不自动发布。
Agent Team CRUD
- List:GET /api/agents、GET /api/subagents。
- Create:POST /api/agents、POST /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
}