Files
sanguo_moziplus_v2/docs/design/architecture-v2.6.md
T
2026-05-18 23:01:31 +08:00

106 KiB
Raw Blame History

AI原生DevOps Platform 架构设计 v2.6

版本: v2.6(Shared Workspace + Blackboard 架构) 基于: architecture-v2.md + v2.0 AI Native 调研 + 技术验证 作者: 庞统(副军师) 日期: 2026-05-15


变更历史

版本 日期 变更内容
v2.0 2026-05-04 初始版本:SQLite 4表 + 状态机 + DAG 引擎
v2.6 2026-05-15 架构重构:Shared Workspace(Blackboard)取代 DAG 引擎为编排核心
v2.6.1 2026-05-15 司马懿评审反馈 + Mail 退役决策 + 质量门控 + 决策记录 + 工程修正
v2.6.2 2026-05-15 课题1设计决策:三层执行模型、续杯机制、AI驱动retry、Guardrail体系、must_haves三件套、分级审查矩阵
v2.6.2.1 2026-05-15 司马懿评审反馈:L2/L3区分标准、timeout修正、outputs关联attempt、Scope Guard异步、risk_level自动
v2.6.3 2026-05-15 课题2设计决策:Tick核心+Inbox JSONL加速、Handoff Comment无缝接手、L1/L2/L3对应Opal-Bridge Fidelity、黑板AI Native内容规范+三层约束体系(Schema校验+Skill引导+L1截取)、依赖驱动并行/串行、Phase规划更新
v2.6.4 2026-05-15 课题3设计决策:分级审查流水线(四级风险→三/二/一阶段)、审查协议注册表(Review Protocol Registry)、反驳权(Rebuttal Phase)、reviews表结构化存储、声明式guardrails.yaml、Full Agent vs Subagent vs Daemon直接执行判据、对抗辩论模式
v2.6.5 2026-05-15 课题4设计决策:模板组件库(+custom)替代固定DAG、四层上下文架构(L0铁律/L1角色/L2引擎注入三段式/L3被动参考)、prompt_templates按角色拼装、L2按角色精确注入不多不少、L3 Skill description四要素优化写法
v2.6.6 2026-05-15 课题7+9设计决策:四种交互模式(沉浸观察/轻触确认/即时对话/被动通知)、推送级别分级(🔴🟡🟢🔵)、三层信息架构(L1一眼/L2看板/L3详情)、5页Dashboard(任务看板/全局监控/产出档案/系统配置/AI Briefing)
v2.6.7 2026-05-15 课题6设计决策:经验三种载体(Memory→Skill→Rule)、两级蒸馏(实时一级+周期二级)、验证(格式+内容+实用性)、四层架构反哺(Daemon注入+被动参考)、experiences表、Skill生命周期(draft→active→deprecated)
v2.6.8 2026-05-16 课题10结论:不需要复杂压缩/摘要、续杯问题已由课题2+4解决、单黑板单Daemon多任务并行、Context预算35-60K远小于128K、用户级多项目待课题11解决
v2.6.9 2026-05-16 7项目调研结论纳入:Guardrail验证脚本层(Aider)、对抗性审计映射(claude-goal→L1/L2/L3)、防偏离三防线+Runaway Guard、双重Hook(OpenClaw+moziplus)、Shadow Checkpoint(Cline)、潜在课题(模型策略/信任分级/Worktree隔离)、Blackboard Map按需触发
v2.6.9.1 2026-05-16 司马懿评审回应:PRD目标不改+架构记录差距、blocked状态保留+设计完整、verification_commands安全模型明确(exec approvals)、Daemon逻辑健康自检纳入§14
v2.6.10 2026-05-16 课题11多项目:方案C单Daemon多数据库 + per-project线程并发 + ActiveAgentCounter异步计数器 + session命名规则(sequential复用/parallel独立) + 三层资源控制 + 项目归档/删除安全流程
v2.6.11 2026-05-16 课题7+9方案完成:v1.0已有11个Tab全部保留(仅任务看板重设计)、Checkpoint三种交互、推送SSE+降级轮询、AI Briefing日报/周报、项目切换器、推送通知中心
v2.6.12 2026-05-16 全量遗留清理(51项→0) + 课题3四项新方案(对抗辩论/评审Schema/反驳权/调度判据) + 司马懿评审通过(comments表comment_type) + 工具链课题初始化 + 技术架构/部署架构重写(v2.6.2)
v2.8 2026-05-18 v2.8 状态增强:新增 paused/escalated/waiting_human 3状态(共11个)+ 归档机制 + M3 Checkpoint/Artifact + 前端两行筛选栏 + 卡片快捷按钮

课题 1-2 遗留 TODO(需后续课题解决)

# 待解决事项 归属课题 说明
T1-1 spawn sub 是否阻塞?需要调查 课题 2 课题 2 解决:不阻塞,signal file 异步
T1-2 事件驱动取代 polling tick 课题 2 课题 2 解决:双层事件架构
T1-3 依赖推进(done→自动解锁下游) 课题 2 课题 2 解决:task_completed 事件即时解锁
T2-1 files_modified 冲突检测 课题 2 D2-4 决策:不做,Agent 评论自然协调
T2-2 Auto-compact 课题 2 D2-6 决策:不做,隔离 session 天然无 context rot
T1-4 Agent 间自主协商机制 课题 3 课题3解决:审查协议+反驳权+评论协商
T1-5 Scope Guard 的 Skill 定义 课题 4 课题4解决:executor.md 步骤2(scope_declaration)
T1-6 truths 验证的具体实现 课题 4 课题4解决:executor.md 步骤1+Plan Checker(plan_check.yaml)
T1-7 outputs attempt_number 过滤规则 课题 4 课题4解决:executor.md 步骤4(output提交)+Daemon build_bootstrap()
T1-8 状态机细化(review 轮次、sub_status) 课题 3 课题3解决:§9.7状态机对齐
T2-3 blackboard.py 写操作自动写 inbox JSONL Phase 1 开发实现
T2-4 Tick Loop + Inbox JSONL Watcher Phase 1 开发实现
T2-5 L2/L3 分层读取 API Phase 2 开发实现
T2-6 仓库级上下文(Agent Context Pack Phase 3 P3 保留,不合并不关闭
T2-7 Handoff Comment 的 Skill 引导 Phase 2 课题4解决:executor.md 步骤5写死
T2-8 Handoff Comment 的 Skill 解析规则 课题 4 课题4解决:executor.md "前序信息"部分+schemas/handoff.schema.json

课题 4 Skill 体系设计 TODO

课题4设计决策:关键操作不靠 Skill 被动触发,走引擎注入(L2 prompt_templates)。以下 28 项全部通过 prompt_templates/ + review_protocols/ + schemas/ 覆盖。此表保留作为设计推导留痕。

覆盖映射

  • S-01~S-12(执行者操作)→ prompt_templates/executor.md
  • S-13~S-20(审查者操作)→ prompt_templates/reviewer.md + review_protocols/*.yaml
  • S-21~S-27(庞统操作)→ prompt_templates/planner.md / adjudicator.md
  • S-28L1 消息构建)→ Daemon build_bootstrap() 代码

详见课题4方案:docs/design/topic4-decomposition-skill-proposal.md D4-6/D4-7

# Skill 内容 适用角色 Phase 来源 覆盖方式
S-01 blackboard.py CLI 使用手册 所有 Agent P1 课题1 §5.2 executor.md 各步骤中写死
S-02 L1→L2/L3 按需读取判断 所有 Agent P2 课题2 §4.4 executor.md "可选参考"部分
S-03 写 Handoff Comment(格式+时机) 所有 Agent P1 课题2 §5.1 executor.md 步骤5
S-04 读 Handoff Comment(利用上一个 Agent 交接) 所有 Agent P2 课题2 §5.1 executor.md "前序信息"部分
S-05 写 observation(时机+severity 格式) 所有 Agent P2 课题1 §4.7 executor.md 步骤3
S-06 写 decision(时机+rationale 格式) 所有 Agent P2 课题1 §9.4 executor.md 步骤2
S-07 写 output 的 Schema 约束 所有 Agent P1 课题2 §3.7 executor.md 步骤4 + schemas/
S-08 Guardrail 打回时的处理流程 执行者 P2 课题3 §9.3 executor.md + guardrails.yaml
S-09 @mention 使用规范 所有 Agent P2 课题1 §5.2 executor.md 步骤3
S-10 claim 后写 scope_declaration(格式+内容) 执行者 P1 课题1 §4.7 executor.md 步骤2(含JSON格式)
S-11 must_haves 三件套自检(truths/artifacts/constraints 执行者 P1 课题1 §9 executor.md 步骤1
S-12 收到 review needs_revision 的反驳流程(ACCEPT/REJECT/PARTIAL 执行者 P2 课题3 §9.5 rebuttal.md
S-13 审查者 Investigation Protocol 五阶段执行 审查者 P2 课题3 §9.4 reviewer.md 五步骤
S-14 多视角审查方法(代码/方案/分析三套视角集) 审查者 P2 课题3 §9.4 reviewer.md + review_protocols/
S-15 写 review 的 Schema 约束(verdict+evidence 审查者 P2 课题3 §9.6 reviewer.md + schemas/
S-16 信心度自评(confidence 打分标准) 审查者 P2 课题3 §9.6 reviewer.md 步骤5(自审)
S-17 收到反驳(REJECT)后的评估方法 审查者 P2 课题3 §9.5 reviewer.md(反方回应处理)
S-18 plan_review 协议(假设提取/pre-mortem/依赖审计) 审查者 P2 课题3 §9.4 review_protocols/plan_review.yaml
S-19 output_review 协议(需求追踪/缺口分析) 审查者 P2 课题3 §9.4 review_protocols/output_review.yaml
S-20 analysis_review 协议(逻辑跳跃/数据来源) 审查者 P2 课题3 §9.4 review_protocols/analysis_review.yaml
S-21 创建任务(truths/artifacts/constraints 定义) 庞统 P1 课题1 §9 planner.md
S-22 风险等级自动判断(task_type→risk_level 庞统 P1 课题3 §9.2 planner.md(映射规则)
S-23 挑战者选择(按任务类型选挑战者) 庞统 P2 课题3 §9.10 planner.md(选择表)
S-24 对抗辩论裁决方法 庞统 P3 课题3 §9.10 adjudicator.md
S-25 escalated 任务的用户沟通 庞统 P3 课题3 §9.7 planner.md / adjudicator.md
S-26 confidence 低时的升级判断 庞统 P2 课题3 T3-5 reviewer.md< 0.7 升级庞统)
S-27 任务拆解方法(依赖声明/子任务创建) 庞统 P2 课题1 §5.1 planner.md(四步+组件库+PlanChecker
S-28 L1 消息构建逻辑 庞统/Daemon P1 课题2 §4.4 Daemon build_bootstrap() 代码
T2-9 inbox 并发写入的竞态处理 Phase 1 验证 已解决:truncate(清空不删除)替代 unlink(删除),实测 200 次并发写入 0 丢失。演进方向:向 webhook 实时化走
T2-10 inbox 文件的 rotate/truncate 策略 Phase 2 关闭:Inbox 每秒被清空,正常运行不膨胀。Daemon 崩溃积压也仅 ~200KB/1000条
T2-11 Tick 频率 30s vs 60s 的性能验证 开发后实测 开发后实测
T2-12 CLI Schema 校验的 schemas/ 目录定义 Phase 1 开发实现

课题 3 遗留 TODO

# 待解决事项 归属 说明
T3-1 reviews 表的 CLI 命令 Phase 2 方案已定,开发实现
T3-2 Guardrail YAML 解析 + 执行引擎 Phase 2 方案已定,开发实现
T3-3 对抗辩论模式的具体黑板协议 Phase 3 方案已定(topic3 §5.1),仅用户明确要求时启用
T3-4 挑战者池的选择策略 Phase 2 方案已定,开发实现
T3-5 confidence 低于阈值自动升级 Phase 2 方案已定,开发实现
T3-6 评审详情文件的 Schema 定义 Phase 2 方案已定(topic3 §5.2),待司马懿评审确认
T3-7 low 风险任务 Guardrail 自动通过 Phase 2 方案已定,开发实现
T3-8 Review Protocol 模板文件编写 Phase 2 方案已定,开发实现
T3-9 反驳权 Daemon 流控 Phase 2 方案已定(topic3 §5.3),轮次上限兜底不设超时
T3-10 Agent 调度判据 Phase 2 方案已定(topic3 §5.4),配置表驱动非 AI 判断

1. v2.6 核心变革:从 DAG 状态机到 Shared Workspace

1.1 为什么变?

v2.0 的核心是 DAG 引擎 + 状态机 + 邮件通信,本质是给 AI 团队做了一套 ERP:

  • 编排是确定性状态机(固定流程)
  • 交互是点按钮(Dashboard)
  • Agent 间靠邮件异步通信(信息分散在 mail 目录)
  • 人的参与密度不变(全程驾驶)

v2.6 的核心是 Shared Workspace(Blackboard)+ Agent 自主决策 + Daemon 投递:

  • 编排是 AI agent 在黑板上自主领活(动态协作)
  • 交互是自然语言对话
  • Agent 间通过黑板共享一切(信息集中在任务空间)
  • 人只做方向决策和验收

1.2 核心原则

黑板是唯一真相源,所有 agent 读它、想、行动,写回结果。Daemon 是投递员,不是决策者。

  1. Agent 决策,Daemon 执行 - 庞统做 plan、张飞领任务、关羽发现风险,都写在黑板上。Daemon 读黑板,执行 spawn/通知。
  2. 产出在黑板,不在邮件 - 所有任务产出、讨论、观察都在任务的黑板空间里,Sanguo Mail 不介入任务协作。
  3. Daemon 不阻塞 Agent - Daemon 是常驻管家,定期 tick 检查黑板,spawn agent 执行,不占用任何 agent 的主 session。
  4. Session 用完即清 - Agent 通过 openclaw agent --agent <id> --session-id <uuid> spawn 隔离 session,执行完 daemon 存档 jsonl 并清理 sessions.json。
  5. 双入口,对等地位 - Agent 对话和 Dashboard 是两个对等入口,共享同一套黑板数据。Dashboard 是 AI Native 的可视化入口,不是降级的监控面板。

2. 架构总览

┌─────────────────────────────────────────────────────────────┐
│                      用户 / 触发器                            │
│                   (Web / CLI / Cron)                         │
└──────────────────────────┬──────────────────────────────────┘
                           │ 写入黑板或触发 daemon
┌──────────────────────────▼──────────────────────────────────┐
│                    Shared Workspace(黑板)                    │
│                                                               │
│  ┌────────────────────────────────────────────────────────┐  │
│  │              SQLite (blackboard.db)                     │  │
│  │  tasks / comments / outputs / agents / events          │  │
│  │  原子读写(propose→validate→commit 或 SQLite 事务)     │  │
│  └────────────────────────────────────────────────────────┘  │
│                                                               │
│  ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐       │
│  │ 任务列表  │ │ 评论线程  │ │ 产出空间  │ │ 讨论区域  │       │
│  └──────────┘ └──────────┘ └──────────┘ └──────────┘       │
└──────────────────────────┬──────────────────────────────────┘
                           │ daemon tick 读写
┌──────────────────────────▼──────────────────────────────────┐
│                    Daemon(管家)                              │
│                                                               │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────────┐  │
│  │ Tick 循环    │  │ Session 管理  │  │ 健康检查          │  │
│  │ (60s 轮询)   │  │ spawn/archive │  │ zombie/reclaim   │  │
│  │ 读黑板→决策  │  │ /cleanup      │  │ /stale 任务      │  │
│  └──────┬───────┘  └──────┬───────┘  └──────────────────┘  │
│         │                 │                                   │
│  Daemon 只做三件事:       │                                   │
│  1. 读黑板,发现需要介入的  │                                   │
│  2. Spawn 对应 agent       │                                   │
│  3. 清理完成的 session     │                                   │
└──────────────────────────┬──────────────────────────────────┘
                           │ openclaw agent --agent <id> --session-id <uuid>
                           │ 执行完 → 存档 jsonl → 清理 sessions.json
┌──────────────────────────▼──────────────────────────────────┐
│                   Agent 层(将军们)                          │
│                                                               │
│  Agent 不常驻。被 spawn 时:                                   │
│  1. 读黑板 → 了解全局状态                                     │
│  2. 想和做 → 根据职责自主决策                                  │
│  3. 写回黑板 → 产出、评论、领任务                              │
│  4. 退出 → session 被 daemon 清理                             │
│                                                               │
│  ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐    │
│  │庞统  │ │司马懿│ │姜维  │ │关羽  │ │张飞  │ │赵云  │    │
│  │策划  │ │质量  │ │平台  │ │风控  │ │编码  │ │数据  │    │
│  └──────┘ └──────┘ └──────┘ └──────┘ └──────┘ └──────┘    │
│                                                               │
│  每个 Agent: SOUL.md + IDENTITY.md + Skills + Workspace      │
│  Agent 主 session 不参与任务执行(不被污染)                     │
└─────────────────────────────────────────────────────────────┘

关键区别:v2.0 vs v2.6

维度 v2.0 v2.6
编排核心 DAG 引擎 + 状态机 Blackboard(Shared Workspace)
决策者 Daemon(状态机驱动) Agent(在黑板上自主决策)
Daemon 角色 调度器(决定谁干什么) 投递员(执行黑板上的决策)
Agent 通信 Sanguo Mail(异步邮件) 黑板 Comment 线程(共享空间)
信息位置 分散(mail + task目录 + session) 集中(黑板 SQLite)
Agent 生命周期 固定节点执行 Spawn 隔离 session,用完即清
通知机制 Mail 轮询 Daemon tick + spawn
协作模式 指令式(庞统分配→将军执行) 自主式(看黑板→领活→写回)

3. Shared Workspace(黑板)设计

3.1 参考系统对比

系统 存储 原子性 讨论 状态机 发现
Claude Code Agent Teams JSON 文件 无(last-write-wins) inbox 点对点 pending/in_progress/completed Agent 轮询
Hermes Kanban v0.13 SQLite SQLite 事务 Comment 线程 7 状态完整机 Dispatcher 60s tick
Network-AI Markdown 文件 flock 三阶段提交 signal key Agent 主动读
agent-blackboard SQLite + Ontology SQLite 事务 本体条目 Coordinator 分发
我们的方案 SQLite SQLite 事务 Comment 线程 简化状态机 Daemon tick

3.2 SQLite Schema

-- ===== 任务表 =====
CREATE TABLE IF NOT EXISTS tasks (
    id TEXT PRIMARY KEY,                    -- task-001
    title TEXT NOT NULL,
    description TEXT,
    status TEXT NOT NULL DEFAULT 'pending',
    CHECK (status IN ('pending','claimed','working','review','done','failed','blocked','cancelled')),

    -- 分配(谁领了或被指派)
    assignee TEXT,                          -- agent id: zhangfei-dev
    assigned_by TEXT,                       -- 谁分配的:pangtong-fujunshi / user

    -- 依赖
    depends_on TEXT,                        -- JSON array of task IDs
    parent_task TEXT,                       -- 父任务(子任务分解时)

    -- 优先级和类型
    priority INTEGER NOT NULL DEFAULT 5,   -- 1(最高)-10(最低)
    task_type TEXT,                         -- coding/review/data/deploy/research/discuss

    -- 时间
    created_at TEXT NOT NULL DEFAULT (datetime('now')),
    updated_at TEXT NOT NULL DEFAULT (datetime('now')),
    claimed_at TEXT,
    started_at TEXT,
    completed_at TEXT,
    deadline TEXT,

    -- 重试
    retry_count INTEGER NOT NULL DEFAULT 0,
    max_retries INTEGER NOT NULL DEFAULT 2,

    -- must_haves 与风险等级(课题1设计决策)
    must_haves TEXT,                          -- JSON: {truths: [], artifacts: [], constraints: []}
    risk_level TEXT DEFAULT 'standard',       -- high/standard/low/research
    estimated_duration_minutes INTEGER        -- 预估工时(续杯硬上限 = 3x 此值)
);

CREATE INDEX IF NOT EXISTS idx_tasks_status ON tasks(status);
CREATE INDEX IF NOT EXISTS idx_tasks_assignee ON tasks(assignee);
CREATE INDEX IF NOT EXISTS idx_tasks_parent ON tasks(parent_task);

-- ===== 评论线程表 =====
-- 参考 Hermes kanban_comment:追加写入,所有参与者可见
CREATE TABLE IF NOT EXISTS comments (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    task_id TEXT NOT NULL,
    author TEXT NOT NULL,                   -- agent id 或 'user'
    comment_type TEXT NOT NULL DEFAULT 'general',  -- general/handoff/observation/rebuttal/rebuttal_response/debate_argument/debate_rebuttal/debate_judgment
    body TEXT NOT NULL,
    mentions TEXT,                          -- JSON array: ["zhangfei-dev", "guanyu-dev"]
    created_at TEXT NOT NULL DEFAULT (datetime('now')),

    FOREIGN KEY (task_id) REFERENCES tasks(id),
    CHECK (comment_type IN ('general', 'handoff', 'observation', 'rebuttal', 'rebuttal_response', 'debate_argument', 'debate_rebuttal', 'debate_judgment'))
);

CREATE INDEX IF NOT EXISTS idx_comments_task ON comments(task_id);
CREATE INDEX IF NOT EXISTS idx_comments_type ON comments(task_id, comment_type);
CREATE INDEX IF NOT EXISTS idx_comments_author ON comments(author);
-- 注意:mentions 是 JSON 数组,无法直接建索引。daemon tick 查询用 json_each(mentions)。
-- 数据量小时够用,后续可拆 comment_mentions 关联表优化。

-- ===== 产出表 =====
CREATE TABLE IF NOT EXISTS outputs (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    task_id TEXT NOT NULL,
    agent TEXT NOT NULL,                    -- 谁写的
    output_type TEXT NOT NULL,              -- code/document/data/config/other
    title TEXT NOT NULL,
    content_path TEXT,                      -- 文件路径(产出物在 task 目录下)
    summary TEXT,                           -- 一句话摘要
    metadata TEXT,                          -- JSON: {files_changed, lines_added, ...}
    attempt_number INTEGER DEFAULT 1,       -- 关联 task_attempts.attempt_number
    created_at TEXT NOT NULL DEFAULT (datetime('now')),

    FOREIGN KEY (task_id) REFERENCES tasks(id)
);

CREATE INDEX IF NOT EXISTS idx_outputs_task ON outputs(task_id);

-- ===== 决策记录表 =====
-- Agent 执行过程中的关键决策必须记录。哪怕是自己做的决策也要填一条。
CREATE TABLE IF NOT EXISTS decisions (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    task_id TEXT NOT NULL,
    decider TEXT NOT NULL,                  -- 谁做的决策
    decision TEXT NOT NULL,                 -- 决策内容:"选 A 方案"
    rationale TEXT NOT NULL,                -- 为什么:"B 方案内存开销更大"
    alternatives TEXT,                      -- JSON array: 被排除的选项
    created_at TEXT NOT NULL DEFAULT (datetime('now')),

    FOREIGN KEY (task_id) REFERENCES tasks(id)
);

CREATE INDEX IF NOT EXISTS idx_decisions_task ON decisions(task_id);

-- ===== 观察表 =====
-- Agent 执行过程中发现的问题、风险、建议
CREATE TABLE IF NOT EXISTS observations (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    task_id TEXT NOT NULL,
    observer TEXT NOT NULL,                 -- 谁观察到的
    severity TEXT NOT NULL DEFAULT 'info',
    CHECK (severity IN ('blocking','warning','info','audit')),
    body TEXT NOT NULL,
    resolved_by TEXT,                       -- 谁处理的
    resolved_at TEXT,                       -- 何时处理的
    created_at TEXT NOT NULL DEFAULT (datetime('now')),

    FOREIGN KEY (task_id) REFERENCES tasks(id)
);

-- ===== 事件日志(审计追踪)=====
CREATE TABLE IF NOT EXISTS events (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    task_id TEXT,
    agent TEXT,
    event_type TEXT NOT NULL,
    detail TEXT,                            -- JSON
    created_at TEXT NOT NULL DEFAULT (datetime('now'))
);

CREATE INDEX IF NOT EXISTS idx_events_task ON events(task_id);
CREATE INDEX IF NOT EXISTS idx_events_time ON events(created_at);

-- 合法 event_type 清单:
-- 任务:task_created, task_claimed, task_started, task_completed, task_failed,
--       task_blocked, task_unblocked, task_reviewed, task_cancelled, task_retried
-- 协作:comment_added, output_written, observation_added, decision_recorded
-- Agent:agent_spawned, agent_completed, agent_zombie_detected
-- Session:session_spawned, session_archived, session_cleanup
-- 系统:daemon_tick, daemon_manual_tick

-- ===== Agent 注册表 =====
CREATE TABLE IF NOT EXISTS agents (
    agent_id TEXT PRIMARY KEY,
    role TEXT,
    current_status TEXT DEFAULT 'idle',     -- idle/working/offline
    current_task TEXT,
    last_active TEXT,
    capabilities TEXT                       -- JSON array: ["coding", "review", "deploy"]
);

-- ===== 任务尝试记录(参考 Hermes task_runs)=====
CREATE TABLE IF NOT EXISTS task_attempts (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    task_id TEXT NOT NULL,
    attempt_number INTEGER NOT NULL,
    agent TEXT NOT NULL,
    outcome TEXT NOT NULL,  -- completed/blocked/crashed/timed_out/spawn_failed/reclaimed
    exit_code INTEGER,
    log_path TEXT,
    summary TEXT,
    metadata TEXT,  -- JSON: {duration_seconds, token_count, ...}
    started_at TEXT NOT NULL DEFAULT (datetime('now')),
    completed_at TEXT,

    FOREIGN KEY (task_id) REFERENCES tasks(id)
);

CREATE INDEX IF NOT EXISTS idx_attempts_task ON task_attempts(task_id);

-- agents 表更新规则:
-- Agent claim 任务时:自己更新 current_status='working', current_task=task_id
-- Agent 完成退出时:daemon 更新 current_status='idle', current_task=NULL
-- Daemon tick 检测到 zombie:daemon 更新 current_status='offline'

连接配置:

def get_connection():
    conn = sqlite3.connect(str(DB_PATH))
    conn.row_factory = sqlite3.Row
    conn.execute("PRAGMA journal_mode=WAL")
    conn.execute("PRAGMA foreign_keys=ON")
    conn.execute("PRAGMA busy_timeout=5000")
    return conn

3.3 状态机(v2.8:11 个状态)

pending → claimed → working → review → done
  ↑         │ ↕        ├→ blocked ──┘  ├→ failed
  │         │ paused   ├→ paused      └→ cancelled
  └─────────┘          ├→ escalated
                       └→ waiting_human  ← M3 Checkpoint

  (review→pending: 审核不通过,打回重做)
  (review→waiting_human: 审查阶段需人工裁定)
  (blocked→pending: 阻塞解除)
  (blocked→escalated: 阻塞升级求助)
  (failed→pending: 重试)
  (failed→escalated: 失败升级求助)
  (escalated→working: 用户介入后恢复)
  (waiting_human→working: Checkpoint reject)
  (waiting_human→done: verify Checkpoint approve)

v2.8 变更: v2.6 有 8 个状态,v2.8 新增 3 个: paused(用户暂停)、escalated(Agent 升级求助)、waiting_human(Checkpoint 人工确认)。

状态 含义 谁触发 调度 聚合
pending 待领取 任何 Agent 或用户创建 正常调度 参与
claimed 已认领 Agent 自己或被指派 超时回收 参与
working 执行中 Agent 超时监控 参与
review 待审核 Agent 完成产出 review 调度 参与
paused 已暂停 用户主动 跳过 不参与
escalated 已升级 Agent 求助 跳过 视同 working
waiting_human 等人工 Agent Checkpoint 跳过 视同 working
done 完成 审核通过 终态 参与
failed 失败 Agent 或 daemon 不调度 参与
blocked 需要帮助 Agent 不调度 参与
cancelled 取消 用户 终态 不参与

聚合规则(v2.8: 优先级 escalated > waiting_human > review > working/claimed > pending > failed > blocked。paused/cancelled 不参与。全部 done → done。

完整合法流转矩阵:

VALID_TRANSITIONS = {
    "pending":       {"claimed", "cancelled"},
    "claimed":       {"working", "paused", "pending", "cancelled"},
    "working":       {"review", "blocked", "failed", "paused", "escalated", "waiting_human", "cancelled"},
    "paused":        {"working", "cancelled"},
    "review":        {"done", "pending", "failed", "escalated", "waiting_human", "cancelled"},
    "blocked":       {"pending", "escalated", "cancelled"},
    "failed":        {"pending", "escalated", "cancelled"},
    "escalated":     {"working", "pending", "cancelled"},
    "waiting_human": {"working", "done", "cancelled"},
    "done":          set(),                                       # 终态
    "cancelled":     set(),                                       # 终态
}

字段迁移(v2.8: escalated 从布尔字段改为 status 判断。DB 保留 escalated INTEGER 做向后兼容,前端/Ticker 改用 task.status == 'escalated'

归档机制(v2.8: tasks 表新增 archived INTEGER DEFAULT 0archived_at TEXT。归档不改变状态,只影响前端显示(默认不显示已归档任务)。

Checkpoint 机制(M3: Agent 执行到需人工确认的节点 → 创建 checkpoint + 设置 waiting_human → 用户 approve/reject → 自动推进状态。详见 docs/design/v2.8-state-enhancement.md

3.4 原子操作

任务认领(claim) - 原子 CAS,防止两个人同时领:

def claim_task(task_id: str, agent_id: str) -> bool:
    conn = get_connection()
    try:
        cursor = conn.execute(
            "UPDATE tasks SET status='claimed', assignee=?, claimed_at=datetime('now') "
            "WHERE id=? AND status='pending' AND (assignee IS NULL OR assignee=?)",
            (agent_id, task_id, agent_id)
        )
        conn.commit()
        return cursor.rowcount > 0  # 0 表示被别人抢了或不是指定分配给自己的人
    finally:
        conn.close()

产出写入 - SQLite 事务保证原子:

def write_output(task_id: str, agent_id: str, output: dict):
    conn = get_connection()
    try:
        conn.execute("BEGIN IMMEDIATE")  # 立即获取写锁
        conn.execute(
            "INSERT INTO outputs (task_id, agent, output_type, title, content_path, summary, metadata) "
            "VALUES (?, ?, ?, ?, ?, ?, ?)",
            (task_id, agent_id, output['type'], output['title'],
             output['path'], output['summary'], json.dumps(output.get('metadata', {})))
        )
        conn.execute(
            "INSERT INTO events (task_id, agent, event_type, detail) VALUES (?, ?, 'output_written', ?)",
            (task_id, agent_id, json.dumps({'output_id': output['title']}))
        )
        conn.commit()
    finally:
        conn.close()

3.5 评论线程(讨论机制)

参考 Hermes 的 kanban_comment 模式:

def add_comment(task_id: str, author: str, body: str, mentions: list = None):
    conn = get_connection()
    try:
        conn.execute(
            "INSERT INTO comments (task_id, author, body, mentions) VALUES (?, ?, ?, ?)",
            (task_id, author, body, json.dumps(mentions or []))
        )
        conn.execute(
            "INSERT INTO events (task_id, agent, event_type, detail) VALUES (?, ?, 'commented', ?)",
            (task_id, author, json.dumps({'body_preview': body[:100], 'mentions': mentions}))
        )
        conn.commit()
    finally:
        conn.close()

讨论示例:

[16:30 庞统] 张飞,你的实现方案我看了,回测数据量大时内存会爆。
              关羽,从风控角度也看看? @关羽 @张飞
[16:35 关羽] 同意。建议加分批加载机制,单批不超过 50 万条。
[16:40 张飞] 收到,改成分批加载。预计 30 分钟。
[16:55 庞统] @张飞 注意止损逻辑也需要同步改,分批后止损触发时机变了。
[17:10 张飞] 完成。产出在 output-zhangfei-v2.md。

核心原则:评论都在黑板上,不在任何 agent 的 session 里。Agent 的 session 是临时的。

3.6 竞态解决

任务认领的竞态通过 SQLite 原子 CAS 解决(先到先得)。

职责冲突的解决(张飞和关羽都认为自己该做某个任务):

  1. 默认:先到先得 - SQLite CAS,谁先 claim 谁做
  2. 升级:庞统仲裁 - 如果争议,评论中 @庞统 请求仲裁
  3. 最终:用户拍板 - @user 请求用户决定

不需要复杂的分布式共识--职责分工已经自然避免了大部分冲突。

3.7 黑板是索引不是仓库(AI Native 内容规范)

核心原则:黑板只存元数据 + 摘要 + 文件路径,不存大段文本内容。

设计推导(课题 2):

  • Network-AI 的核心洞察:Agent 只读黑板摘要,详细数据在文件中
  • Claude Code 的 file reference 模式:不内联,只引用
  • agent-chorus 的 Context Pack 实验证明:结构化上下文让 Agent 文件打开量降 70%、token 消耗降 60%、零生产风险答案
  • Opal-Bridge 的 Fidelity 三档:无损/摘要/混合,传递时按需降档
  • 一个典型任务全量黑板信息 ~1100-1750 tokens,极端 ~4000 tokens--远小于 128K context
  • 问题不是空间不够,而是信号噪声比:全量注入让 Agent 在无关信息上浪费注意力

AI Native 内容规范--不做硬限制,做软引导:

传统做法是给每个字段设长度上限(如 comments.body ≤ 2000 字符),这是 CRUD 应用的思维。 AI Native 的做法是:Agent 是智能体,有能力判断"这段分析应该写文件还是直接写评论"。规范是指导性的,不是强制性的。

  • 不做硬限制--不设字段长度上限,不截断,不报错
  • 做软引导--Agent 的 Skill 中写"评论应简洁明了,大段分析写文件后在评论中给路径"
  • 做传递优化--L1 传递时自动截取(最近 3 条评论、每条 100 字符),这是传递层面的优化,不是存储层面的限制
  • 做信息分层--黑板上的 comments 表存完整内容(不截断),但 L1 传递时只取摘要

为什么这样做是 AI Native:

  1. Agent 是智能体,不是 API 客户端--它有能力判断"这段分析应该写文件还是直接写评论"
  2. 如果硬限制导致信息丢失,Agent 会绕过限制(拆成多条评论、用文件存储),反而更混乱
  3. 真正需要控制的是传递时的信息量(L1 预算),不是存储时的信息量

黑板上"必要信息"的定义(指导性):

类别 上黑板 不上黑板
决策 谁、选了什么、为什么 完整备选方案对比表
产出 title + summary + content_path 代码全文、数据文件
状态 当前 status + 最新 observation 完整事件日志(可归档)
讨论 结论 + 关键论据 来回辩论的完整过程
风险 severity + 一句话描述 详细影响分析报告

防爆炸机制:

  • 产出物只存路径(outputs.content_path)
  • 事件日志有 TTL(events 表定期归档旧数据)
  • 大段分析建议写文件,黑板只存摘要+路径

三层约束体系(AI Native 结构化约束)

Skill 软引导的问题是"可看可不看",等于没有约束。数据库硬限制是传统 CRUD 思维。中间地带是 CLI 层 Schema 校验——参考 agent-chorus 的 JSON Schema 模式(每个操作都有 schemas/*.schema.json),在写入接口层校验结构。

机制 约束力 适用对象
Schema 校验 blackboard.py CLI 写入时校验 JSON Schema 强(不符合返回明确错误) 结构化操作(handoff / output / decide / observe
Skill 引导 Agent Skill 中的行为规范文本 弱(可看可不看) 非结构化操作(普通评论、讨论)
L1 截取 Daemon 构建 L1 时自动截取 代码层面,Agent 无感 传递优化

为什么这是 AI Native

  1. Schema 是可执行文档——Agent 不需要读 Skill 就能知道格式要求(CLI 错误信息会告诉它缺了什么)
  2. 错误信息是建设性的——"Handoff must include 'completed' field" 让 Agent 知道该补什么
  3. 约束的是结构,不是内容——不限制写多长,只限制必须包含哪些字段
  4. Agent 可以自主决定深度——可选字段可以不写
  5. 和 OpenAI Agent SDK 的 handoff input_type 同理——Pydantic schema 校验交接数据

Schema 定义schemas/ 目录):

// schemas/handoff.schema.json
{
  "type": "object",
  "required": ["completed", "artifacts"],
  "properties": {
    "completed": { "type": "string", "description": "完成了什么" },
    "artifacts": {
      "type": "array",
      "items": { "type": "string" },
      "description": "产出物路径列表"
    },
    "remaining": { "type": "string", "description": "未完成事项(可选)" },
    "next_steps": { "type": "string", "description": "对接手者的建议(可选)" }
  }
}

// schemas/observe.schema.json
{
  "type": "object",
  "required": ["severity", "body"],
  "properties": {
    "severity": {
      "type": "string",
      "enum": ["info", "warning", "critical"],
      "description": "info=只记录不触发; warning=下次tick触发庞统; critical=立即spawn庞统"
    },
    "body": { "type": "string", "description": "风险描述" }
  }
}

severity 枚举与处理方式对齐(与 §4.7 Guardrail 体系一致):

severity Daemon 处理 对应 Guardrail 行为
info 只记录,不触发 不介入
warning 下次 tick 统一处理 spawn 庞统(L3)判断
critical inbox 通知 → 立即 spawn 庞统 立即介入
操作 Schema 文件 必填字段 Schema 校验 CLI 附加校验
--handoff handoff.schema.json completed + artifacts 结构完整,类型正确 artifacts 中路径是否存在
--output output.schema.json summary + content_path summary 非空字符串 content_path 文件是否存在
--decide decide.schema.json decision + rationale 两个字段非空字符串
--observe observe.schema.json severity + body severity 枚举值(info/warning/critical)
--comment(普通) body 无 Schema 校验

Agent 使用方式

# 结构化操作:CLI 校验 Schema
blackboard.py comment --task task-001 --author zhangfei-dev \
  --handoff '{"completed": "分批加载实现", "artifacts": ["task-001/output.md"], "remaining": "止损逻辑"}'
# 校验失败 → 返回具体错误:"Handoff must include 'completed' field"
# 校验通过 → 写入 comments 表,body 自动格式化为结构化文本

# 普通评论:无 Schema 校验
blackboard.py comment --task task-001 --author zhangfei-dev \
  --body "@赵云 task-002 需要分钟线数据"

落地到 schema(存储层):

  • outputs 表:content_path + summary,不存文件内容
  • comments 表:body 存完整内容(不截断),handoff 类型自动格式化
  • decisions 表:decision + rationale 是结构化文本
  • observations 表:body 是风险描述

Agent 获取信息的分层策略(L1/L2/L3)详见 §4.4,对应 Opal-Bridge Fidelity 三档。


4. Daemon(管家)设计

4.1 Daemon 的角色定位

Daemon 是投递员,不是决策者。所有决策发生在黑板上,daemon 只执行。

Daemon 做三件事:

  1. 读黑板 - 定期 tick,检查黑板状态
  2. Spawn Agent - 根据黑板上的指示,spawn 对应的 agent
  3. 清理 Session - agent 执行完后,存档 jsonl + 清理 sessions.json

Daemon 不做:

  • 不决定谁做什么(agent 自己决定或庞统在黑板上分配)
  • 不维护状态机(黑板就是状态)
  • 不做业务逻辑(不解析产出、不做评审)

三层执行模型:Daemon 的操作按成本和复杂度分为三层:

层级 方式 成本 适用场景 例子
L1 Daemon 直接操作 SQLite 读写、文件操作 几乎为零 纯机械动作 更新状态、记录事件、机械验证(文件存在、JSON格式、字段非空)
L2 spawn sub openclaw agent --agent <id> --session-id <uuid> 轻量(隔离 session,单任务) 轻量 AI 判断 scope guard、格式校验、快速评估、假死 reminder
L3 run agent spawn 完整 Agent 到黑板上工作 完整(读黑板+思考+写回) 重度 AI 工作 庞统拆解、张飞编码、司马懿 review、庞统纠错

关键区别:

  • L2 的 sub 是一次性、单任务的("帮我检查这个输出是否在 scope 内"),执行完就退出
  • L3 的 agent 是完整的黑板参与者(读全局、自主决策、写回多个表)

L2 与 L3 的区分标准:是否读黑板全局。

  • L2:不读黑板全局上下文,只拿当前任务的特定字段做判断。spawn 时传递局部数据(如 scope_declaration 文本 + task.truths),sub 返回结果后退出。
  • L3:读黑板全局(tasks + comments + outputs + decisions + observations),做全局决策。spawn 时只传任务 ID + 触发原因,Agent 自己读黑板。

这个区分决定了 spawn 时的消息内容--L2 传数据,L3 传指针。

4.2 事件驱动架构(课题 2 设计决策)

设计推导过程

三个参考系统的做法:

系统 架构 事件通知方式 启示
open-multi-agent 单进程 TypeScript 纯 EventEmitter--queue.on('task:ready', handler)。TaskQueue 内部维护 listeners Map,complete() 时同步触发 emit。零基础设施 和我们的黑板同构:TaskQueue.complete() = 我们的任务完成,unblockDependents() = 我们的依赖解锁
agent-chorus 多进程(Claude/Codex/Gemini 各自独立) 本地 JSONL 文件队列--chorus send 写入 .agent-chorus/messages/<target>.jsonl,chorus messages --agent <self> --clear 读并清空。纯文件系统,无网络 Standup+Conclude 模式:Agent 开始时读 inbox,结束时广播状态。JSONL inbox 做跨进程通信
Edict 分布式(API Gateway + Orchestrator + Agent Pool) Redis Streams Event Bus--task.created 等主题 + WebSocket 推送 Dashboard 我们是单机单进程,不需要 Redis

推导结论:

  1. open-multi-agent 证明:单进程内 EventEmitter 完全够用,但它是单进程,我们是跨进程
  2. agent-chorus 证明:跨进程通信用 JSONL 文件就行,不需要 HTTP/Redis/MQ
  3. Edict 的 Redis Streams 是分布式场景所需,我们不需要
  4. 真正需要即时响应的场景只有 4 个:task_completed / task_failed / @mention / user_action。其他 ≤30s 延迟完全可接受
  5. 60s Tick 本身不是问题,问题是 Tick 的效率--应该 Tick 是核心,加速器可选

用户反馈与设计迭代:

  • 初始设计:Signal File 跨进程通知 → 用户质疑"Signal File 存在的意义是什么"
  • 第二版:HTTP 端点 → 用户要求"基于优秀实践推导,不是拍脑袋换方案"
  • 最终版:Tick 核心 + Inbox JSONL 加速(agent-chorus 模式)--基于三个参考系统的实际代码推导

D2-1:Tick 核心 + Inbox 加速(最终方案)

┌──────────────────────────────────────────────────────────────────┐
│                    Daemon (Python asyncio)                       │
│                                                                   │
│  核心:Tick Loop(30s 主循环)                                     │
│  ┌─────────────────────────────────────────────────────────────┐ │
│  │ 读黑板全量状态(SQLite 查询)                                  │ │
│  │ 发现需要处理的(mention / blocked / done → pending)           │ │
│  │ 执行对应操作(spawn / 通知 / 清理)                             │ │
│  │ 健康检查(zombie / stale / heartbeat)                         │ │
│  │                                                               │ │
│  │ 设计推导:Hermes 60s tick 证明 polling 可靠稳定。              │ │
│  │ 我们从 60s 降到 30s,因为黑板查询比 Hermes 轻量。              │ │
│  └─────────────────────────────────────────────────────────────┘ │
│          ↑                                                        │
│  加速:Inbox JSONL(agent-chorus 模式)                           │
│  ┌─────────────────────────────────────────────────────────────┐ │
│  │ Agent 写黑板后,可选:追加一行 JSON 到 daemon inbox             │ │
│  │ Daemon 主循环每 1s 检查 inbox 是否有新内容                     │ │
│  │ 有新内容 → 立即执行一次 mini-tick(只处理触发的事件)            │ │
│  │ 处理完清空 inbox                                               │ │
│  │                                                               │ │
│  │ 设计推导:agent-chorus 用 JSONL inbox 做跨 Agent 通信,         │ │
│  │ 我们用 JSONL inbox 做 Agent→Daemon 通知。同理同构。            │ │
│  │ inbox 是加速器,不是核心。Tick 兜底所有场景。                    │ │
│  └─────────────────────────────────────────────────────────────┘ │
│          ↑                                                        │
│  恢复:启动时全量扫描                                              │
│  ┌─────────────────────────────────────────────────────────────┐ │
│  │ Daemon 重启后立即做一次完整 Tick(PM2 自动重启)                │ │
│  │ 消除重启后的 30s 空窗                                          │ │
│  │ 不需要 EventBus 持久化--黑板(SQLite)是唯一真相源              │ │
│  └─────────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────┘

为什么不选的替代方案:

  • EventBus + Signal File(初始设计):Signal File 需要额外的扫描/读/删循环,增加了耦合链
  • HTTP 端点(第二版):引入网络依赖,Daemon 需要跑 HTTP 服务,不够简单
  • Redis pub/sub(Edict 方案):引入新依赖,v2.6 已去掉 Redis;我们不需要分布式
  • SQLite update-hook:需要 C API 绑定
  • fswatch/watchdog:跨平台兼容性差

Inbox JSONL 具体实现(参考 agent-chorus chorus send 模式):

# blackboard.py 写完 SQLite 后,可选追加一行 JSON
INBOX_PATH = Path("~/.sanguo_projects/sanguo_moziplus_v2/inbox/daemon.jsonl")

# 写入格式(参考 agent-chorus message schema: from/to/timestamp/content/cwd)
async def notify_daemon(event_type: str, task_id: str, agent: str):
    line = json.dumps({
        "from": agent,
        "to": "daemon",
        "timestamp": datetime.now(timezone.utc).isoformat(),
        "event": event_type,     # comment_added / task_completed / task_failed
        "task_id": task_id,
    })
    async with aiofiles.open(INBOX_PATH, mode='a') as f:
        await f.write(line + '\n')

# Daemon 主循环中检查 inbox
async def check_inbox():
    if not INBOX_PATH.exists():
        return
    lines = INBOX_PATH.read_text().strip().split('\n')
    INBOX_PATH.write_text('')  # truncate:清空内容不删除文件,避免并发追加写入时文件不存在
    for line in lines:
        msg = json.loads(line)
        await handle_event(msg['event'], msg['task_id'], msg['from'])

Daemon 主循环:

async def daemon_main_loop():
    # 启动时全量扫描
    await full_tick()

    while True:
        # 1. 检查 inbox(每 1s)
        await check_inbox()  # 有内容则立即执行 mini-tick

        # 2. 定期 Tick(每 30s)
        if time.time() - last_tick > 30:
            await full_tick()
            last_tick = time.time()

        await asyncio.sleep(1)

D2-2:依赖声明的并行/串行自动决策

设计推导:open-multi-agent 的 TaskQueue.complete() → unblockDependents() 是核心模式--complete→auto-unlock,纯依赖声明驱动。其 scheduler.ts 还提供了 4 种调度策略(round-robin / least-busy / capability-match / dependency-first)。

串行触发链(Tick + Inbox 加速版):

Agent A 完成 task-001
  → 写黑板 outputs + 更新 status → done + 写 handoff comment
  → 通知 Daemon(inbox JSONL)
  → Daemon 下次循环(~1s 内)收到通知 → mini-tick:
      查询所有 depends_on 包含 task-001 的 pending 任务
      → task-002 depends_on: [task-001],检查 task-001 done ✅
      → spawn Agent B 执行 task-002
  (如果 inbox 通知丢失 → 30s Tick 兜底补上)

并行:depends_on 为空且 assignee 不同的任务,自然并行(Daemon 分别 spawn)。不需要额外逻辑。

不做 files_modified 冲突检测(D2-4):Agent 通过黑板评论自然协调("我在改 main.py,你别碰"),不需要系统强制。Scope Guard(课题 1)作为兜底。实际覆盖:depends_on 覆盖 80%+ 的显式依赖场景,边角场景通过黑板评论 + 庞统仲裁补充。

与课题 1 的兼容性

课题 1 设计 事件驱动后变化 改善
续杯机制 task_completed 通知加速依赖解锁 @mention 从 ≤60s 降到 ≤1s
retry 由 AI 决策 task_failed 通知加速 retry 链 庞统更快介入
Guardrail 吹哨人 observation 写入后通知 Daemon Daemon 即时感知问题
三层执行模型 不变,Tick/inbox 处理仍按 L1/L2/L3 分层 一致

4.3 Session 生命周期

1. Daemon spawn
   openclaw agent --agent zhangfei-dev --session-id <uuid> \
     --message "请检查黑板 task-001..."
   ↓
2. Agent 执行
   - 读黑板(SQLite 查询)
   - 做任务(编码/审核/数据分析)
   - 写回黑板(产出、评论、状态更新)
   ↓
3. Agent 退出(自然结束)
   ↓
4. Daemon 清理
   - mv <session_id>.jsonl → task-001/archive/
   - mv <session_id>.trajectory.jsonl → task-001/archive/
   - 编辑 sessions.json 删除该 session 记录

技术验证结论:

  • openclaw agent --agent <id> --session-id <uuid> 可创建完全隔离的 session
  • 直接编辑 sessions.json 可安全删除 session 记录 (已验证)
  • Gateway WS sessions.delete 需要 operator.admin scope(token 模式不授予,不可用)
  • 回退方案:直接编辑 sessions.json 是安全可靠的

4.4 Agent Spawn 的上下文分层传递(课题 2 设计决策)

设计推导:GSD Wave Execution 证明隔离 session + 新鲜 context > 单一 session + 压缩。Claude Code 的 file reference 模式证明"引用而非内联"是最优策略。Opal-Bridge 的 Fidelity 三档提供了理论框架。agent-chorus 的 Context Pack 实验证明结构化上下文让 Agent 效率提升 60-70%。问题不是 context 不够大,而是信号噪声比。

L1/L2/L3 对应 Opal-Bridge Fidelity 三档:

Opal-Bridge Fidelity 我们的映射 场景
Mode A:无损(完整上下文) L1 + L2 + L3 复杂任务,Agent 需要完整了解讨论历史和产出
Mode B:LLM 摘要 L1 + L2 标准任务,核心信息 + 扩展摘要
Mode C:混合保留最近N条 L1 简单任务,只传核心,Agent 按需取更多

Agent 自己决定用哪个 Fidelity 档位--收到 L1 后判断信息是否足够,不够就 L2/L3。

D2-5:三层上下文传递(L1 必传 / L2 按需 / L3 按需)

层级 内容 Token 估算 谁决定
L1(spawn message) 任务核心 + 角色 + 触发原因 + 依赖状态 + 最近评论 + must_haves ~300-500 Daemon 自动
L2(CLI 按需) 完整评论线程 + 产出摘要 + 决策记录 + 观察记录 ~500-1500 Agent 自主决定
L3(文件按需) 产出物文件完整内容 + 完整事件日志 + 子任务详情 ~2000-10000 Agent 自主决定

L1 Spawn Message 模板:

def build_spawn_message_L1(task_id: str, agent_id: str, trigger: str) -> str:
    task = get_task(task_id)

    # 依赖状态摘要(1行/依赖任务)
    deps_status = []
    for dep_id in json.loads(task['depends_on'] or '[]'):
        dep = get_task(dep_id)
        deps_status.append(f"  {dep_id}: {dep['status']} - {dep['title']}")

    # 最近 3 条评论摘要(截断 100 字符)
    recent_comments = get_comments(task_id, limit=3)
    comments_str = ""
    for c in recent_comments:
        comments_str += f"  [{c['created_at'][:16]} {c['author']}] {c['body'][:100]}\n"

    # must_haves 摘要
    must_haves = json.loads(task.get('must_haves') or '{}')
    truths_str = ', '.join(must_haves.get('truths', []))

    return f"""黑板任务通知(L1):
任务:{task['title']}({task['id']})
状态:{task['status']} | 类型:{task['task_type']} | 风险:{task['risk_level']}
触发原因:{trigger}
描述:{task['description'] or '(无)'}
验收标准(truths):{truths_str or '(未定义)'}

依赖状态:
{chr(10).join(deps_status) if deps_status else '  (无依赖)'}

最近评论:
{comments_str if comments_str else '  (无评论)'}

请使用以下命令获取更多信息:
  L2(扩展):blackboard.py read --task {task_id} --level L2
  L3(全量产出):blackboard.py read --task {task_id} --type outputs
"""

D2-6:不需要 Auto-compact:v2.6 的 Agent 每次 spawn 都是隔离的新鲜 session,天然没有 context rot。唯一可能有累积的是庞统主 session(长期在线协调),属 Phase 3 优化。

D2-7:Context 预算分配(128K 模型):

组件 预算 说明
System Prompt + SOUL.md + IDENTITY.md ~3K-5K tokens 固定开销
Skills + AGENTS.md ~2K-4K tokens 固定开销
L1 spawn message ~300-500 tokens 必传
L2 黑板扩展(按需) ~500-1500 tokens Agent 自主决定
L3 产出物文件(按需) ~2K-10K tokens Agent 自主决定
工作空间(Agent 思考+输出) ~30K-50K tokens 预留
总计 ~40K-70K tokens 远小于 128K,安全

4.5 续杯与心跳

参考 v1.0 实践 + Hermes v0.13 Claim TTL。

正常流(大多数情况):

  1. Agent spawn → 开始工作
  2. Agent 每个关键进展写黑板 observation(既是进度汇报,也是心跳信号)
  3. Daemon tick 看到 working 状态 + 有新 observation → 不干预(健康状态)
  4. Agent 完成产出 → 写 output + 状态流转 → Daemon 检测到继续下一步

异常流:

情况 Daemon 检测到 行为 层级
Agent 有进展 黑板有新 observations 不干预(无限续) L1
Agent 没进展但 session 活跃 无新 observations 但 session 还在 不干预(可能正在思考) L1
↑ 判断信号:observations 最后写入时间 < estimated_duration_minutes,纯 L1 查询,不依赖 AI 判断
timeout(agent run 返回超时)+ 产出达标 agent run 返回超时 + outputs 表有内容 幻觉门控验证产出 → 通过则继续流转 L1→L2
timeout(agent run 返回超时)+ 产出不达标 agent run 返回超时 + outputs 为空 L2 spawn sub 发 reminder 让 Agent 继续(假死处理) L2
timeout + 产出不达标 + reminder 后仍无进展 二次 timeout 回收到 pending,记录 failure_detail L1
非timeout 错误(进程退出) 进程已死 进入 AI 纠错流程 L3
硬上限超时 working 状态超过 3x 预估工时 强制回收,记录事件 L1

设计推导:

  • v1.0 实践证明:看结果不看过程(即使 CLI 报错/超时,产出文件存在且有效就算成功)
  • 续命和重试是两个独立预算:续命(Agent有进度→无限续),重试(Agent真挂→有限次)
  • Hermes 的 Claim TTL(默认15分钟)提供了超时回收的参考值

timeout 的检测:timeout 信号来自 openclaw agent --agent <id> 的返回值(阻塞调用)。Agent 在执行过程中通过写黑板 observations 维持活跃信号--Daemon tick 检查 observations 的最后写入时间,如果有新 observation 说明 Agent 还在工作。但最终判断 Agent 是否超时,以 agent run 的返回值为准。

reminder 后的硬时间上限:reminder 后如果超过 estimated_duration_minutes 仍未完成(从 reminder 时间算起),才回收任务。

4.6 AI 驱动的 Retry(纠错协商)

参考 v1.0 _handle_blocked_node() + Hermes task_runs + Claude Code Teams "before retrying, answer what failed"。

核心原则:Retry 原因由 AI 判断,Daemon 只执行。

流程:

  1. Agent 失败(产出 status=failed 或 Daemon 检测到异常终止)
  2. Daemon 不判断原因,只在黑板上记录这次 attempt(task_runs 模式,每次 attempt 独立记录)
  3. Daemon spawn 庞统(L3)看黑板上的失败记录 + 之前所有 attempts
  4. 庞统在黑板上写决策(四种选择之一):
    • "同一 Agent 重试" + 失败原因分析 + 改进建议
    • "换 Agent 重试" + 为什么换 + 新 Agent 优势
    • "任务需要用户介入" + 卡在哪 + 建议
    • "任务无法完成,建议取消" + 为什么
  5. Daemon 读庞统决策,执行对应操作
  6. 如果重试后仍失败 → 新 attempt 记录 → 再次 spawn 庞统
  7. Circuit breaker:同一 task 总 attempt 数达到 N 次(默认3次,不区分是哪个 Agent)→ 自动 block + 通知用户。理由:3 次尝试都不成功说明问题在任务本身而非 Agent 能力。

失败记录:谁记录什么?

记录者 记录内容 黑板位置
Daemon 机械类失败(进程退出码、超时) events 表,event_type=task_failed
司马懿 内容类失败(评审不通过) reviews 表(verdict=needs_revision + issues)
庞统 方向类失败(需求偏离) decisions 表(重规划原因)
Agent 自己 能力不足/专业外,主动报告失败 comments 表(说明原因)+ tasks status→failed
Agent(重试时) 新 attempt 的产出 outputs 表(带 attempt_number)

Agent 重试时能看到什么:黑板上的 events(失败记录)+ reviews(评审意见)+ comments(讨论)。全部在黑板上,spawn 时自然读到。

设计推导:

  • v1.0 实践:庞统分析原因 → 司马懿 challenge → 三轮协商 → 执行,方向正确但由引擎硬编码调用
  • v2.6 改进:Agent 在黑板上自主协商(需要事件驱动支持,见课题2),Daemon 只 spawn 不调度
  • Hermes task_runs:每次 attempt 独立记录(attempt_number, outcome, log_path, exit_code),可追溯可审计

4.7 Guardrail 体系(吹哨人机制)

参考 OpenAI Agent SDK OutputGuardrail + GSD must_haves + v1.0 M4 Guard 机制。

核心原则:Guardrail 是吹哨人不是终结者。检测到问题写黑板(observation),触发后续 AI 判断链。决策权在黑板上,执行权在 Daemon。

三个 Guardrail:

Guardrail 触发时机 检测方式 发现问题后
Scope Guard Agent claim 任务后在工作过程中写 decisions(scope 相关)时 L2 sub 异步对比 scope_declaration vs task.truths 写 observation(severity=warning),Daemon 下次 tick 触发庞统判断
Output Guard Agent 写 output 时 L1 机械检查(文件存在、格式正确、字段非空)+ L2 语义检查 机械失败直接打回,语义问题写 observation
Format Guard Agent 写任何结构化数据时 L1 JSON Schema 校验 格式错误直接打回重做

后续动作链(问题升级):

Guardrail 检测到问题 → 写黑板 observation
  ↓
Daemon tick 读到 observation
  ↓
根据 severity 分级处理:
  - blocking → L3 立即 spawn 庞统
  - warning → L3 spawn 庞统(下次 tick 统一处理)
  - info → 只记录,不触发
  ↓
庞统在黑板上写决策:
  - "确认偏离,打回" → Daemon 改状态回 pending
  - "方向扩展合理,批准继续" → 继续
  - "需要用户判断" → 通知用户

设计推导:

  • OpenAI Agent SDK:Guardrail 本身是轻量 AI Agent(并行运行,专门做检查),不是 if-else 规则
  • GSD must_haves truths:面向可观测行为,不是实现步骤
  • v1.0 M4 Guard:entry/exit guard + skill 化检查逻辑,方向正确但绑定在 DAG 节点上

Scope Guard(异步检查,不阻塞 Agent 执行):

  • 触发时机:Agent claim 任务后在工作过程中写 decisions(scope 相关)时
  • 检查方式:L2 sub 异步对比 scope_declaration vs task.truths
  • 不阻塞:Agent 写完 scope_declaration 后继续工作,不等 Guard 结果
  • 发现问题:写 observation(severity=warning),Daemon 下次 tick 触发庞统判断
  • 兜底:即使 Scope Guard 漏报,庞统在 review 阶段仍会检查方向正确性

5. Agent 与黑板的交互

5.1 Agent 被_spawn_后的工作流程

Agent 被 spawn
    ↓
1. 读黑板 → 了解任务全局状态
   - 读 tasks 表:当前任务的状态、描述、依赖
   - 读 comments 表:讨论历史
   - 读 outputs 表:已有产出
   - 读 observations 表:已知风险
    ↓
2. 想 → 根据自己的职责自主决策
   - 我是编码先锋,这个 pending 任务适合我 → claim
   - 我是风控守将,这个 comment @ 我 → 回复
   - 我是副军师,这个任务需要分解 → 创建子任务
   - Agent claim 任务后、开始工作前,写 scope_declaration 到 decisions 表:
     "我计划做什么,产出什么"
     Scope Guard(L2 sub)会对比 scope_declaration vs task.truths
    ↓
3. 做 → 执行任务
   - 编码、审核、数据分析等
   - 过程中发现风险 → 写 observation
   - 需要其他人协助 → 写 comment @mention
    ↓
4. 写回黑板 → 产出、评论、状态更新、决策记录
   - 写 outputs 表:产出文件路径 + 摘要
   - 写 comments 表:完成说明
   - 写 decisions 表:关键决策(哪怕自己的决策也要填一条)
   - 更新 tasks 表:status → done/review
   - must_haves 三件套(任务创建时由庞统定义):
     - truths:用户视角的可观测行为("用户能看到回测结果"),不是实现步骤("编写回测脚本")
     - artifacts:必须存在的产出文件
     - constraints:继承的约束(如"不超过500行"、"必须用vnpy")
    ↓
5. 写 Handoff Comment → 退出
   - Agent 结束前必须写一条结构化的交接评论(借鉴 agent-chorus checkpoint)
   - 内容:完成什么、产出在哪、还剩什么、建议下一步
   - 这条 comment 会出现在下一个 Agent 的 L1 消息中(最近 3 条评论),实现无缝接手
   - 示例:
     ```
     blackboard.py comment --task task-001 --author zhangfei-dev \
       --body "## Handoff\n完成:分批加载实现\n产出:task-001/output-zhangfei-v2.md\n未完成:止损逻辑分批适配\n建议下一步:关羽 review 止损逻辑"
     ```
    ↓
6. Daemon 自动清理 session
   - 通知 Daemon(inbox JSONL)
   - Daemon 检测到完成 → 继续下一步(解锁下游 / spawn review / 清理 session)

设计推导(Handoff Comment):

  • agent-chorus 的核心机制是 Standup + Conclude:Agent 开始时读 inbox,结束时广播状态
  • 映射到黑板:Standup = Agent spawn 后读黑板(L1),Conclude = Agent 结束时写 handoff comment
  • agent-chorus 的 checkpoint 广播给所有其他 Agent → 我们的 handoff comment 通过 L1 自然传递给下一个 Agent
  • 关键价值:黑板上的状态足够让 Agent B 无缝接手 Agent A 的工作--这正是 agent-chorus 解决的核心问题

5.2 Agent 工具集

Agent 通过 exec 工具调用 CLI 命令操作黑板:

# 读黑板(全部)
python3 ~/.sanguo_projects/sanguo_moziplus/cli/blackboard.py read --task task-001

# 读黑板(过滤:只读和自己相关的)
python3 ~/.sanguo_projects/sanguo_moziplus/cli/blackboard.py read --task task-001 --agent zhangfei-dev

# 读黑板(过滤:只读最近 20 条)
python3 ~/.sanguo_projects/sanguo_moziplus/cli/blackboard.py read --task task-001 --last 20

# 读黑板(过滤:只读特定类型)
python3 ~/.sanguo_projects/sanguo_moziplus/cli/blackboard.py read --task task-001 --type comments

# 认领任务
python3 ~/.sanguo_projects/sanguo_moziplus/cli/blackboard.py claim --task task-001 --agent zhangfei-dev

# 写产出
python3 ~/.sanguo_projects/sanguo_moziplus/cli/blackboard.py output --task task-001 --agent zhangfei-dev \
  --type code --title "分批加载实现" --path task-001/output-zhangfei.md \
  --summary "实现分批加载,单批50万条"

# 写评论
python3 ~/.sanguo_projects/sanguo_moziplus/cli/blackboard.py comment --task task-001 --author zhangfei-dev \
  --body "完成分批加载实现" --mentions "[]"

# 写观察
python3 ~/.sanguo_projects/sanguo_moziplus/cli/blackboard.py observe --task task-001 --observer guanyu-dev \
  --severity warning --body "止损逻辑需适配分批模式"

# 记录决策
python3 ~/.sanguo_projects/sanguo_moziplus/cli/blackboard.py decide --task task-001 --decider zhangfei-dev \
  --decision "使用分批加载而非流式" --rationale "流式需要改底层框架,分批只需改回测模块"

# 创建任务(任何 Agent 都可以创建)
python3 ~/.sanguo_projects/sanguo_moziplus/cli/blackboard.py create --title "分钟线数据下载" \
  --creator zhaoyun-data --task-type data

# 写 Handoff Comment(结构化,CLI 校验 Schema
python3 ~/.sanguo_projects/sanguo_moziplus/cli/blackboard.py comment --task task-001 --author zhangfei-dev \
  --handoff '{"completed": "分批加载实现", "artifacts": ["task-001/output.md"], "remaining": "止损逻辑分批适配"}'
# --handoff 使用 schemas/handoff.schema.json 校验
# 缺必填字段 → CLI 返回具体错误,如 "Handoff must include 'completed' field"
# 校验通过 → 自动格式化为结构化评论写入 comments 表

6. 关键场景流程

6.1 庞统规划 + Agent 领任务(事件驱动版)

用户 → 庞统(主session):"设计一个动量因子策略"
    ↓
庞统在黑板上写:
  - 创建 task-001(数据准备,pending,无依赖)
  - 创建 task-002(因子计算,pending,depends_on: [task-001])
  - 创建 task-003(回测验证,pending,depends_on: [task-002])
  - 评论:"建议赵云领 001,张飞领 002 和 003"
    ↓
庞统写 inbox 通知: task_created
    ↓
Daemon Tick 发现 task-001 pending + 庞统评论建议赵云
  → spawn 赵云(L1 消息含任务核心 + 庞统建议)
    ↓
赵云读黑板 → claim task-001 → 执行 → 写产出
  → 写 Handoff Comment: "完成:分钟线数据下载 | 产出:task-001/data/ | 无未完成事项"
  → 更新 status→done → 通知 Daemon(inbox JSONL)
    ↓
Daemon ~1s 内收到 inbox 通知 → mini-tick:
  → 查询 depends_on 包含 task-001 的 pending 任务 → task-002
  → task-002 的依赖全部满足 → spawn 张飞(L1 消息含赵云的 handoff 摘要)
    ↓
(同理 task-002 done → 即时触发 task-003)

对比 polling 版:task-001 done 到 task-002 spawn 的延迟从 ≤60s 降到 ≤1s。张飞的 L1 消息中包含赵云的 Handoff Comment,无需额外查询即可无缝接手。

6.2 Agent 间协作讨论(事件驱动版)

张飞执行 task-002 时发现需要分钟线数据
    ↓
张飞写评论:"@赵云 task-002 需要分钟线数据,能帮忙下载吗?"
张飞更新任务状态 → blocked
  → 通知 Daemon(inbox JSONL)
    ↓
Daemon ~1s 内收到 inbox 通知 → mini-tick:
  → 解析 @mention → 赵云
  → spawn 赵云(L1 消息含评论摘要)
    ↓
赵云读黑板 → 看到评论 → 下载数据 → 写产出
赵云写评论:"@张飞 数据就绪,可以继续" + 写产出
  → 通知 Daemon(inbox JSONL)
    ↓
Daemon 收到通知 → @mention → spawn 张飞
    ↓
张飞读黑板 → 看到数据就绪 → 继续 task-002

对比 polling 版:@mention 响应从 ≤60s 降到 ≤1s。

6.3 Agent 发现风险

张飞在 task-002 中发现止损逻辑有 bug
    ↓
张飞写 observation(severity: warning):
  "止损逻辑在分批模式下可能漏触发"
张飞写评论:"@关羽 止损逻辑需要你从风控角度确认"
    ↓
Daemon tick 发现 observation + 评论 @ 关羽
    ↓
Daemon spawn 关羽 → 关羽读黑板 → 审查 → 写评论 + observation

6.4 用户直接参与

用户读黑板 → 发现 task-002 进度慢
    ↓
用户在黑板上写评论:"task-002 优先级提高,需要今天完成"
    ↓
Daemon tick 发现用户评论 → 如果张飞未 active → spawn 张飞通知

7. Session 隔离与清理

7.1 技术实现

class SessionManager:
    def async_spawn_agent(self, agent_id: str, message: str) -> str:
        """异步 spawn 隔离 session,不等待完成。返回 session_id。"""
        session_id = str(uuid.uuid4())
        cmd = [
            "openclaw", "agent",
            "--agent", agent_id,
            "--session-id", session_id,
            "--message", message,
            "--json"
        ]
        # Popen 异步启动,不阻塞 daemon tick
        subprocess.Popen(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
        log_event(agent=agent_id, event_type='agent_spawned', detail={'session_id': session_id})
        return session_id

    def cleanup_session(self, agent_id: str, session_id: str, archive_dir: str):
        """存档 jsonl + 文件锁保护下清理 sessions.json"""
        sessions_dir = f"/Users/chufeng/.openclaw/agents/{agent_id}/sessions"
        store_path = f"{sessions_dir}/sessions.json"
        lock_path = f"{sessions_dir}/.cleanup.lock"

        # 1. 存档 jsonl 文件
        os.makedirs(archive_dir, exist_ok=True)
        for ext in ['.jsonl', '.trajectory.jsonl', '.trajectory-path.json']:
            src = f"{sessions_dir}/{session_id}{ext}"
            if os.path.exists(src):
                shutil.move(src, f"{archive_dir}/{session_id}{ext}")

        # 2. 文件锁保护下编辑 sessions.json(防止和 Gateway 并发写入冲突)
        with open(lock_path, 'w') as lock_file:
            fcntl.flock(lock_file, fcntl.LOCK_EX)
            try:
                with open(store_path) as f:
                    store = json.load(f)

                keys_to_remove = [k for k in store if session_id in k]
                for k in keys_to_remove:
                    del store[k]

                with open(store_path, 'w') as f:
                    json.dump(store, f, indent=2)
            finally:
                fcntl.flock(lock_file, fcntl.LOCK_UN)
                os.unlink(lock_path)

7.2 验证结论

验证项 结果
openclaw agent --session-id <uuid> 创建隔离 session 通过
连续 spawn 多个 session 互不干扰 通过
并行 spawn 成功 通过
直接编辑 sessions.json 删除记录安全 通过
jsonl 存档后从原目录删除 通过
Gateway WS sessions.delete(需 admin scope) 不可用
openclaw sessions cleanup --fix-missing --enforce 对 agent main session 报错
Agent 主 session 对 CLI spawn 的 sub 完全无感 确认(设计如此)

8. Sanguo Mail:退役

v2.6 中 Mail 完全退役。黑板的两个操作替代了 Mail 的所有功能:

Mail 功能 黑板替代
庞统分配任务 庞统在黑板创建 task + 评论 @指定 agent
Agent 间通信 评论 @mention
结果回传 产出写入 outputs 表 + 评论通知
讨论 评论线程

黑板比 Mail 更可靠:信息集中在 SQLite(不分散在 mail 目录)、有状态追踪、评论线程保持上下文完整、SQLite 读写比 Mail poller 更可靠。

如果需要系统级通知(daemon 异常、Gateway 状态),在黑板上创建 system 类型任务处理。


9. 质量门控(挑战/评审体系)

9.1 设计目标

课题1定义了"谁来判断"(双轨制)和"判断什么"must_haves三件套、Guardrail吹哨人)。课题3解决"判断结果怎么记录、怎么协商、怎么流转"。

v1.0 三层体系(PAV自律 → 司马懿review → 庞统+司马懿终审)的问题:

  1. PAV 形同虚设——Skill是"菜单"不是"触发器"Agent可忽略
  2. 每个节点都审过重——没有分级,简单/复杂任务同一个审查标准
  3. 方案阶段没审查——只审产出不审方案
  4. 评审结果不结构化——自然语言评论,无法机器判断
  5. 司马懿角色重叠——节点审一次+终审一次

9.2 分级审查流水线

参考实践superpowers 串行双审、TradingAgents 对抗辩论、v1.0 PRD 三层体系

任务风险等级 流水线 方案审查 产出审查 审查模式 最大轮次
high(部署/策略/资金) 三阶段 独立审查 独立审查 + Guardrail 对抗辩论 5
standard(编码/设计) 二阶段 方案过挑战 产出过挑战 单审 3
low(文档/格式化/搬运) 一阶段 跳过 Guardrail 自动检查 自动 0
research(调研/分析) 一阶段 跳过 庞统确认方向 单审 2

风险等级:庞统创建任务时标注。默认 standard。task_type 为 strategy/deploy 自动设 highresearch 自动设 research

9.3 三阶段审查流程

参考实践superpowersimplementer → spec reviewer → code quality reviewer串行)、TradingAgentsBull vs Bear辩论)

阶段 1:方案审查(Plan Review——high/standard 任务

执行者提交 scope_declaration 到黑板 decisions 表
    ↓
挑战者审查方案
    ├── high:对抗辩论(正方 vs 反方 → 庞统裁决)
    └── standard:单审(指定挑战者,默认司马懿)
    ↓
通过 → 进入执行
未通过 → 协商修改(max_rounds 轮)
    └── 超轮次 → 升级用户

方案审查 vs Scope Guard(课题1):

  • Scope Guard 是过程中的软检查(L2 sub 异步,发现问题写 observation
  • 方案审查是正式评审(L3 Agent 审查,通过/打回有 verdict

阶段 2:执行 + Guardrail 自动检查——所有任务

执行者按方案执行
    ↓
每次写 output 时 Daemon 自动触发 Guardrail
    ├── L1 机械检查(文件存在/JSON格式/字段非空)→ 不通过直接打回
    ├── L2 轻量 AI 检查(Schema校验/artifacts路径验证)→ 不通过写 observation
    └── L3 安全红线(tripwire:如直接操作生产环境)→ 立即中断
    ↓
Guardrail 通过 → 进入产出审查

阶段 3:产出审查(Output Review——high/standard 任务

执行者提交产出到黑板 outputs 表
    ↓
挑战者审查产出(质量/完整性/与方案一致性)
    ↓
评审结果结构化记录到 reviews 表
    ↓
通过 → status: review → done
未通过 → status: review → working(打回重做)
    └── 协商在 comments 表
    └── 超轮次 → 升级用户

9.4 审查协议注册表(Review Protocol Registry

参考实践

  • superpowers:三个独立 prompt 文件(implementer/spec-reviewer/code-quality-reviewer),每个角色有专属模板
  • oh-my-claudecode CriticInvestigation Protocol 分 Phase(预判→验证→多视角→缺口分析→自审),不同 artifact type 自动切换视角
  • superpowers spec-reviewerprompt 注入对抗性指令("DO NOT trust the report. Read the actual code."

问题:审查者容易陷入局部审查(编码规范/编译通过),漏掉本质问题(需求一致性/语义正确性)。被挑战后一律照改不加思考。

方案:审查协议是代码注入的,不是靠 Agent 自己找 Skill。Daemon spawn 审查者时动态加载协议模板。

review_protocols/
├── plan_review.yaml          # 方案审查协议
├── output_review.yaml        # 产出审查协议
├── guardrail_l2.yaml         # L2 轻量AI检查协议
└── analysis_review.yaml      # 分析/调研审查协议

每个协议定义四个维度:

维度 内容 参考
审查维度(审什么) dimensions 列表,每个有 weightcritical/major/minor)和 method superpowers 三种 reviewer 各自的关注点
审查方法(怎么审) investigation_protocol 分阶段执行 oh-my-claudecode Critic 五阶段 Protocol
多视角 按 artifact type 切换视角集 Critic 代码视角(安全/新人/运维) vs 方案视角(执行者/利益相关者/怀疑论者)
对抗性指令 adversarial_instructions 防止走过场 superpowers spec-reviewer "DO NOT trust" 指令

Investigation Protocol 通用模式(参考 Critic,各协议按场景裁剪):

Phase 1 预判(Pre-commitment):先不读产出,凭领域经验预测3-5个最可能出问题的点
Phase 2 验证(Verification):读实际产出(不是报告),逐条验证
Phase 3 多视角(Multi-perspective):从不同角色看产出
Phase 4 缺口分析(Gap Analysis):不只看"什么有问题",还看"什么缺失了"
Phase 5 自审(Self-audit):给每个 finding 打 confidence,低 confidence 降级

多视角矩阵

审查类型 多视角集合
output_review(代码) 安全 / 新人 / 运维
plan_review(方案) 执行者 / 利益相关者 / 怀疑论者
analysis_review(调研) 领域专家 / 实践者 / 反方辩手
guardrail_l2(轻量) 无多视角

9.5 反驳权(Rebuttal Phase

参考实践TradingAgents Bull vs Bear 模式——双方都有表达权

审查不是单向的。但不是每次都触发反驳——有跳过条件:

跳过条件(不需 spawn 反驳):

  • 审查者 verdict=approved → 直接 done,跳过 rebuttal
  • 审查者 verdict=needs_revision,但 issues 全是 minor severity → 执行者自然在 comments 接受并修改,不 spawn 反驳

触发条件spawn 反驳):

  • 审查者 verdict=needs_revision,且 issues 中有 critical 或 major severity → spawn 原执行者反驳
  • 审查者 verdict=rejected → spawn 原执行者反驳
审查者提交 review
    ↓
verdict=approved → 直接 done(跳过 rebuttal
verdict=needs_revision 且只有 minor → 执行者直接修改(跳过 rebuttal
verdict=needs_revision 且有 critical/major → spawn 反驳
    ↓
Daemon spawn 原执行者,注入反驳指令:
    "对每个 issue,明确表态:ACCEPT / REJECT / PARTIAL
     不允许全部接受不加思考。"
    ↓
执行者 response 写入 comments 表
    ↓
有 REJECT → Daemon spawn 审查者看 response → 继续协商
全部 ACCEPT → 修改后重提交 → 审查者 re-review

9.6 评审结果结构化存储(reviews 表)

参考实践

  • HermesComment 的 metadata JSON 承载结构化数据
  • SWE-agentTrajectory 线性追加,不修改历史
  • GitHub PR ReviewAPPROVE / REQUEST_CHANGES / COMMENT 三种 verdict

设计原则:追加写入不修改历史(SWE-agent),黑板索引+文件详情(课题2),结构化 verdictGitHub PR Review)。

CREATE TABLE IF NOT EXISTS reviews (
    id TEXT PRIMARY KEY,
    task_id TEXT NOT NULL,
    output_id TEXT,
    reviewer TEXT NOT NULL,              -- agent id 或 'system'
    review_type TEXT NOT NULL,
    CHECK (review_type IN ('plan_review', 'output_review', 'guardrail', 'final_review')),
    verdict TEXT NOT NULL,
    CHECK (verdict IN ('approved', 'rejected', 'needs_revision')),
    confidence REAL,                     -- 0.0-1.0
    round INTEGER NOT NULL DEFAULT 1,
    max_rounds INTEGER NOT NULL DEFAULT 3,
    consensus_reached BOOLEAN DEFAULT FALSE,
    summary TEXT NOT NULL,               -- 一句话结论(黑板索引)
    detail_path TEXT,                    -- 完整评审报告文件
    created_at TEXT NOT NULL DEFAULT (datetime('now')),
    FOREIGN KEY (task_id) REFERENCES tasks(id),
    FOREIGN KEY (output_id) REFERENCES outputs(id)
);

CREATE INDEX IF NOT EXISTS idx_reviews_task ON reviews(task_id);
CREATE INDEX IF NOT EXISTS idx_reviews_output ON reviews(output_id);

Guardrail 检查结果也入 reviews 表reviewer='system', review_type='guardrail')。

comments 表和 reviews 表职责分离

职责 内容 verdict
comments 讨论、@mention、协商过程 自然语言
reviews 正式评审结论 结构化 JSON 必须有

9.7 协商流程与状态机对齐(v2.8 更新)

现有状态机(v2.811个状态)pending → claimed → working → review → done

状态转换 触发条件 对应阶段
working → working 方案审查 needs_revision 阶段 1
working → review 写 output + Guardrail 通过 阶段 2→3
working → working Guardrail rejected(自动打回) 阶段 2
working → escalated Agent 遇到无法处理的问题 任意阶段
working → waiting_human Agent 触发 Checkpoint 任意阶段
review → done 产出审查 approved 阶段 3
review → working 产出审查 needs_revision 阶段 3
review → escalated 超轮次升级用户 阶段 3
review → waiting_human 审查阶段需人工裁定 阶段 3
waiting_human → working Checkpoint reject(驳回) 阶段 3
waiting_human → done verify Checkpoint approve(通过) 阶段 3

v2.8 变更: escalated 从布尔标志改为独立状态(status="escalated"),不再使用 review + escalated flag 模式。超轮次时直接进入 escalated 状态,通知用户裁定。用户裁定后恢复到 workingpending

low 风险任务:working → [Guardrail 自动检查] → done(跳过 review 状态) research 任务:working → [庞统确认] → review → done

9.8 声明式 Guardrail 配置

参考实践OpenAI Agent SDK @output_guardrail 装饰器、v1.0 M4 Guard、SonarQube rule_id 模式

# guardrails.yaml
#
# L1 check 用 assert 字段(Python 表达式,Daemon eval 执行)
# L2 check 用 prompt 字段(传给 subagent 的检查指令)
# 两者本质不同,不用同一个字段

task_types:
  coding:
    output_guardrails:
      - name: file_exists
        assert: "len(output.get('files', [])) > 0"
        severity: blocking
        layer: L1
      - name: json_valid
        assert: "output.get('json_schema_valid', False) == True"
        severity: blocking
        layer: L1
      - name: artifacts_exist
        assert: "all(os.path.exists(p) for p in output.get('artifacts_paths', []))"
        severity: blocking
        layer: L1
      - name: scope_alignment
        prompt: "Compare the agent's scope_declaration against task truths. Check: is every truth covered? Are there deviations not declared?"
        severity: warning
        layer: L2
    output_review:
      required: true
      mode: single_reviewer
      max_rounds: 3

  deploy:
    plan_review:
      required: true
      mode: debate
      max_rounds: 5
    output_guardrails:
      - name: no_direct_production
        assert: "output.get('target_env') != 'production'"
        severity: tripwire
        layer: L1
      - name: rollback_plan_exists
        assert: "output.get('rollback_plan') is not None"
        severity: blocking
        layer: L1
    output_review:
      required: true
      mode: debate
      max_rounds: 5

  data:
    output_guardrails:
      - name: format_check
        assert: "output.get('format') in ['csv', 'parquet', 'json']"
        severity: blocking
        layer: L1
    output_review:
      required: false

  research:
    output_review:
      required: true
      reviewer: "pangtong-fujunshi"
      mode: single_reviewer
      max_rounds: 2

9.9 Full Agent vs Subagent vs Daemon 直接执行

参考实践

  • superpowersImplementer/Spec Reviewer/Code Quality Reviewer 都是 Task tool dispatch 的 subagent,各自独立 prompt 和模型
  • oh-my-claudecodeCritic 被禁止 Write/Edit 工具(disallowedTools),角色隔离
  • open-multi-agentTaskQueue 维护 agent poolscheduler 按 capability-match 分配

判据

问题 Full Agent Subagent Daemon 直接执行
需要独立身份/人格?
需要 Agent 专属工具? 通用工具 不需要 AI
任务复杂度 编码/审查/调研/决策 单一检查/快速评估 格式校验/文件检查
需要写黑板? 只返回 pass/fail 只改状态
需要多轮交互? 一次性 一次性

场景映射

场景 方式 OpenClaw API 理由
执行者编码/数据/部署 Full Agent openclaw agent --agent <id> 需要身份+专属工具
挑战者审查 Full Agent openclaw agent --agent simayi-challenger 需要质量守门人角色+多轮
执行者反驳 Full Agent(原 Agent openclaw agent --agent <原执行者> 需要原执行者身份
庞统规划/裁决 Full Agent(隔离session openclaw agent --agent pangtong-fujunshi --session-id <new> 避免主session上下文膨胀
L2 Guardrail AI 检查 Subagent sessions_spawn(task=...) 单一检查、无身份
Scope Guard 异步检查 Subagent sessions_spawn(task=...) 轻量一次性
L1 机械校验 不走 AI Daemon 直接执行 纯机械操作

简化规则:黑板上有名字的角色走 Full Agent。无名字的一次性检查走 Subagent。纯机械检查 Daemon 自己做。

庞统主 session 隔离策略:主 session 做轻量调度(L1构建、状态检查)。复杂的任务拆解和裁决 spawn 隔离 session,避免上下文膨胀。

9.10 对抗辩论模式(high 风险任务)

参考实践TradingAgents Bull vs Bear → Research Manager 裁决

正方(执行者):scope_declaration,论证方案可行性
反方(挑战者池):找方案漏洞、风险、遗漏
    ↓
庞统裁决:综合双方观点
    ├── 认可正方 → 方案通过
    ├── 认可反方 → 方案打回
    └── 综合意见 → 要求修改后重新辩论

挑战者池(按任务类型选择,不是固定司马懿):

任务类型 默认挑战者
编码 司马懿
风控 关羽
数据 赵云(数据质量视角)
部署 姜维

10. 产出物目录约定

~/.sanguo_projects/sanguo_moziplus/artifacts/
└── {task-id}/
    ├── outputs/          # Agent 产出物(代码、文档、数据)
    ├── archive/          # session jsonl 存档
    └── data/             # 数据文件

Agent 写产出时,content_path 指向此目录。Daemon 存档 session jsonl 时也写入 archive/ 子目录。


11. 保留 v2.0 的设计

以下 v2.0 的设计在 v2.6 中保留:

  1. SQLite WAL 模式 - 黑板数据库同样使用 WAL
  2. 结构化产出规范 - output.md frontmatter + 结论 JSON(写在黑板 outputs 表中)
  3. 观察机制 - v2.0 Report Watcher 的思路升级为 observations 表
  4. 证据原则 - 结论必须有证据(代码行号、日志、文件内容)
  5. 审核流程 - 可通过黑板评论 + 状态机实现

11. 上下文管理策略(课题10结论)

核心结论:不需要复杂的压缩/摘要机制。课题2+4的设计已覆盖上下文管理的主要场景。

11.1 黑板信息量测算

信息类型 单个任务估算
任务基础信息(tasks 表) ~50-60 tokens
10 条评论(comments 表) ~300-500 tokens
5 个产出摘要(outputs 表) ~150-250 tokens
10 条事件日志(events 表) ~150-250 tokens
3 条决策记录(decisions 表) ~150-200 tokens
单个任务全量 ~1000-1500 tokens

即使 10 个任务全量注入也仅 ~1-1.5 万 tokens,远小于 128K context window。

11.2 三个场景的结论

场景1:续杯时上下文膨胀

已在课题2+4中解决:

  • 黑板保留完整讨论链(comments/decisions/observations),新 Agent 随时可读
  • 课题4 D4-7 三段式注入:操作规范 + 任务上下文 + 前序信息(depends_on 产出)
  • 比 GSD Wave Execution 更优——GSD 给每个 executor 全新 context 但丢弃思考过程,我们保留在黑板中

场景2:多任务并行

所有优秀实践的共识:单黑板、单 Daemon、多任务并行调度。

  • open-multi-agent:一个 TaskQueue,事件驱动,无依赖任务自然并行
  • Hermes:一个 Dispatcher + 一个 SQLite60s tick 扫描
  • GSD:一个 orchestrator,同 wave 并行,跨 wave 串行

moziplus 同此模式:一个 SQLite 黑板、一个 Daemon 进程、Tick 扫描可推进的任务并行 spawn。 每个 Agent spawn 时只注入自己任务的信息(课题4 D4-7 按角色注入),不受其他任务干扰。

⚠️ 待解决:用户级多任务(跨项目/跨域)需要项目级隔离机制,与课题11一起设计。

场景3Agent 自主决定读 L3

在 L2 bootstrap 末尾注入"可选参考"提示(课题4 D4-11 已在示例中体现):

═══ 可选参考 ═══
根据任务需要,你可以用 read 加载以下 Skill
- 编码:~/.openclaw/skills/coding-implementation/SKILL.md
- 回测:~/.openclaw/skills/quant-backtest/SKILL.md
只在需要时加载,不需要全部读取。

未来增强:SkillRouter 检索 + OpenClaw 动态关键词触发(见课题12 SkillRouter 调研)。

11.3 Context 预算分配

组件 预算 说明
System Prompt + SOUL.md + IDENTITY.md ~3000-5000 固定开销(L0+L1
L2 引擎注入(操作规范 + 任务上下文) ~1000-2000 每次 spawn 强制注入
L2 历史经验提醒 ~150 最多 3 条 experience
L3 可选参考 ~100 Skill 列表提示
工作空间(Agent 思考+输出) ~30000-50000 预留给 Agent
总计 ~35K-60K 远小于 128K,安全

11.4 设计原则

  1. 黑板是索引(做什么 + 在哪找),不是仓库(详细内容)
  2. 产出物在文件中,黑板只存路径
  3. Agent spawn 时传最小充分上下文(L2),按需获取更多(L3)
  4. 不做复杂压缩——信息量本身就很小

12. 开发策略(v2.6)

核心原则:不分阶段,不妥协,直奔 AI Native。 每个部分设计到清楚为止。

12.1 设计推进方式

按课题逐个推进。课题之间允许并行,不强求串行。每个课题设计清楚就定稿。

已完成设计的课题

  • 课题1:三层执行模型(v2.6.2
  • 课题2:事件驱动 + Inbox JSONLv2.6.3
  • 课题3:挑战/评审体系(v2.6.4)
  • 课题4:拆解 + 上下文架构(v2.6.5)
  • 课题6:经验沉淀闭环(v2.6.7
  • 课题7+9:交互模式 + Dashboardv2.6.6 → 方案文档 v2.6.11
  • 课题11:多项目支持(v2.6.10)

待推进课题

课题 内容 方向 状态
课题7 AI Native 人机交互 4种交互模式+推送4级+信息3层+双入口对等+Checkpoint交互+AI Briefing 📐 方案完成
课题9 Dashboard 设计 v1.0已有11个Tab全部保留,任务看板重设计,SSE实时推送,新增AI Briefing Tab 📐 方案完成
课题10 上下文管理 ⏸️ 暂缓
课题11 用户级多项目 方案C:单Daemon多数据库 + per-project线程并发 + 全局LLM信号量 + per-agent互斥锁(借鉴open-multi-agent AgentPool 📐 方案完成(v2
节点级模型策略 Aider architect/editor/weak 三层分工 审查节点用强模型、执行节点用快模型,成本与质量平衡 P2
信任分级系统 DeepSeek-TUI Plan/Agent/YOLO 三级 Dashboard 按信任等级展示不同操作按钮 P2
Worktree 项目隔离 Superset + Claude Squad 同项目内多Agent并行改代码的物理隔离 P1
Blackboard Map Aider Repo Map 黑板结构化索引,Agent按任务ID只读关联子图,不全量读取 P3(触发条件:单任务>5K tokens 或并行>15任务)
工具链集成 PRD C10 DevOps工具链(代码管理/CI/CD/测试/沙箱/运维)集成到v2.0 📋 信息收集(docs/design/toolchain-proposal.md

司马懿 v2.6.9 评审结论与回应

评分: 55/70。最高:上下文管理 9/10。最低:自主协作能力 + 异常自愈 7/10。

3 个评审意见的回应

# 司马懿意见 回应 处理
1 PRD §2.1 B3"共享意识"与架构有差距,改PRD对齐 PRD 目标正确不改。当前架构已基本实现共享意识(黑板+CLI读写+@mention+Handoff),唯一差距是 L2 prompt 需要告诉 Agent"你可以查全局" 在 §15.1 借鉴4 的 prompt_template 中加入全局查询提示
2 blocked 状态转换图不完整 + mentions/experience_tags 风格不统一 blocked 定义完整(§3.3 转换矩阵含 blocked,§6.2 场景清晰:Agent执行中被卡→blocked→他人帮忙→pending)。mentions 做通知路由(轻查询),experience_tags 做统计分析(重查询),场景不同不需要统一格式 不修改
3 verification_commands 安全性 Agent 已有 exec 权限,verification_commands 走 Daemon exec,由 OpenClaw exec approvals 机制(allowlist+approval)保障安全,不引入新攻击面。参考:Claude Code 同模型、Aider 直接信任、NVIDIA 深度防御指南 在 §15.1 借鉴1 明确安全模型

采纳的改进建议

  • Daemon 逻辑健康自检(连续 N tick 无变更则告警)→ 纳入 §14 风险缓解
  • PRD 与架构对齐描述 → 在架构文档中记录当前状态而非修改 PRD
  • 📋 多项目 scope → 课题11 设计
  • 📋 AI Retry 基本版 → Phase 1 考虑
  • 📋 SkillRouter → 课题12

已完成调研

  • 7 个新项目调研(Claude Squad / Superset Terminal / OpenCode / claude-goal / Cline / Aider / DeepSeek-TUI
    • 综合报告:docs/research/research-seven-projects-synthesis.md
    • 详细报告:docs/research/research-batch{1,2,3}-*.md

12.2 开发启动条件

所有核心课题设计完成后启动开发。开发顺序由设计依赖关系决定,不由阶段划分决定。

12.3 核心依赖链(设计 → 开发)

黑板基础设施(SQLite + CLI + Daemon
  → 事件驱动(Inbox + 依赖推进)
    → Agent 交互(Handoff + 评论 + Observation
      → 审查体系(Review + Guardrail + 反驳)
        → 智能化(AI规划 + 自主领活 + 经验沉淀)
          → Dashboard 前端

每层依赖前一层,但不等所有层设计完才开发。前层设计清楚即可开发。


13. 技术选型

需求 参考系统 我们的方案 理由
共享状态 Hermes SQLite + Network-AI flock SQLite WAL + 事务 CAS 原子性 + 无外部依赖
讨论 Hermes kanban_comment comments 表 + @mention 简单追加写入,所有人可见
事件驱动 open-multi-agent EventEmitter + agent-chorus JSONL inbox Tick 核心 + Inbox JSONL 加速 + 启动全量扫描 Tick 兜底可靠,inbox 加速即时响应,零新依赖
调度 Hermes Dispatcher 60s tick Tick 30s + Inbox JSONL 加速 + 启动全量扫描 Tick 可靠 + inbox 即时
上下文传递 GSD Wave Execution + Claude Code file ref + Opal-Bridge Fidelity L1 必传 + L2/L3 按需读取 + Handoff Comment 信号噪声比优化 + 无缝接手
通知 Claude Code idle notification Daemon spawn + L1 message OpenClaw 原生能力
通信 Hermes kanban_comment + Claude Code inbox 黑板 comments + @mention 替代 Sanguo Mail
竞态 Network-AI propose→validate→commit SQLite CAS(first-commit-wins) SQLite 事务足够
Session Hermes process-per-worker openclaw agent --session-id OpenClaw 原生隔离
清理 无参考 编辑 sessions.json 已验证可行

14. 风险和缓解

风险 概率 缓解
Agent 上下文不足(隔离 session 没有历史) spawn 时传递黑板关键信息 + agent 可主动读黑板
Daemon 单点故障 PM2 自动重启 + tick 无状态
SQLite 并发写入 WAL + busy_timeout + BEGIN IMMEDIATE
黑板膨胀(大量评论/产出) 定期 archive + agent 只读最近 N 条
Agent 不知道该做什么 Skill 指导 + 庞统 plan 评论 + daemon 消息含上下文
Sanguo Mail 退役后的系统通知 黑板 system 类型任务替代
Daemon 逻辑死循环 Daemon 逻辑健康自检:连续 N tick(默认 20)无任何任务状态变更则写 observation 告警 + 通知用户。PM2 只能检测进程崩溃,逻辑死循环需应用层检测

15. 7项目调研结论与设计借鉴

调研日期: 2026-05-16 调研范围: Claude Squad / Superset Terminal / OpenCode / claude-goal / Cline / Aider / DeepSeek-TUI 详细报告: docs/research/research-seven-projects-synthesis.md

15.1 已纳入设计的借鉴点

借鉴1:Guardrail 验证脚本层(纳入课题3)

来源: Aider lint→test→commit 质量闭环

当前设计topic3 方案 阶段2):

L1 机械检查(文件存在、JSON格式)→ 不通过直接打回
L2 轻量 AI 检查(Schema校验)→ 不通过写 observation
L3 安全红线(tripwire)→ 立即中断

增强后L1 增加验证脚本层

L1 机械检查 + 验证脚本
  ├── 文件存在性检查(原有)
  ├── JSON 格式检查(原有)
  └── 🆕 verification_commands 执行(新增)
      ├── 任务 Plan 中声明的验证命令(如 pytest, flake8, mypy
      ├── 命令 exit 0 = 通过,非 0 = 打回
      └── stdout/stderr 附在打回原因中

黑板 Schema 变更tasks 表新增 verification_commands JSON 字段

{
  "verification_commands": [
    {"cmd": "pytest tests/test_foo.py -x", "description": "单元测试必须通过"},
    {"cmd": "flake8 src/", "description": "代码规范检查"}
  ]
}

触发时机Daemon 检测到 output 写入 → 执行 Guardrail → L1 验证脚本 → 脚本失败则自动打回。

安全模型verification_commands 通过 Daemon 调用 exec,走 OpenClaw exec approvals 机制(allowlist + approval)。Agent 已有 exec 权限,verification_commands 不引入新的攻击面。参考:Claude Code 同模型(Agent 可执行命令,宿主机 exec approvals 拦截危险操作)、Aider 直接信任、NVIDIA 深度防御指南。

参考实践:Aider 的 lint→test→commit 是原子操作——验证不通过就不 commit。我们的 Guardrail 也是原子门控——验证不通过就不进入 review。

借鉴2:对抗性审计映射(纳入课题3

来源: claude-goal 三种审计模式(none/adversarial/double

映射到 Guardrail L1/L2/L3

claude-goal 模式 moziplus Guardrail 触发条件 行为
none(跳过审计) L1 only(机械+脚本) low 风险任务 自动检查通过即完成
adversarial(对抗审计) L1 + L2AI审查) standard 风险任务 一轮 AI 审查,通过/打回
double(双重审计) L1 + L2 + 反驳权 high 风险任务 双轮审查 + 执行者可反驳 + 最多5轮

claude-goal 的完成审计 6 步流程(还原交付物→对照表→检查证据→找缺失→继续/完成)对 Output Guard 的 AI 审查层有参考价值,但不硬编码步骤——AI 审查者按 Skill 指导灵活执行。

借鉴3:防偏离改进(纳入课题3+4

来源: claude-goal Stop Hook + 完成审计

v2.0 的防偏离三层防线

防线 claude-goal 机制 moziplus v2.0 对应 实现方式
每轮重新注入目标 Stop Hook 注入 <objective> L2 引擎注入任务上下文 Daemon spawn 时注入 truths + acceptance_criteria
不信任 Agent 自述 完成审计 6 步(查证据) Output Guard + Scope Guard L1 验证脚本 + L2 AI 审查(prompt→artifact 对照)
Runaway Guard 500 次续杯上限 当前缺失 新增:每个任务最大 tick 上限(配置项 max_ticks,默认 100

新增设计tasks 表增加 max_ticks 字段(默认 100)。Daemon 每次 tick 处理某任务时递增 tick_count,超过 max_ticks 时:

  1. 自动暂停任务
  2. 写入 system observation:“任务超过最大 tick 上限,可能陷入循环”
  3. 通知用户决定继续/取消

借鉴4:双重 Hook 机制(纳入 Daemon 设计)

来源: claude-goal 的 Claude Code Stop Hook + mozi v1 的 HookRegistry

v2.0 双重 Hook 架构

┌─────────────────────────────────────────┐
│ Layer 1: OpenClaw Hook(系统级)          │
│ • Heartbeat(定时轮询,读 HEARTBEAT.md │
│ • WebhookHTTP 入口,外部事件触发)      │
│ • Cron(定时任务)                        │
│ → 触发 Agent session 内行为              │
└─────────────────────────────────────────┘
         ↓ 事件到达
┌─────────────────────────────────────────┐
│ Layer 2: moziplus Hook(编排级)         │
│ • NODE_AFTER_EXECUTE → 触发 Guardrail    │
│ • NODE_ON_SUCCESS → 触发经验沉淀          │
│ • TASK_AFTER_COMPLETE → 触发 Scope Guard │
│ • CONCLUSION_AFTER_PARSE → 写入黑板      │
│ → 触发编排层业务逻辑                     │
└─────────────────────────────────────────┘

mozi v1 已有 HookRegistry(20 个 hook 点,覆盖任务/节点/结论/路由全生命周期),v2.0 继承并精简:

  • v1 的 HookPoint 枚举 → v2 的 Daemon event handler
  • v1 的 priority + stop_propagation → v2 保留(Hook 链可控)
  • v1 的两级失败隔离(关键型暂停/辅助型跳过)→ v2 保留
  • 新增:Guardrail 验证脚本作为 NODE_AFTER_EXECUTE 的默认 Hook

与 claude-goal 的对比

维度 claude-goal moziplus v2.0
Hook 注册位置 Claude Code settings.json Daemon HookRegistry
Hook 触发点 Agent Stop 事件 节点完成/任务完成/产出写入
Hook 实现 Python 脚本 Daemon event handler + 可插拔 Hook
防偏离手段 拦截停止+注入目标 L2注入上下文+Guardrail验证+Runaway Guard

借鉴5Shadow Checkpoint(纳入课题6 经验沉淀)

来源: Cline Shadow Git Checkpoint

设计:每次 Agent 产出写入黑板时,Daemon 自动对产出目录做 git commit(带 agent_id + task_id + timestamp tag)。

  • 与课题4的关系:不依赖课题4。Shadow Checkpoint 是 Daemon 层行为(产出写入后触发),课题4是 Agent spawn 时的上下文注入。两者独立。
  • 与课题6的关系Shadow Checkpoint 的变更历史是经验蒸馏的输入(课题6 DISCOVER 阶段可以 diff 两个 checkpoint 看Agent改了什么)
  • 回滚能力:用户可以在 Dashboard 上选择任意 checkpoint 一键回滚
  • 存储开销:git commit 增量存储,开销可控

实现:在 NODE_AFTER_EXECUTE Hook 中增加 git checkpoint 逻辑。

15.2 经评估暂不纳入的借鉴点

Blackboard Map(按需触发,不预设)

来源: Aider Repo Map

结论:当前单个任务黑板信息 ~1000-1500 tokens(§11.1 测算),10 个任务全量注入 ~1-1.5 万 tokens,远小于 128K。现阶段不需要 Blackboard Map

触发条件(达到以下任一时启动设计):

  • 单个任务黑板信息超过 5000 tokens
  • 并行任务数超过 15 个
  • Agent spawn 时注入上下文超过 10K tokens
  • 或者 L2 注入需要做精准裁剪(只取关联子图而非全量)

预留设计:当需要时,基于黑板 comments/outputs/decisions 的拓扑关系构建图索引,Agent 按任务 ID 只读关联子图。

15.3 技术选型更新

需求 原参考 新增参考 我们的方案
质量门控 Hermes 幻觉门控 Aider lint→test→commit L1 机械+脚本 → L2 AI → L3 红线
防偏离 claude-goal Stop Hook + 完成审计 L2 注入 + Guardrail + Runaway Guard
产出追溯 Cline Shadow Git NODE_AFTER_EXECUTE Hook 自动 git commit
Hook 机制 mozi v1 HookRegistry claude-goal Stop Hook + OpenClaw Heartbeat/Webhook 双重 Hook(系统级+编排级)
多项目隔离 Superset Worktree 课题11 中设计(Worktree 物理隔离)