Files
YunShu/docs/会议室架构计划书.md
titor 0898188086 docs: 会议室架构规划 + MSN hourlyforecast 端点更新
- 新增 docs/会议室架构计划书.md 完整架构方案(主持者+子Agent+task+cache+记忆)
- 更新 taolun.md 追加 2026-05-11 讨论历史
- 更新 AGENTS.md 规范(type, cache 字段)
- 更新 architecture.md 后续演进章节
- 更新 changelog.md 架构规划里程碑
- 修复 MSN 天气接口文档:新增 hourlyforecast,标记 weathertrends 已失效
- 更新 skills/msn-weather-api/SKILL.md 新增 hourlyforecast 端点
- 更新 agents/weather-agent.md 支持逐小时查询
2026-05-11 08:32:30 +08:00

13 KiB
Raw Blame History

云枢·Agent 会议室架构计划书

生成日期2026-05-11 目的:从单 Agent 架构升级为"会议室模式"1 主持 + N 领域专家 + 共享黑板) 最终目标:在云枢上验证通过后,移植到 HxClaw河虾 Claw


一、架构总览

        用户
          │
   ┌──────▼──────────────────────────────────────┐
   │  主持者dialog-agenttype: main            │
   │  人格 + 调度规则 + task + memory 工具        │
   │  唯一入口,用户只和它对话                     │
   └──────┬───────────────────────────────────────┘
          │ task("weather", {city: "北京"})
          │ task("earthquake", {region: "通州"})
          │ task("memory", {action: "read", ...})
          ▼
   ┌───────────────────────────────────────────┐
   │  发言人(领域子 Agenttype: sub             │
   │  weather / earthquake / memory / narrator   │
   │  被调才说话,返回文本 + 可选缓存数据          │
   │  各自的 cache / skills / tools 互相隔离      │
   └───────────────────────────────────────────┘
          │ 读写
          ▼
   ┌───────────────────────────────────────────┐
   │  记录者(记忆系统)                          │
   │  共享黑板:用户画像、偏好、异常记录            │
   │  memory Agent 负责从对话中提取有价值信息       │
   │  所有 Agent 只读,仅 memory Agent 写入        │
   └───────────────────────────────────────────┘

二、角色定义

2.1 主持者dialog-agenttype: main

职责

  • 用户的唯一入口
  • 有血有肉的个人助理,能闲聊
  • 识别用户意图,调度对应的子 Agent
  • 读/写记忆(用户画像、上下文摘要)

工具列表

  • task — 调度子 Agent
  • memory.read — 读长期记忆
  • memory.write — 写长期记忆

System Prompt 包含

  • 人格(从 memory.personality 加载)
  • 调度规则(何时调哪个子 Agent
  • 不含任何领域知识

System Prompt 不包含

  • 天气知识、地震知识等
  • http-getgeocode 等具体工具

Session

  • session.json 只存 user ↔ dialog 的对话轮次
  • 子 Agent 内部的 tool_calls 不写入

2.2 发言人weather-subtype: sub

职责

  • 响应天气查询
  • task 调才执行,不直接面对用户
  • 返回显示文本 + 可选缓存数据

工具列表http-get, geocode, skill

Frontmatter

name: weather
type: sub
description: 天气查询专家
cache:
  ttl: 7200
  keys: ["city", "forecast_type"]
tools:
  - http-get
  - geocode
  - skill

2.3 发言人earthquake-subtype: sub预留

职责:响应地震信息查询

Frontmatter

name: earthquake
type: sub
description: 地震信息查询
cache:
  ttl: 300
  keys: ["region", "time_range"]
tools:
  - http-get
  - skill

2.4 记录者memory-subtype: sub

职责

  • 阅读对话历史,提取用户画像
  • 把有价值的信息写入长期记忆数据库
  • 响应其他 Agent 的记忆查询
  • 记录子 Agent 的异常(如 API 失效)

工具列表memory.read, memory.write, read-file, write-file

Frontmatter

name: memory
type: sub
description: 记忆管理员
tools:
  - memory.read
  - memory.write
  - read-file
  - write-file

2.5 汇报员narrator-subtype: sub成熟期

职责:把结构化数据翻译成个性化回答

name: narrator
type: sub
description: 个性化回答生成器
tools:
  - memory.read

三、核心工具task

3.1 职责

task(agent_name, arguments)
  │
  ├── 1. 加载 {agent_name}-sub.md Frontmatter
  │       ├── name, type, tools, cache
  │       ├── cache.keys → ["city", "forecast_type"]
  │       └── cache.ttl  → 7200
  │
  ├── 2. 拼缓存 key
  │       ├── 遍历 cache.keys → 从 arguments 提取值
  │       ├── 拼接 → "city=北京&forecast_type=today"
  │       └── hash   → "a1b2c3d4e5f6"
  │
  ├── 3. 读缓存文件 ~/.config/yunshu/cache/{agent_name}.json
  │       ├── HIT  → cache_data = {temp: 25, ...}
  │       └── MISS → cache_data = null
  │
  ├── 4. 调子 Agent LLM
  │       ├── system = {agent_name}-sub.md 内容
  │       ├── user = {
  │       │     "args": arguments,
  │       │     "cache_data": cache_data  // 有缓存传数据,没有传 null
  │       │   }
  │       └── 子 Agent 返回文本 + 可选 ---CACHE--- + JSON
  │
  ├── 5. 处理子 Agent 返回
  │       ├── 有 ---CACHE--- → 提取后面的 JSON → 写缓存
  │       └── 无 ---CACHE--- → 只传文本
  │
  └── 6. 返回显示文本给 Hostdialog Agent 的 LLM

3.2 缓存文件格式

// ~/.config/yunshu/cache/{agent_name}.json
{
  "<hash>": {
    "created_at": "2026-05-11T06:00:00+08:00",
    "ttl": 7200,
    "data": {
      "temp": 25,
      "condition": "晴"
    },
    "raw": {
      "city": "北京",
      "forecast_type": "today"
    }
  }
}
  • hash 由 cache.keysarguments 中提取值 → 拼接 → SHA256 取前 12 位
  • raw 存原始参数,方便调试和遍历
  • 每次读缓存时惰性清理过期条目

3.3 传给子 Agent 的参数

{
  "args": {
    "city": "北京",
    "forecast_type": "today",
    "units": "C"
  },
  "cache_data": {
    "temp": 25,
    "condition": "晴"
  }
}
  • args 是 dialog 传过来的原始参数
  • cache_data 是缓存的数据(有缓存时),子 Agent 据此直接回答,省一次 API 调用
  • 两者都是原始数据,不是处理过的文本

四、记忆系统

4.1 存储位置

~/.config/yunshu/memory.db  (或 memory.jsonMVP 阶段)

4.2 数据模型

{
  "personality": "你是个幽默风趣的北京大妞,说话带点贫",
  "user_profile": {
    "location": "北京通州",
    "unit": "C",
    "allergies": ["花粉"],
    "interests": ["户外"],
    "mood_today": null
  },
  "agent_errors": {
    "weather": ["msn_api_500 at 2026-05-11T06:00:00"],
    "earthquake": []
  },
  "dialog_context": {
    "last_agent": "weather",
    "last_topic": "北京天气",
    "summary": "用户问了北京天气"
  }
}

4.3 读写规则

操作 谁做 时机
memory.read dialog / 子 Agent 需要画像时
memory.write 只有 memory Agent 从对话中提取画像后
memory.write("dialog_context") dialog 每次回答后

4.4 memory Agent 的工作流

用户: "我住北京通州,最近花粉过敏厉害"
  → dialog 聊天回应
  → dialog: task("memory", {action: "extract", text: "用户说住通州、花粉过敏"})
  → memory: 提取 → memory.write("user_profile.location", "北京通州")
                       memory.write("user_profile.allergies", ["花粉"])

用户: "今天天气怎么样?"
  → dialog: task("memory", {action: "read_context"}) → 有 location
  → dialog: task("weather", {city: "北京通州"})

五、文件结构

yunshu/
├── main.go                     # CLI 入口
├── types.go                    # 核心类型AgentDef, ToolDef 等)
├── loader.go                   # .md 解析Frontmatter + Body
├── registry.go                 # Agent 注册中心(扫描 + 按 type 分类)
├── llm.go                      # LLM API 封装
├── tool.go                     # 工具注册表 + ExecuteTool
├── runtime.go                  # RunAgent 主循环
│
├── agents/
│   ├── dialog-agent.md         # type: main — 主持者
│   ├── weather-sub.md          # type: sub — 天气
│   ├── earthquake-sub.md       # type: sub — 地震(预留)
│   ├── memory-sub.md           # type: sub — 记忆管理员
│   └── narrator-sub.md         # type: sub — 汇报员(成熟期)
│
├── skills/
│   ├── msn-weather-api/SKILL.md
│   └── geocoding/SKILL.md
│
├── docs/
│   ├── taolun.md
│   ├── 会议室架构计划书.md
│   ├── changelog.md
│   ├── architecture.md
│   └── AGENTS.md
│
└── pkg/
    ├── mdprint/
    ├── style/
    └── termui/

用户配置目录

~/.config/yunshu/
├── config.yaml                  # LLM 配置
├── session.json                 # 对话历史(仅 user ↔ dialog
├── agents/
│   ├── dialog-agent.md          # 用户可覆盖对话 Agent
│   └── weather-sub.md           # 用户可覆盖天气子 Agent
├── skills/                      # 用户可扩展知识
├── cache/
│   ├── weather.json
│   ├── earthquake.json
│   └── ...
├── data/
│   └── weather/                 # 子 Agent 自己的数据目录
└── memory.db                    # 长期记忆数据库

六、调用流程示例

用户: "北京明天多少度?"

  HOSTruntime.go:
    1. 加载 dialog-agent.md → system prompt
    2. 读 session.json → 恢复上下文
    3. 调 LLMsession + system + tools
    4. LLM 返回 tool_call: task("weather", {city: "北京", forecast_type: "tomorrow"})

  task 工具:
    1. 加载 weather-sub.md Frontmatter
       → cache.keys: ["city", "forecast_type"], ttl: 7200
    2. 拼 key → "city=北京&forecast_type=tomorrow" → hash
    3. 查 weather.json → MISS首次查明天
    4. 调子 Agent LLM:
       system = weather-sub.md
       user = {args: {city: "北京", forecast_type: "tomorrow"}, cache_data: null}
    5. 子 Agent:
       ├── geocode("北京") → (39.9, 116.4)
       ├── skill("msn-weather-api") → 接口参数
       ├── http-get(URL) → JSON
       └── 返回: "北京明天 18-31°C晴"
                  ---CACHE---
                  {temp_lo: 18, temp_hi: 31, condition: "晴"}
    6. task 提取 CACHE → 写 weather.json
    7. 返回 "北京明天 18-31°C晴" 给 dialog

  HOSTruntime.go:
    1. tool 返回 → LLM 继续
    2. LLM 生成最终回答:
       "北京明天 18到31度大晴天适合出去浪"
    3. dialog: task("memory", {action: "update_context", agent: "weather", city: "北京"})
    4. 追加 session.json
    5. 输出给用户

七、实施阶段

阶段一:基础架构(当前 → 1周

任务 说明
1.1 Frontmatter 扩展 解析 type: main|subcache 字段
1.2 Agent 注册中心 registry.go 扫描 agents/~/.config/yunshu/agents/,按 type 分类
1.3 task 工具 实现子 Agent 加载、LLM 调用、缓存读写
1.4 Cache 系统 cache/ 目录管理、JSON 文件读写、过期清理
1.5 memory.read/write 工具 简单的 JSON 文件读写
1.6 dialog-agent.md 重写为主持者(极薄:人格 + 调度规则)
1.7 weather-sub.md 从旧 weather-agent.md 改造

阶段二:记忆系统(阶段一完成后)

任务 说明
2.1 memory-sub.md 记忆管理员 Agent从对话提取画像
2.2 记忆数据库 结构化存储(画像、偏好、异常记录)
2.3 画像自动提取 memory Agent 定期从对话中提取有用信息

阶段三:扩展(可选)

任务 说明
3.1 earthquake-sub 地震信息查询
3.2 narrator-sub 个性化回答生成
3.3 更多数据源 台风、核电、火山...

八、与 PicoClaw 的对比

维度 PicoClaw 云枢·会议室模式
入口 单 Agent用户直接对话 对话 Agent唯一入口+ 背后一堆子 Agent
上下文 所有轮次 + 系统 prompt 混在一起 session 只存 user↔dialog子 Agent 用完即毁
知识 预置或长 prompt skill 按需加载
工具 所有工具混着用 按角色过滤dialog 只有 task + memory
记忆 共享黑板memory Agent 管写入
扩展 改代码或改 prompt 加一个 .md 文件
失败隔离 坏 tool_call 可能污染全部 子 Agent 独立,坏就坏一个
用户自定义 不可能 ~/.config/yunshu/agents/ 放 .md 即可

九、设计原则

  1. 主持者保持极薄 — 只有人格 + 调度规则,不做领域知识
  2. 子 Agent 不自知 — 不知道缓存存在、不管理自己的 session只回答当前问题
  3. 机械化的不做 LLM — 缓存 key 拼装、文件读写都是 Go 代码LLM 不参与
  4. 数据隔离 — 子 Agent 的 cache 文件、data 目录互相独立
  5. 记忆共享 — 黑板机制,所有 Agent 可读,仅 memory Agent 可写
  6. 一个入口 — 用户永远只和 dialog-agent 对话,感受不到子 Agent 的存在