Files
writing-agent/docs/tag-blackboard.md
2026-07-10 08:31:27 +08:00

16 KiB
Raw Blame History

标签驱动黑板

1. 定位

本系统用于多 worker 协作式文本生成,覆盖:

简易小说快速撰写quick-write
规则怪谈 / 短篇结构化创作weird-rules-short 等)
长篇小说 / 交互式写作助手interactive-novelTODO
场景扮演模拟scene-roleplayTODO
角色扮演 / 角色卡互动(并入 scene-roleplay 的 instantiate + run见 §2

核心思想:

黑板 = 标签化数据池
标签 = skill 之间的接口
skill = SKILL.md 定义的能力worker = 一次 invoke
Agent = tool loop 内调度 invoke 哪个 skill
Runtime = 按 skill 契约拼接上下文(上半固定、下半动态)

一句话:标签驱动 + agent 选 skill + Runtime 拼上下文——不是固定流水线,也不是 LLM 自由分发上下文。

上下文拼接见 docs/context-assembly.md。不要让 agent 临场改 inputTags分发由 inputTags + contextSegments 静态声明。


2. Skill 定义、实例化与 Book

2.1 类比

Skill 包orchestrator manifest + workers  = 能力定义(静态)
Session + 黑板 tag                           = 一次运行的实参
Book                                         = 过程、资产、游玩(见 book-storage.md
play stage                                   = agent invoke run skill

写角色卡、收集设定、启动询问 都不是独立「产品模式」,而是 实例化阶段 的不同形态:把 prerequisite tags 写满,然后才进入运行阶段。

2.2 三层阶段(勿混淆)

运行相位RuntimePhase
  idle | running | waiting_user | done | error
  系统在等什么。见 runtime-state-machine.md

业务 stageBook / Session
  design实例化→ play运行→ done

tag 阶段(黑板条目 tag 名中的段)
  候选 | 草稿 | 确认稿 | 当前 | 更新
  单条数据的 lifecycle

业务 stage 写在各 skill 的 orchestrator.md,不扩运行相位 enum。

2.3 实例化design

职责: agent 按需 invoke instantiate skill沉淀 设计.* tag产出 设计.run_skill清单 后 declare ready。

选 orchestrator 包
  → design stage启动询问 → agent invoke instantiate skill能力库
  → declare_instance_ready
  → play stageagent invoke run skill
  → done → 归档 Book过程 + 资产,见 book-storage.md

可从 Book / CardAsset 加载已有 tag跳过部分 instantiate skill。

运行相位上,实例化阶段多为 waiting_user(input)(启动询问、总管 ask_user实例化也可调用 setup worker,但仍是 worker固定 inputTags/outputTags不是第二个生产总管。

2.4 每个 skill 声明什么

在 orchestrator.md 中写清(见 orchestrator-skill-format.md

## 启动询问 / ## 实例化
  prerequisiteTags本 skill 运行前必须有的 tag
  instanceReadyWhen何时可进入 run stage文字条件 + tag 列表)
  写入目标 tag可多个不必再塞进单一 book.brief

## 阶段定义
  instantiate或沿用 stageId brief→ runwrite / review …)→ done

## Worker 编排
  仅 run stage 及之后调度生产 workerinstantiate 阶段只 ask_user 或 run setup worker

2.5 已有雏形weird-rules-short

业务 stage 现 stageId 含义
实例化 brief 启动询问 → book.brief(≈ 需求.核心要点)→ startupCompleted
运行 write write-rules 产出规则与 core
运行 review 双验收 worker
结束 done finish

basic 同理:brief = 实例化,outline worker = 运行。
文档与实现迁移时,可将 stageId 改名为 instantiate,或保留 brief 但在 ## 阶段定义 注明 brief ≡ instantiate

2.6 角色卡

不再单独维护 character-card-author skill 包。角色设定、口吻、行为边界等 tag 在 扮演类 skill 的 instantiate 段 收集或生成(可选 setup worker
若需跨 Session 复用,将 角色.A.设定角色卡.确认稿确认稿 存入 Book新 Session 加载 Book 而非再跑完整实例化。

2.7 Book 与黑板

黑板Session 内)   运行时 tag 池worker 读写
Book项目级       长期实例accepted 确认稿归档;下一场 Session 可加载

详见 docs/book-storage.md。Session 是一次运行Book 是一个创作项目(一本小说、一个扮演项目)。


3. 黑板条目

2.1 最小结构

type BlackboardItem = {
  id: string;
  tag: string;
  content: string;
  source: string;
  metadata?: Record<string, unknown>;
};

2.2 可选增强

type BlackboardItem = {
  id: string;
  tag: string;
  content: string;
  source: string;
  scope?: string;
  createdAt?: number;
  updatedAt?: number;
  dependencies?: string[];
  metadata?: Record<string, unknown>;
};

2.3 字段含义

id           唯一标识,追踪与依赖
tag          标签本体,决定身份与消费路径(核心)
content      具体内容(字符串)
source       产生该条目的 worker id调试用
scope        作用范围,如当前章节、场景、项目(可选)
dependencies 依赖的其他黑板条目 id可选
metadata     置信度、真实性、控制模式等(不参与基础路由)

注意:

tag 是核心路由依据。
source 不是路由依据,只用于调试与溯源。
metadata 不参与基础路由,除非某 skill 明确约定。

已废弃: 旧模型的 keysummarytags[]readableBywritableBy 作为路由字段。迁移期代码可能仍保留 BlackboardEntry,以本文为准逐步替换。


4. 标签原则

标签不是信息分类学,而是 工作流接口

3.1 设计原则

标签越少越好,但必须能区分不同消费路径。
两个信息若永远被同一批 worker 消费,可合并 tag。
若在不同阶段被不同 worker 消费,必须拆分 tag。
若可能被误当成事实,必须加阶段段。
若涉及角色私有认知tag 里必须体现角色归属。

3.2 推荐格式

对象.内容
对象.内容.阶段
领域.对象.内容.阶段

不强制四段式;按复杂度逐级增加。

示例:

大纲.草稿
事件.草稿
正文.草稿
正文.确认稿

角色.A.行动.候选
角色.A.台词.候选
角色.A.内心想法.候选
角色.A.记忆.当前

3.3 标签替代的旧字段

角色.A.内心想法.候选

已表达:归属 A、类型为内心想法、阶段为候选、消费路径由声明 inputTags 的 worker 决定。

不需要 再写 ownervisibleTotype=action 等平行字段。

3.4 匹配规则Runtime

Worker frontmatter 声明 inputTags

inputTags:
  - "需求.核心要点"      # 精确匹配
  - "角色.A.*"          # 前缀匹配tag 以「角色.A.」开头
  - "大纲.*.草稿"       # 前缀匹配

规则:

无通配 → 精确匹配 tag
以 .* 结尾 → 前缀匹配(实现优先于完整正则)
多条命中 → 默认按 updatedAt 取最新;或 worker 声明 inputMerge: concat | latest

总管调度时也可对 tag 索引(不含 content做存在性判断例如「是否有 规则.确认稿」。


5. 阶段标签

阶段表示同一类信息在不同生命周期下的语义。

候选     worker 生成的可能内容,不等于事实
草稿     生成中的文本或结构
确认稿   用户或流程确认,可进入长期状态
当前     当前生效状态
更新     状态变化结果

重要规则:

候选 ≠ 已发生。
草稿 ≠ 确认稿。
角色行动候选不能直接写入长期记忆。
长期记忆优先从正文.确认稿 与明确 记忆.更新 生成。

验收(user_confirmed / programmatic_review通过后Runtime 将对应产物 tag 从 .草稿 升级为 .确认稿(或写入新的确认稿条目并标记旧草稿 superseded


6. Worker

每个 worker 是固定的标签消费者和生产者。

5.1 类型

type WorkerDefinition = {
  id: string;
  name: string;
  description: string;
  inputTags: string[];
  outputTags: string[];
  inputMerge?: "latest" | "concat";
  run: (context: WorkerContext) => Promise<WorkerResult>;
};

type WorkerContext = {
  taskId: string;
  workerId: string;
  items: BlackboardItem[];
  params?: Record<string, unknown>;
};

type WorkerResult = {
  items: BlackboardItem[];
  logs?: string[];
  askUser?: string[];
};

5.2 规则

worker 只能读取 inputTags 声明的标签(含前缀规则)。
worker 只能输出 outputTags 声明的标签。
worker 不读取全量黑板。
LLM 不决定自己能看什么。
Runtime 校验 outputs 的 tag  ⊆ outputTags。

5.3 Worker Skill 落盘

docs/worker-skill-format.md。正文写「怎么做」;inputTags / outputTags 写在 frontmatter。

5.4 ask_user

提问是 worker 能力,不是独立 worker。中途提问时 resumeContext 保存 workerId保存 inputTags恢复时仍从 Worker Skill 读 inputTags


7. 总管Main Agent

总管只负责流程推进。

6.1 职责

判断当前任务属于哪种 skill / 业务阶段
选择下一个 workerrun_worker
判断是否需要追问用户ask_user
判断是否需要用户确认下一步requiresApproval
判断是否 finish

6.2 不负责

不决定某条信息给谁看
不手动拼接 worker 上下文
不让 LLM 判断信息权限
不把全量黑板交给 worker
不在 run_worker 里指定 inputTags / outputTags

6.3 决策结构

type MainAgentDecision = {
  id: string;
  action: "ask_user" | "run_worker" | "create_temp_worker" | "review_blackboard" | "finish";
  reason: string;
  workerId?: string;
  requiresApproval: boolean;
  statePatchAllowed: false;
};

执行链:

总管选择 worker
→ Runtime 读取该 worker 的 inputTags
→ 从黑板取匹配条目,组装 WorkerContext
→ 调用 worker
→ worker 输出固定 outputTags
→ 写回黑板
→ 按 acceptanceMode 验收

Tool 合约见 docs/tool-contracts.md


8. Skill 包与 manifest

Skill 包 = orchestrator.mdmanifest+ workers/*/SKILL.md。详见 orchestrator-skill-format.md

manifest 包含:

Skill 注册表instantiate + run
验收策略
Instance Ready 规则

不写 逐步编排表。inputTags / contextSegments 在 Worker SKILL.md。

8.1 已启用包

说明
novel/basic 演示:需求 → 大纲
novel/weird-rules-short 规则怪谈:写 + 双验收

8.2 规划包(见 skills/README.md

说明
novel/quick-write 简易档:几乎无 tag 路由,上下文全量给 LLM
novel/interactive-novel 长篇 / 写作助手instantiate + 多轮 run
novel/novel-standard 标准流水线(或与 interactive 合并)
dialogue/scene-roleplay 场景扮演(含角色设定 instantiate + 互动 run

9. 各模式核心 tag参考

实现 skill 时从下列词汇出发,不必一次全部实现。

8.1 简易小说quick-write

极简;可大量依赖 session + 全量上下文tag 仅作交付锚点:

用户.输入
需求.摘要
正文.草稿
正文.确认稿

8.2 结构化短篇(如 weird-rules-short

迁移目标示例(与现 key 对照实施):

需求.核心要点        ← book.brief
核心.危险.隐藏       ← core.danger
规则.草稿            ← rules.draft
规则.说明.草稿       ← rules.commentary
验收.读者视角.记录   ← review.infer.notes
验收.作者视角.记录   ← review.author.notes

8.3 交互式长篇

用户.原始输入 | 用户.意图转述 | 用户.确认结果
项目.设定 | 项目.风格要求
大纲.当前 | 大纲.候选修改 | 大纲.确认稿
事件.当前 | 事件.确认稿
正文.原文 | 正文.续写锚点 | 正文.草稿 | 正文.确认稿
记忆.长期摘要 | 记忆.确认稿

8.4 场景扮演

用户.行动输入 | 用户.行动意图
世界.规则 | 世界.当前状态 | 世界.隐藏状态
场景.可见信息 | 场景.隐藏信息
角色.{id}.记忆 | 信念 | 行动.候选 | 台词.候选
行动.裁决结果
输出.场景反馈
更新.世界状态 | 更新.角色状态

8.5 角色卡

撰写:角色卡.草稿角色卡.确认稿
游玩:读 角色卡.确认稿 + 用户.控制模式 + NPC.*


10. 正文 worker 与角色候选

角色 worker 输出 角色.*.台词.候选 等,直接进入正文事实。

正文 worker 读取候选 + 风格约束,输出 正文.草稿;用户确认后为 正文.确认稿

角色候选 → 提供意图
正文 worker → 文本化、风格化、叙事化
正文.确认稿 → 最终发生与表达

11. 可选增强

10.1 采用记录

tag: 采用.记录

记录正文采用了哪些候选条目,避免未采用候选污染记忆。早期可省略,记忆 worker 只从 正文.确认稿 抽取。

10.2 真实性 / 置信度metadata

type TruthMode =
  | "truth" | "belief" | "claim" | "lie" | "rumor" | "plan" | "unknown";

不参与基础路由。

10.3 RAG

RAG 不替代黑板。检索结果也应写成 tag例如 角色.A.相关记忆摘要,由 worker 通过 inputTags 读取。


12. 与阶段机的关系

运行相位、业务 stage、tag 阶段 三者正交(详见 §2.2

运行相位     系统在等什么(见 runtime-state-machine.md
业务 stage   instantiate → run → doneorchestrator.mdbrief 即 instantiate
tag 阶段     黑板条目 lifecycle候选 / 草稿 / 确认稿)

实例化阶段在运行相位上通常体现为 waiting_user(input);进入 run stage 后为 running + worker 验收循环。
阶段机 enum 不增加 instantiate 相位——业务 stage 由 orchestrator + tag 索引判断。

阶段机规则本身不因 tag 迁移而改变。变的是黑板读写、worker 上下文、总管决策字段。


13. 与 Book 存储

Book 存长期实例;黑板存 当前 Session 的运行时 tag。实例化产物与 run 阶段确认稿可归档到 Book。
详见 docs/book-storage.md 与 §2.7。


14. 实现原则(必须遵守)

1. worker 不读取全量黑板quick-write 等显式声明全量 inputTags 的 skill 除外)。
2. worker 只能读取 inputTags 声明的标签。
3. worker 只能输出 outputTags 声明的标签。
4. LLM 不决定上下文分发。
5. 总管 run_worker 时不带 inputTags / outputTags。
6. 标签是 worker 之间的接口。
7. 候选不等于事实;草稿不等于确认稿。
8. 正文 worker 可重写角色候选产物。
9. 长期记忆优先从正文.确认稿 更新。
10. 简单 skill 用简单 tag复杂 skill 再增加对象与阶段段。
11. 角色卡与设定在 instantiate 阶段写入 tag跨 Session 复用走 Book 加载,不单独 author skill 包。
12. 代码与旧文档冲突时,以本文为准改代码。

15. 代码迁移顺序(参考)

1. src/types/blackboard.ts → BlackboardItem + listByTag / matchPrefix
2. src/skills/types.ts + loader → 解析 inputTags / outputTags
3. src/worker/executor.ts → 按 tag 组装 context校验 outputTags
4. src/types/runtime.ts + main-agent → 决策去掉 inputKeys / outputKeys
5. skills/novel/weird-rules-short → 第一个 tag 化样板
6. skills/novel/quick-write → 简易全量 LLM 档

当前代码仍为旧 key 模型;实现前以本文为规格。


16. 相关文档

文档 内容
orchestrator-skill-format.md 总管 orchestrator.md 写法
worker-skill-format.md Worker SKILL.md 写法
tool-contracts.md 总管 / worker tool
skill-format.md Skill 包存储
runtime-state-machine.md 5 相位阶段机
implementation-guide.md 写代码顺序
skills/README.md Skill 包索引与 TODO