16 KiB
标签驱动黑板
1. 定位
本系统用于多 worker 协作式文本生成,覆盖:
简易小说快速撰写(quick-write)
规则怪谈 / 短篇结构化创作(weird-rules-short 等)
长篇小说 / 交互式写作助手(interactive-novel,TODO)
场景扮演模拟(scene-roleplay,TODO)
角色扮演 / 角色卡互动(并入 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
业务 stage(Book / 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 stage:agent 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)→ run(write / review …)→ done
## Worker 编排
仅 run stage 及之后调度生产 worker;instantiate 阶段只 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 明确约定。
已废弃: 旧模型的 key、summary、tags[]、readableBy、writableBy 作为路由字段。迁移期代码可能仍保留 BlackboardEntry,以本文为准逐步替换。
4. 标签原则
标签不是信息分类学,而是 工作流接口。
3.1 设计原则
标签越少越好,但必须能区分不同消费路径。
两个信息若永远被同一批 worker 消费,可合并 tag。
若在不同阶段被不同 worker 消费,必须拆分 tag。
若可能被误当成事实,必须加阶段段。
若涉及角色私有认知,tag 里必须体现角色归属。
3.2 推荐格式
对象.内容
对象.内容.阶段
领域.对象.内容.阶段
不强制四段式;按复杂度逐级增加。
示例:
大纲.草稿
事件.草稿
正文.草稿
正文.确认稿
角色.A.行动.候选
角色.A.台词.候选
角色.A.内心想法.候选
角色.A.记忆.当前
3.3 标签替代的旧字段
角色.A.内心想法.候选
已表达:归属 A、类型为内心想法、阶段为候选、消费路径由声明 inputTags 的 worker 决定。
不需要 再写 owner、visibleTo、type=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 / 业务阶段
选择下一个 worker(run_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.md(manifest)+ 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 → done(orchestrator.md;brief 即 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 |