- 人工智能
- RAG
- Agent 记忆
- MCP 服务
- 知识管理
【免费下载链接】gbrain
Garry's Opinionated OpenClaw/Hermes Agent Brain
本文是 GBrain(Garry's Opinionated OpenClaw/Hermes Agent Brain)项目内
plugin-variants/gbrain-coding/skills/conventions/brain-routing.md约定的系统化展开。它面向所有会读写 brain 页面的 Skill 与 Agent,回答一个贯穿始终的问题:一条操作到底该落到哪个 brain(数据库)、哪个 source(库内仓库)。读完本文,你将掌握双轴路由的完整心智模型、7 层 Source 解析链的源码级实现、跨脑查询/写入的边界纪律,以及一套可直接照抄的决策表与反模式清单。
为什么需要一条"脑路由"约定
GBrain 允许用户同时拥有多个数据库(brain),每个数据库内部又可以有多个命名内容仓库(source)。对 Agent 而言,工具层暴露的只是query、put_page、search这类语义接口,真正决定"查询打向哪个库、写入落在哪个库内仓库"的是路由逻辑。路由一旦静默出错,轻则检索不到内容,重则把团队资料写进个人大脑、制造审计盲区。
因此brain-routing.md被设计为一条cross-cutting(横切)约定:它不绑定任何单一 Skill,而是约束所有"读或写 brain 页面"的操作。它的完整心智模型沉淀在 docs/architecture/brains-and-sources.md,本文则聚焦 Agent 落地时的决策规则与底层解析实现。
两个正交轴:一页记住的路由坐标系
约定开篇就用"两个轴"把问题降维:
- Brain = 哪个数据库:由
--brain <id>、GBRAIN_BRAIN_ID环境变量、.gbrain-mount点文件决定。 - Source = 数据库内的哪个仓库:由
--source <id>、GBRAIN_SOURCE环境变量、.gbrain-source点文件决定。
两者正交,每条操作各自选一个轴即可。举例来说,在同一大脑里,slugtopics/ai可以同时存在于source=wiki与source=gstack下,它们是两篇不同的页面——slug 只在 source 内唯一,而非全局唯一,页面主键是(source_id, slug)。这正是"只调 source 不动 brain"能成立的前提。
从 brains-and-sources.md 可提炼出一条更本质的判据:
数据所有者改变 → 跨 brain 边界;数据所有者不变、仅主题/仓库改变 → 跨 source 边界。
- 在同一个 brain 内从 wiki 切到 gstack 笔记 → 调
--source - 查询一个不属于你的团队发布的 brain → 调
--brain - 想让某主题彻底不进入个人搜索 → 用
federated=false的--source - 与队友共享一个 brain → 用
--brain挂载团队 brain
默认行为(ALWAYS):信任解析器,别越界
约定为所有 Agent 定义了雷打不动的默认路径:
- 如果还没看过用户的挂载情况,先跑
gbrain mounts list; - 信任解析器。用户若位于
~/team-brains/media/,其.gbrain-mount已把 brain 钉为media-team,不要静默覆盖它; - 每次 brain 操作都显式传入解析出的 brain id再调用工具(即使与默认一致),让路由在日志里可见。
裸执行gbrain query "X"会路由到默认 brain 的默认 source——这在 90% 的场景下就是正确答案。"没有理由就不要跨边界"是该约定的第一纪律。这条默认行为对应 brains-and-sources.md 中的完整优先级:--brain→GBRAIN_BRAIN_ID→.gbrain-mount→ 最长前缀挂载路径匹配 → 回退host。
何时切换 Brain
应该切换(--brain <id>)的三种场景:
- 用户的问题明确指向某个其所属的团队("team X 决定了什么?""team X 的 project Y 什么状态?")——要在搜索之前就切换,而不是在 host 里搜不到之后再补救;
- 用户要摄入属于某团队的数据(团队会议纪要、团队管线的信件)——数据所有者决定 brain;
- 用户点名了团队/brain("查一下 media-team brain 里……")。
不要切换的两种场景:
- 用户问的是可能来自任何地方的通识问题——先在 host 开始,host 没有再按需跨查;
- 不确定时——留在 host,把你找到的东西摆出来,让用户指认具体 brain。
Source 解析链:7 层优先级的源码级拆解
Source 轴是路由中最容易静默出错的地方,GBrain 用一个7 层解析链(v0.41.13+)来收敛它。约定明确给出实现位置:src/core/source-resolver.ts 中的resolveSourceId()(L146-L226),最高优先级在前:
| # | 层级 | 信号 |
|---|---|---|
| 1 | flag | 显式--source <id>CLI 标志(gbrain extract/gbrain import上为--source-id <id>) |
| 2 | env | GBRAIN_SOURCE环境变量 |
| 3 | dotfile | CWD 或任意祖先目录中的.gbrain-source文件 |
| 4 | local_path | 已注册 source 的local_path包含 CWD(最长前缀获胜) |
| 5 | brain_default | brain 级sources.default配置键(显式用户意图) |
| 5.5 | sole_non_default | 第 1–5 层均未命中,且恰好有一个注册 source 带local_path、不是'default'、且'default'不含任何活跃页面(空性守卫:非空'default'会抑制翻转,解析回落到seed_default并输出一行 stderr 通知两侧)。自动路由到它;每次 CLI 调用触发一次性 stderr 提示,可用GBRAIN_NO_SOLE_NON_DEFAULT_NUDGE=1关闭两条提示 |
| 6 | seed_default | 字面量'default'(迁移 v16 后恒存在) |
为什么会有第 5.5 层:sole_non_default的来龙去脉
第 5.5 层是 v0.41.13 针对单 source 大脑(典型场景:用户只有一个 Obsidian vault、一个笔记文件夹、一个项目)引入的。修复之前,从/tmp执行gbrain sync、而大脑只注册了studiovault时,会静默路由到'default',随后每次编辑都在createVersion处失败——因为 slug 根本不存在于那个空 source 里。这一层自动路由到"唯一显然的答案"。
从源码看,pickSoleNonDefaultSource()(src/core/source-resolver.ts#L303-L343)的执行条件非常保守:
- 注册的非
default且带local_path的 source恰好一个,多了(2+)就视为歧义,落到seed_default并要求显式--source; - 排除已归档 source(
archived = false); - #3070 空性守卫:只有当
'default'源没有任何活跃页面(pages表中source_id='default' AND deleted_at IS NULL)时才翻转。若'default'已有内容,则回落并打印一行 stderr,指明两侧并给出修复命令(--source <id>或sources.default); - 提示可用
GBRAIN_NO_SOLE_NON_DEFAULT_NUDGE=1抑制,便于 CI / 脚本化管线使用。
置于brain_default之后是刻意设计:用户通过gbrain sources default <id>显式设置过sources.default,就说明他声明了意图,该意图优先于自动路由。另外该层不读取config.federated——--no-federated只管辖读混合,不参与写路由(相关回归由 test/sync-sole-non-default-routing.test.ts 钉死)。
v0.37.7.0 配套工具:sources current
解析链再可靠,Agent 也需要"写破坏性操作之前确认目标"的验证手段。v0.37.7.0 提供了(实现位于 src/commands/sources.ts#L1505):
gbrain sources current [--json]:回显解析出的 source以及哪一层赢了——执行任何破坏性操作前先跑一次;gbrain sources current --source X:演示显式 flag将会解析到什么(校验 X 存在于 sources 表)。
底层的resolveSourceWithTier()(src/core/source-resolver.ts#L764-L831)与resolveSourceId()共用同一套 7 步逻辑,仅额外返回{ source_id, tier, detail },并通过导出的SOURCE_TIER_NAMES常量(flag/env/dotfile/local_path/brain_default/sole_non_default/seed_default)保证--json输出与代码使用同一套规范词汇,不会漂移。
哪些命令走这条链
约定列出的命令:gbrain sync、gbrain import、gbrain search、gbrain extract(用--source-id <id>,因为--source被保留给 fs|db 数据源轴)、gbrain graph-query(--source限定遍历范围,--include-foreign扩展到所有 source)。
信任边界(v0.34.1.0):解析器只是 CLI 层
这是路由安全性的关键设计:解析链只存在于 CLI 层。Operations.ts 里的 handler不会读.gbrain-source或GBRAIN_SOURCE;MCP / 远程调用方走的是ctx.auth.sourceId/ctx.auth.allowedSources。也就是说,一个远程调用方不可能继承服务端进程的 CLI source 上下文——远程作用域必须显式授权,从根上杜绝了"跨进程环境变量泄漏"类漏洞。该边界在 brains-and-sources.md 中有完整展开(source 隔离、facts 可见性、takes 持有者、写侧 slug 围栏均为 fail-closed 且被测覆盖)。
解析链的工程细节(源码补充)
- ID 校验:
--source与GBRAIN_SOURCE走强校验[a-z0-9-]{1,32},非法值直接抛SourceTargetError;而 dotfile(第 3 层)与sources.default(第 5 层)是"静默回落"层——操作者手改出错(如遗留下划线 ID)就落到下一层,保持解析器对坏配置的鲁棒性。 __all__哨兵:第 1、2 层对__all__原样放行(它并非 source id,跳过正则与存在性校验),由sourceScopeOpts赋予"跨越一切 source"的语义。- 存在性校验:
assertSourceExists()在每层命中后都会执行(SELECT id FROM sources WHERE id = $1 AND archived = false),源不存在或已归档会抛出带修复提示的错误——防止向不存在的 source 静默写入、制造死外键。 - 点文件信任规则(第 3 层):向上逐级遍历目录时用
lstatSync(而非statSync)检查,isTrustedDotfile拒绝符号链接、他人所有、全局可写文件(#418),防止多用户主机上在共享祖先目录植入伪造.gbrain-source。 - 第 4 层最长前缀:CWD 与注册
local_path两侧都做realpath(防符号链接伪造前缀匹配),且按active 优先于 archived分层比较(#3880);N 个注册路径的 realpath 用Promise.all并行,I/O 开销收敛到最慢单源而非总和。
何时切换 Source
应该切换(--source <id>):
- 用户正在某个特定 repo 工作——
.gbrain-source点文件通常已处理,不要与它对抗; - 用户问的是限定在某 repo 内的问题("我的 gstack 笔记里关于 retry policy 说了什么?");
- 你要写一篇逻辑上属于某个 repo 的页面——数据出处决定 source。
不要切换:
- 用户意图跨越多个 repo——保持
federated=true的 source 用于跨 source 搜索; - 隔离会导致失去跨 repo 匹配。
跨脑查询:Latent-Space Federation
v0.19不做确定性的跨脑联邦——没有 SQL 扇出,没有统一排序。联邦是 Agent 的职责,不是数据库的职责。这是刻意为之的特性:它让调试保持清晰、让访问控制保持干净(brains-and-sources.md)。
当用户的问题可能横跨多个 brain 时:
- 先用显而易见的查询打 host;
- 查看
gbrain mounts list找相关 brain id; - 若认为另一个 brain 有答案,显式用
--brain <id>重查那个 brain; - 跨结果综合,用
<brain>:<source>:<slug>标注,让用户可追溯。
绝不静默混用 brain——每条发现都必须可追溯到其所属 brain。
跨脑写入:读可以发散,写必须克制
写入比读取严格得多。跨 brain 写入前必须先询问:
- 关于某团队工作的事实 → 团队 brain,而不是 host;
- 用户确认的、只有 TA 知道的个人信息 → host/个人 brain,而不是团队 brain;
- 从公开数据发现的 enrichment → 通常放 host,除非用户另有指示。
如果你准备执行put_page --brain <team-brain>,除非用户明确说了"存到 team-X",否则先与用户确认。写入的默认 brain 是用户个人 brain。这条纪律与 quality.md 的"Notability Gate"形成互补:前者管"写到哪里",后者管"值不值得写"。
带 Brain 上下文的引用格式
标准引用格式不变([Source: ...]),但当页面来自挂载的 brain 时,为人类可追溯性追加 brain 上下文:
- 单 brain 查询:
[Source: Meeting, 2026-04-10](不变); - 跨脑综合:
[Source: media-team:meetings/2026-04-10]或[Source: policy-team:research/retry-budgets]。
这是 v0.18.0 的 source 感知引用([source-id:slug])在相关时扩展了 brain 前缀。完整的引用文法(用户陈述、会议、邮件、网页、社交、综合)见 quality.md。
决策表:照着抄的 7 个典型场景
| 情境 | Brain | Source |
|---|---|---|
| 用户 cd 进团队 brain 的 checkout 后问通识问题 | dotfile 解析出的团队 brain | dotfile 解析出的 source |
| 用户问"team X 决定了什么?" | 显式team-x | 解析器默认 |
| 用户问"我们全团队正在做什么?" | 跨挂载扇出,Agent 驱动 | 解析器默认 |
| 用户说"把这加到我的 gstack 笔记里" | host | gstack |
| 用户说"为 team X 保存这份会议纪要" | team-x(含糊时确认) | 团队的 meetings source |
| 用户说"帮我写篇文章" | host(个人) | essays |
| 未知——无法分类 | 留在 host,询问用户 | 解析器默认 |
反模式:四条红线
- 静默跳 brain 去"找"答案,而用户显然意指 host——这是审计线索上的洞;
- 把明显属于团队的数据写进 host("团队的计划现在躺在你的个人大脑里"= 糟糕的惊吓);
- 单次查询内做跨脑联邦却不在引用里标明 source brain——用户无法追溯答案;
- 无视
.gbrain-mount/.gbrain-source点文件——它们是承重上下文,用户设立它们必有原因。
与相邻约定的关系
- docs/architecture/brains-and-sources.md:完整心智模型,含四种拓扑图(单人、个人多 repo、个人+团队、CEO 级多团队)与实体身份(
entity_identities)、跨 source 链接边的细则; - plugin-variants/gbrain-coding/skills/conventions/brain-first.md:先读 brain 再问人——本约定的读取端纪律,含查找链(
search→query→get_page→ 外部 API)与brain_first: exempt声明式豁免; - plugin-variants/gbrain-coding/skills/conventions/quality.md:引用格式基准,本文在其上扩展了 brain 前缀。
实践上,将本文的决策表与gbrain sources current验证步骤组合,是 Agent 在执行任何写操作前的最低成本安全网;而解析链本身已被 test/source-resolver-with-tier.test.ts、test/sync-sole-non-default-routing.test.ts 等测试覆盖,路由行为可回归、可验证。
- 人工智能
- RAG
- Agent 记忆
- MCP 服务
- 知识管理
【免费下载链接】gbrain
Garry's Opinionated OpenClaw/Hermes Agent Brain
相关推荐
如何使用 symfony/routing 实现灵活的 PHP 路由系统:基于接口的解耦实践指南
如何使用 symfony/routing 实现灵活的 PHP 路由系统:基于接口的解耦实践指南 symfony/routing 是一个强大的 PHP 路由库,支
后端gbrain 嵌入迁移完全指南:在既有 brain 上安全切换 Embedding 模型与维度
gbrain 嵌入迁移完全指南:在既有 brain 上安全切换 Embedding 模型与维度 导读 :本文面向需要在 gbrain 中更换 Embedding
人工智能RAGAgent 记忆MCP 服务知识管理Qdrant HNSW向量索引:从理论算法到生产级高性能实现的深度解析
Qdrant HNSW向量索引:从理论算法到生产级高性能实现的深度解析 当AI应用需要从千万级向量数据中实现亚秒级相似性检索时,传统的线性扫描方法在响应时间和资
人工智能RAGAgent 记忆MCP 服务知识管理
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考