基于 gbrain 的智能体大脑定时调度实战:从 Cron 基线到 Dream Cycle 与安静时段门控
2026/9/19 17:25:45 网站建设 项目流程
  • 人工智能
  • RAG
  • Agent 记忆
  • MCP 服务
  • 知识管理

【免费下载链接】gbrain

Garry's Opinionated OpenClaw/Hermes Agent Brain

项目地址:https://gitcode.com/gh_mirrors/gb/gbrain
点击查看免费下载

导读:gbrain(Garry's Opinionated OpenClaw/Hermes Agent Brain)把个人/团队知识库变成了会自我维护的系统——而让"自我维护"真正运转起来的,是一整套 20+ 项常驻定时任务编排。本篇以 docs/guides/cron-schedule.md 为核心骨架,完整还原参考调度表、cron 落地命令、强制安静时段门控与跨时区处理,并深入到gbrain dream夜间循环的三级裁剪级联(triage cascade)、oneshot 合成模式与排水池并发模型,结合 triage-rescue.ts、synthesize.ts 等源码验证每一项配置旋钮的真实默认值与行为。读完你将能照抄出一套可上生产、可验证、不打扰用户的定时大脑维护方案。

为什么要有一张调度表:大脑的"复利"从定时开始

原文档开篇就点明了这组任务的意义:一个生产级大脑运行着 20+ 项周期任务,让知识库保持鲜活、持续累积(compounding)。如果不做这件事,大脑只会在你手动摄入数据时才更新——页面过期、实体信息单薄、引用断裂、Agent 基于旧上下文作答。

而配好之后,效果是闭环的:

  • 邮件、社交媒体、日历、会议自动流入大脑;
  • 单薄页面在夜间被自动充实;
  • 断裂的引用被自动修复;
  • 你醒来时,大脑比入睡时更聪明。

这正是 docs/guides/cron-schedule.md 想要传递的核心思想:调度不是运维杂活,而是大脑的"存活机制"。文章末尾的 Tricky Spots 第一条把它讲得很重:"dream cycle 不是可选的——没有它,信号从每一次对话中泄漏出去;有了它,什么都不丢。这是一个会遗忘的 Agent 和一个会记住的 Agent 之间的区别。"

参考调度总表

以下是原文档给出的生产环境参考调度表(每个任务的 Brain Interaction 描述了它如何作用于大脑,Recipe 列指向仓库中的配套食谱):

频率任务与大脑的交互食谱
每 30 分钟邮件监控搜索发件人、更新人物页email-to-brain
每 30 分钟X/Twitter 采集创建/更新媒体页、实体抽取x-to-brain
工作日 3 次/天会议同步完整摄入 + 参会人传播meeting-sync
每周日历同步每日文件 + 参会人丰富calendar-to-brain
每日上午晨间简报检索日历参会人、交易状态、活跃线程briefing skill
每周大脑维护gbrain doctor、embed stale、孤儿页检测maintain skill
夜间Dream Cycle实体清扫、丰富薄弱点、修复引用见下文

值得注意的原文档观点:"20+ 个任务听起来很多,但别过度 cron"(详见 Tricky Spots 第 3 条)。起步只需三件事:邮件(30 分钟)、dream cycle(夜间)、大脑健康检查(每周),然后随集成食谱逐个增加。

优先使用 gbrain 原生的调度面

系统 cron 是最低公分母,但 gbrain 自带多个调度面,原文档明确要求"能匹配就先用手边的":

  • gbrain dream—— 官方夜间维护循环(lint、backlinks、extract、sync、embed、synthesize)。直接调度它,而不是下面手工搓 dream cycle 脚本。
  • gbrain jobs/ minions—— 带重试、退避和审计轨迹的任务队列,可提交 shell 任务或 LLM 子代理。详见 minion-orchestrator skill:它区分确定性 shell 任务(gbrain jobs submit shell ...)与 LLM 子代理任务(gbrain agent run ...),并给出"超过 ~2 分钟的操作必须走持久执行阶梯(durable-execution ladder)+ deadman 检查"的路线约定。
  • gbrain autopilot—— 常驻后台守护进程,按自身节奏运行循环(sync、extract、embed、backlinks、durible job 处理都在其中,见 maintain skill 的 Autopilot check 小节)。
  • cron-schedulerskill(skills/cron-scheduler/SKILL.md)—— 教 Agent 管理其宿主的调度器,契约包含:调度错峰(每 5 分钟槽位最多 1 个任务、无冲突)、时区感知的安静时段门控(带 user-awake 覆盖)、薄任务提示("读 skills/X/SKILL.md 并运行",禁止内联 3000 字长提示)、幂等性、结果落盘为报告(reports/{job-name}/{YYYY-MM-DD-HHMM}.md)。
  • Bootstrap 会话触发的调度——gbrain bootstrap安装由 HEARTBEAT.md 驱动的、随会话活动触发的调度,见 bootstrap.md。

对于"仅调度sync+embed --stale"这一具体场景,主文档是 live-sync.md。

cron-schedulerskill 还给出一个重要的多源大脑经验:当gbrain sources list显示 2+ 个活跃源时,用一条合并 cron 行替代 N 条按源条目——

*/5 * * * * gbrain sync --all --parallel 4 --workers 4 --skip-failed

并发预算大约是parallel × workers × 2 ≈ 32个连接(每个按文件 worker 各自开一个 2 连接池),要保持在 Postgresmax_connections之下。gbrain doctor在检测到 2+ 个活跃源时会以sync_consolidation检查的形式直接给出这条推荐行。反模式则包括:所有任务挤在同一分钟(:00)、在 cron 里内联超长提示词、未先在 3–5 个条目上测试就跑全量、任务重跑产生不同输出(非幂等)、安静时段发通知、以及给每个源单独写gbrain sync --source <id>条目。

实现:在系统 cron 中落地

原文档给出了一套可直接照抄的 crontab 实现(注意cd到各采集器目录、重定向日志、用&&串联、用--json便于脚本解析):

# Email collector — 每 30 分钟 */30 * * * * cd /path/to/email-collector && node email-collector.mjs collect && node email-collector.mjs digest # X/Twitter collector — 每 30 分钟 */30 * * * * cd /path/to/x-collector && node x-collector.mjs collect >> /tmp/x-collector.log 2>&1 # Meeting sync — 工作日 10 点、16 点、21 点 0 10,16,21 * * 1-5 cd /path/to/meeting-sync && node meeting-sync.mjs >> /tmp/meeting-sync.log 2>&1 # Calendar sync — 周日 10 点 0 10 * * 0 cd /path/to/calendar-sync && node calendar-sync.mjs --start $(date -v-7d +%Y-%m-%d) --end $(date +%Y-%m-%d) # Brain health — 每周一早上 6 点 0 6 * * 1 gbrain doctor --json >> /tmp/gbrain-health.log 2>&1 && gbrain embed --stale # Autopilot health gate — 每天 7 点。退出码就是信号: # 0 = 新鲜(或未安装),1 = 需要关注(心跳过期、从未运行或已暂停),2 = 守护进程自行退出轮换。 # 状态只读文件系统,因此即使数据库宕机也能工作。 0 7 * * * gbrain autopilot --status >> /tmp/gbrain-autopilot-health.log 2>&1 || your-notify "gbrain autopilot needs attention" # Dream cycle — 夜间 2 点 0 2 * * * /path/to/dream-cycle.sh

逐行要点:

  • 邮件采集拆两步collect负责抓取,digest负责生成摘要,两者都必须执行,摘要依赖采集结果;
  • gbrain doctor --json && gbrain embed --stale&&保证只有健康检查通过才触发嵌入回填(embed 只对缺失嵌入的 chunk 生效,是 >100 文件大同步或--no-embed运行的安全网);
  • gbrain autopilot --status的退出码是被设计成可用于门控的:0/1/2 三态在 live-sync.md 与 maintain skill 中均有明确约定,且--status只读文件系统、不连数据库——这正是它能在数据库故障期间依旧工作的原因;--json会给出stateheartbeat_age_secondspaused_reasondisabled_reason等完整报告。

关于gbrain sync+gbrain embed --stale这条链路的底层细节,live-sync.md 补充了很有价值的前提:gbrain 面向 SupabaseTransaction pooler(端口 6543)调优,但engine.transaction()(迁移、DDL、同步导入)会路由到派生的direct连接(db.<ref>.supabase.co:5432)。该 direct 主机是 IPv6-only 的,IPv4-only 主机不可达时会自动回退到 pooler 并打印一条 stderr 警告——但 pooler 约 2 分钟的语句超时可能截断超长迁移或批量导入。修复方式:设置GBRAIN_DIRECT_DATABASE_URL为 Session pooler 字符串,或启用 Supabase 的 IPv4 附加服务;GBRAIN_DISABLE_DIRECT_POOL=1可整体跳过 direct pool。验证方法:跑一次gbrain sync,比对gbrain stats的页面数与仓库中可同步文件数。

同步本身是提交驱动、幂等且可恢复的:它导入的是committed变更,未提交的编辑与未跟踪文件会计入 drift 并打印N uncommitted file(s) not synced,而非静默忽略;并发运行安全(同一提交两次同步因内容哈希一致而 no-op);被杀掉的同步会从数据库检查点恢复,bookmark 只在真正完成时前进。若你的工作流确实要写不提交的文件,可用gbrain sync --working-tree(单次)或gbrain config set sync.include_working_tree true(常驻配置,dream cycle 等所有调用方都遵守)——但先过一遍git status,因为 untracked 意味着git status列出的所有未忽略的临时文件和密钥都会被纳入。

安静时段门控(强制)

原文档把这一节标为MANDATORY:每个会发送通知的 cron 任务都必须先检查安静时段。门控是一个由你创建的小脚本(gbrain 不附带它),在每一个发通知的 cron 脚本顶部调用;被扣下的输出进一个 holding 目录,由晨间简报清空。不要从这里复制片段——完整门控脚本与模式以 Quiet Hours 为唯一权威主页。

quiet-hours.md 给出的核心逻辑:

QUIET_START = 23 // 当地 11 PM QUIET_END = 8 // 当地 8 AM is_quiet(local_hour): return local_hour >= QUIET_START OR local_hour < QUIET_END

发送任何通知前必须:① 确定用户当前时区(来自配置或 heartbeat 状态);② 将当前 UTC 时间转成当地时间;③ 若在安静时段:扣下消息、不发送。扣下时写入 holding 目录:

if is_quiet(): mkdir -p /tmp/cron-held/ write("/tmp/cron-held/{job-name}.md", output) exit // 不发送 else: send(output)

晨间简报负责拾取:

morning_briefing(): held_files = list("/tmp/cron-held/*.md") if held_files: briefing += "## Overnight Updates\n\n" for file in held_files: briefing += read(file) delete(file)

可用的 shell 实现(quiet-hours-gate.sh):

#!/bin/bash # quiet-hours-gate.sh — run before any notification TIMEZONE="${USER_TIMEZONE:-US/Pacific}" LOCAL_HOUR=$(TZ="$TIMEZONE" date +%H) if [ "$LOCAL_HOUR" -ge 23 ] || [ "$LOCAL_HOUR" -lt 8 ]; then echo "QUIET_HOURS=true" exit 1 # 不发送 fi echo "QUIET_HOURS=false" exit 0 # 可以发送

在 cron 脚本中使用:

# 先检查安静时段 if ! bash scripts/quiet-hours-gate.sh; then mkdir -p /tmp/cron-held echo "$OUTPUT" > /tmp/cron-held/$(basename "$0" .sh).md exit 0 fi # 非安静时段——正常发送 send_notification "$OUTPUT"

关于/tmp/cron-held/的一个现实提醒(quiet-hours 文档 Tricky Spots 第 3 条):/tmp在重启后不保留(macOS 还会定期清理)。如果一条扣下的消息绝不允许跨重启丢失,改用持久目录(如~/.local/state/cron-held/)。

另外,gbrain 本身已原生理解安静时段的两处地方,应优先使用:

  • 自升级auto模式只在安静时段应用升级,通过gbrain config set self_upgrade.quiet_hours '{"start":23,"end":8,"tz":"US/Pacific"}'配置,见 upgrades-auto-update.md;
  • 其余自定义 cron、采集器、通知路径,用上文 shell 模式兜底。

cron-schedulerskill 还补充了 user-awake 覆盖规则:默认安静时段为本地 11 PM–8 AM;若用户正处于活跃状态(user-awake 标志),安静时段被挂起;安静时段输出进 held 队列,晨间联系时释放积压。

旅行感知的时区处理

原文档给出了 Agent 侧推断逻辑:读取日历中的航班、酒店、出差中(out-of-office)块来推断用户当前所在地与时区,所有呈现给用户的时间都用当地时区

// 示例:用户飞往东京 // 太平洋时间下午 2 点 = 东京凌晨 3 点 = 安静时段 // 扣下通知,并入晨间简报 get_user_timezone(): calendar = gbrain search "flight" --type calendar --recent 7d if recent_flight: return infer_timezone(flight.destination) return config.default_timezone // fallback: US/Pacific

旅行时:在家乡的清醒时段会触发、但在目的地撞上睡眠时段的 cron 任务,会被扣下并并入下一个晨间简报——零配置变更quiet-hours.md提供了与之配套的操作状态结构(userAwakecurrentLocation、可选的homeLocationgarryAwake别名仅为兼容保留,生产者应写userAwake),并给出了何时应更新时区的信号:日历显示用户飞往某地、用户提到身处不同城市、或用户活跃时段偏移(凌晨 3 点 PT 还在回复 = 大概率在旅行)。

需要诚实地指出局限(quiet-hours Tricky Spots 第 4 条):基于日历的时区探测依赖用户日历中存在带位置数据的航班/酒店事件;如果用户出行不建日历条目,系统检测不到迁移。此时回退到活跃时段分析,仍不确定就问用户。

Dream Cycle:最重要的 cron 任务

原文档用一句话定义它的地位:"最重要的 cron 任务——在你睡觉时运行。"

gbrain 已内置:直接调度gbrain dream

gbrain dream把维护循环的后半段(lint、backlinks、extract、sync、embed、synthesize)合并为一条命令。每晚调度它,下面伪代码中的 Phase 4(以及 Phase 2 的大部分卫生检查)就被覆盖了。文中给出的伪代码是面向还要在其上叠加 LLM 驱动实体清扫与记忆整合的 Agent 的"宿主侧变体"。

关于日期的归属有一个容易踩的细节:夜间摘要落在你实际生活过的日历日上。循环按显式--date>cycle.timezone配置 > 宿主 IANA 时区 > UTC 的顺序分桶——因此一个在本地午夜之后运行的调度,会落在你生活过的那一天,而不是 UTC 日期。当宿主时钟区与你不同(比如云端机器在 UTC)时,固定一次即可:

gbrain config set cycle.timezone America/Los_Angeles

合成成本控制:triage 级联

synthesize 阶段是一个两阶段级联:一个廉价的打分 triage(utility 层模型,每条新 transcript 一次调用)为昂贵的逐 transcript 合成子代理把关。原文档给出的旋钮(在 config.ts 的配置键清单中均有对应注册,例如dream.triage.thresholddream.triage.rescue_floordream.triage.rescue_min_segmentsdream.triage.rescue_content_typesdream.triage.max_charsdream.triage.max_tokensdream.triage.max_msdream.triage.concurrencydream.synthesize.modedream.synthesize.link_manifestdream.synthesize.quote_verifydream.synthesize.inline_concurrencydream.synthesize.max_turnsdream.synthesize.max_submissions_per_source_per_day):

  • dream.triage.threshold(默认 0.5)——得分门槛,是 transcript 通过闸门的两种方式中的第一种(下文 verified-segment rescue 是第二种)。得分会缓存,因此重新调参即可瞬间重新闸控,零新增 LLM 调用。太多常规内容被合成就调高;真实信号被跳过就调低。
  • models.dream.triage——triage 模型(默认 utility 层 / Haiku 档)。
  • dream.triage.max_chars(默认 24000,下限 1000)——发送给评审的每条 transcript 采样窗口(头/中/尾)。它不属于缓存有效性的一部分——修改后需gbrain dream retriage --force在新采样下重新评审。
  • dream.triage.max_tokens(默认 2048,下限 256)——评审输出预算。
  • dream.triage.concurrency(默认 4,钳制 1–16)——并发评审调用数。
  • Verified-segment rescue(埋没信号恢复,$0):得分落在[dream.triage.rescue_floor, threshold)区间内的 transcript,只要满足两个条件仍可通过:评审自己引用的片段中至少dream.triage.rescue_min_segments(默认 2;设为 0 即禁用)个在 transcript 中验证为子串,且其内容类型在dream.triage.rescue_content_types(默认mixed,reflection,idea,strategy,people——绝不 rescue routine/technical)中。零额外 LLM 调用、可作用于缓存裁决;dream retriage读取同一道闸门,因此 reconcile 扫描永远不会取消被 rescue 准入的任务。遥测字段:details.triage.rescue_checked/rescue_fired
  • dream.synthesize.quote_verify(默认开启)——对新建 dream 页的机械式写后引用验证/修复(被改写的"引号"会修复为逐字 transcript 片段或去掉引号;绝不发明内容)。关闭开关是事故逃生舱;遥测落在details.synthesis.quote_verify
  • dream.synthesize.max_turns(默认 16)——agentic 子代理与 oneshot 回退的合成回合预算(默认 oneshot 路径——见下节——是单次补全,从不消耗回合)。triage 映射把手预抽取的片段交给子代理,因此中档默认模型(models.dream.synthesizereasoning档)+ 16 回合预算就是预期的配对——用 frontier 模型覆盖既不必要又拖慢队列。完整性来自 triage 覆盖(每个文件都被评分,减去max_ms预算下推迟的文件)加上片段引导的提示词,而不是模型大小。若写入页数偏低,可调到 30 并检查details.synthesis.avg_turns是否存在上限压力。
  • dream.triage.max_ms(默认 5 分钟)——每周期评审新文件的墙钟预算;大的冷语料库跨几个周期完成 triage(缓存文件免费)。被推迟的文件标记为"not yet triaged",绝不静默拒绝。
  • dream.synthesize.max_submissions_per_source_per_day(默认 0 = 关)——按源每日合成任务数的可选上限;忙碌部署用 200/天是合理值。

维护配方——修改阈值后、经历TRIAGE_VERSION提升后(当前版本按峰值而非平均打分;提升后首个周期会在max_ms预算内重新评审语料库并把其余推迟到后续周期),或要排空排队的合成积压时:

gbrain dream retriage --dry-run # 会改什么(零 LLM 调用) gbrain dream retriage --reconcile-queue # 重新评分 + 取消未通过闸门的排队任务 gbrain dream retriage --audit-rejects 20 # 用合成模型对 20 个被拒任务做二次意见

源码层面的印证:synthesize.ts 头部注释完整描述了该管道——discoverTranscripts → runTriagePass(有界池,受 dream.triage.max_ms 限制)→ judgeSignificance(utility 模型,在 max_chars 内的头/中/尾采样)→ 得分 ≥ threshold 通过 / 得分在 [rescue_floor, threshold) 且内容类型在白名单且 ≥ rescue_min_segments 个片段验证为子串则 rescue 通过(F2 救援,$0,仅闸控时刻)→(读取时——重调阈值或 rescue 旋钮 = 零重新评审)。而 triage-rescue.ts 用常量给出了 rescue 的精确默认值:DEFAULT_RESCUE_FLOOR = 0.30DEFAULT_RESCUE_MIN_SEGMENTS = 2DEFAULT_RESCUE_CONTENT_TYPES = ['mixed','reflection','idea','strategy','people'],以及一个关键细节MIN_RESCUE_SEGMENT_NORM_CHARS = 40——"实质性"片段至少 40 个归一化字符,过短的验证引用(一个名字、一句问候)不算埋没信号的证据;applyTriageRescue对任何畸形形状(null 分数、缺失片段、非字符串引用)都失败关闭(fail-closed),绝不抛异常;passesTriageGate先做廉价的阈值判定,否则进入 rescue 区间。文档所述"双方式过闸"与"retriage 读取同一道闸门"正是由passesTriageGate这一单一入口保证的(文件注释里明确写着 one-gate rule:任何消费者都从同一入口读取,不能各自手搓score >= threshold检查)。

合成速度:oneshot 模式 + 排水池

triage 级联之上是执行旋钮:

  • dream.synthesize.mode(默认oneshot——每个合成子代理如何运行。oneshot对一条已携带预检索LINK CANDIDATES清单和写入白名单的提示词做一次无工具补全,然后以编程方式校验并写入页面(slug 语法、白名单、transcript 哈希后缀、精确匹配 wikilink——任何写入前全部检查;嵌入移出模型路径,在阶段末尾由一次只覆盖本阶段写入页面的有界 pass 回填——绝不整库扫描)。响应未通过任何检查时会在同一任务内自动回退到经典 agentic 循环——无工作丢失、无需重新提交。oneshot 尝试与其回退调用都是实际付费的 provider 工作,都计入合成 token/花费遥测。典型效果:每条 transcript 的 10+ 次 provider 往返(上限默认 16 回合,调高max_turns后更多)→ 1 次。回退旋钮:gbrain config set dream.synthesize.mode agentic
  • dream.synthesize.link_manifest(默认开)——零嵌入的预检索清单(由 triage 裁决中缓存的实体 + 片段笔记构建)。对两种模式都有益:agentic 子代理不再把回合烧在低产搜索上;oneshot 子代理提前拿到链接目标。
  • dream.synthesize.inline_concurrency(默认 1,钳制 1–8)——Postgres 上按运行排队的子任务队列的并发排水循环(PGLite 总是串行排水)。provider 上限仍由速率租约控制(每条路径上的每次 provider 往返都持有一个租约槽),因此这个旋钮只消除排队等待,绝不过度驱动 API。

如何读阶段报告(details.synthesis):

  • modeoneshot_jobs/fallback_jobs/agentic_jobs+fallback_reasons直方图——fallback 率上升意味着模型在违反输出契约,先看首要原因再考虑回退 agentic;length包含输出用量到达请求上限的畸形响应(即使 provider 的 stop reason 不明确);
  • queue_wait_ms_p50/p95child_runtime_ms_p50/p95——缓慢但健康的排水可见,不会与卡死混淆;
  • dead_jobs/degraded——任何子任务未完成的运行都不会盖章冷却(cooldown),因此下一次夜间运行会精确重试失败的 transcript;所有子任务都死亡的运行会大声宣告阶段失败。当每一次尝试的页面写入都失败时,合成子任务也会进入死信——completed从不意味着"零页面写入"。

还有三个字段回答"花了多少钱、落没落地":

  • spend——阶段实际花费,cost_basis: 'in+out+cache_read'。子任务从minion_jobs的 token 数按配置的合成模型计价求和;triage 来自 pass 自身的用量。total_usd只在两者都有定价时才非 null——未定价的模型读出来是 unknown 而非假0details.triage以相同口径携带评审自己的tokens_in/tokens_out/cost_usd
  • children_zero_pages——完成但没写任何页面的子任务数。这个数字攀升意味着模型在产出"合法但空洞"的输出——而一片全绿的阶段状态会掩盖它。
  • quote_verify——写后引用 pass 触碰了什么:检查/修复/剥离的片段数、作为已存在而跳过的页面数、不平衡段落数,以及仅告警的未接地数字/日期断言计数。

每次调用的花费还会以阶段标签进入chat_usage_log账本:编排器自己的调用在phase:synthesize下,每个排干的子任务在自己的job:<name>下——两者永不重复计数。

它做什么:四阶段伪代码

原文档给出了完整的 dream cycle 伪代码骨架,值得完整保留(它把"会记住的 Agent"翻译成了可执行步骤):

dream_cycle(): // Phase 1: 实体清扫 conversations = get_todays_conversations() for message in conversations: entities = detect_entities(message) for entity in entities: page = gbrain search "{entity.name}" if not page: create_page(entity) // 新实体,创建 + 丰富 elif page.is_thin(): enrich_page(entity) // 单薄页面,补全 else: update_timeline(entity) // 已有页面,追加今天的提及 // Phase 2: 修复断裂引用 pages = gbrain list --type person --limit 100 for page in pages: for entry in page.timeline: if not entry.has_source_attribution(): fix_citation(entry) // 缺失时补 [Source: ...] if entry.has_tweet_url() and not entry.url_is_valid(): fix_url(entry) // 断裂的推文链接 // Phase 3: 整合记忆 patterns = detect_patterns_across_conversations() for pattern in patterns: promote_to_memory(pattern) // 临时 → 持久知识 // Phase 4: 同步 gbrain sync --no-pull --no-embed gbrain embed --stale

对照 maintain skill,gbrain dream官方管线的实际阶段顺序是lint -> backlinks -> sync -> synthesize -> extract -> patterns -> embed -> orphans(可选阶段如 atoms/concepts/drift 插在中间)。skill 补充了两个新阶段的实现细节:

  • Patterns 阶段:在extract之后运行(保证图状态新鲜)。读取dream.patterns.lookback_days(默认 30)内的近期 reflections,做一次 Sonnet pass 找出反复出现的主题,当 ≥dream.patterns.min_evidence(默认 3)篇 reflection 支撑一个主题时写入wiki/personal/patterns/<theme>。完成一次运行会记录它消费的最新 reflection(dream.patterns.last_evidence_ts);窗口内没有更新的 reflection 时,重复运行以no_new_evidence跳过而不支付另一次模型 pass——gbrain dream --phase patterns --once可强制一次。
  • 冷却dream.synthesize.cooldown_hours(默认 12)意味着 autopilot 下每天至多约 2 次 synthesize 运行。完成时间戳dream.synthesize.last_completion_ts只在成功运行时写入(跳过/失败不写)。显式--input/--date/--from/--to调用绕过冷却。
  • --dry-run语义:运行打分 triage pass(评审并缓存新文件裁决)但跳过合成子代理。不是零 LLM 调用——要零调用预览请用gbrain dream retriage --dry-run
  • 信任边界:合成子代理运行在显式写路径白名单(来自_brain-filing-rules.jsondream_synthesize_paths.globs)之下;即使提示注入成功也写不出白名单。PROTECTED_JOB_NAMES使 MCP 根本无法提交子代理任务。
  • 幂等与隐私:transcript 以(file_path, content_hash)为键,同内容重跑是 no-op;dream.synthesize.exclude_patterns(默认["medical", "therapy"])在任何 LLM 调用前过滤 transcript,条目自动包裹为词边界正则(medical匹配 "medical advice" 但不匹配 "comedical")。

搭建 Dream Cycle

按宿主分类的三种搭建方式(原文档原文保留):

OpenClaw:以 DREAMS.md 作为默认 skill 随附。light / deep / REM 三个阶段在安静时段自动运行。

Hermes Agent:

/cron add "0 2 * * *" "Dream cycle: search today's sessions for entities I mentioned. For each person, company, or idea: check if a brain page exists (gbrain search), create or update it if thin. Fix any broken citations. Then consolidate: read MEMORY.md, promote important signals, remove stale entries." --name "nightly-dream-cycle"

Claude Code / 自定义 Agent:创建一个脚本:

#!/bin/bash # dream-cycle.sh # 检查安静时段(应当在安静时段运行——这正是我们运行的时机) echo "Dream cycle starting at $(date)" # Phase 1: 实体清扫(派生子代理) # 读取今天的对话日志,抽取实体,更新大脑 # Phase 2: 官方维护循环(lint, backlinks, extract, sync, embed, synthesize) gbrain dream # Phase 3: 呈现循环标记的任何问题 gbrain doctor --json | jq '.checks[] | select(.status=="warn")' echo "Dream cycle complete at $(date)"

晨间简报与每周维护如何纳入调度

参考调度表里的 Daily AM briefing 与 Weekly brain maintenance 分别由两个 skill 承担,它们的输入正好是前面各环节的产出:

  • briefing skill 在动笔前有完整的 pre-briefing 上下文拉取:gbrain salience --days 7(情感/活动显著性扫描)、gbrain anomalies(对 30 天基线的统计异常)、gbrain recall --query ... --json(个人事实与偏好)、gbrain recall --since-last-run --supersessions --pending --rollup --json(热记忆脉冲:隔夜解决的矛盾、top 提及、上次简报以来的新事实、待整合数),以及有 Google 源时的gbrain waiting --json(开环:谁在等你)。输出格式中每个事实都带[Source: slug, updated DATE]内联引用;简报默认只读。--since-last-run会推进~/.gbrain/recall-cursors/<source>.json游标;作为 cron 运行时务必显式传--source <slug>或设GBRAIN_SOURCE——cron 不会以仓库根目录为 cwd 启动。
  • maintain skill 提供gbrain doctor --remediation-plan --json+gbrain doctor --remediate --yes --target-score 90 --max-usd 5的自治路径(按依赖排序的修复计划,--max-usd是硬成本上限,防止合成循环在无人看管时烧掉 Anthropic 额度),以及逐维度的手动走查:stale 页、孤儿页、死链、缺失交叉引用、gbrain extract links --dir ~/braingbrain extract timeline --dir ~/brain、back-link 铁律、filing 违规、引用审计、标签一致性、gbrain features --json、嵌入新鲜度(大刷新用nohup gbrain embed refresh > /tmp/gbrain-embed.log 2>&1 &)、RLS/模式/文件存储健康与开放线程。健康检查输出有标准化的## Brain Health Report — YYYY-MM-DD表格结构,为大脑健康留下随时间可审计的轨迹。

容易踩的坑(Tricky Spots)

原文档总结了五点,每一条都值得在生产前逐条对照:

  1. Dream cycle 不是可选的。没有它,信号从每一次对话中泄漏;有了它,什么都不丢——这是"会忘记的 Agent"与"会记住的 Agent"的分水岭。
  2. 安静时段门控要挂在每个通知任务上。只要有一个任务跳过门控,用户就会在凌晨 3 点被 ping——一次凌晨 3 点的打扰足以让用户禁用整个系统。
  3. 别过度 cron。20+ 个任务听起来很多,但起步只需:邮件(30 分钟)、dream cycle(夜间)、大脑健康(每周)。随着集成食谱逐步增加。
  4. 时区变化是自动的。不要因为用户出行就让他重配 cron——读日历、推断时区、调整投递。
  5. 被扣下的消息必须被拾取。如果安静时段扣下了通知,晨间简报必须包含它——否则信息就丢了。

如何验证(How to Verify)

原文档给出的五步验收清单,是这套调度方案"可落地"的最后一块拼图:

  1. 安静时段:把安静时段设为当前小时。跑一个发通知的 cron。验证输出去了/tmp/cron-held/,而不是发到消息渠道。
  2. Dream cycle:手动运行 dream cycle。检查单薄实体页被丰富、断裂引用被修复。
  3. 邮件采集 cron:等 30 分钟。检查data/digests/里出现新的 digest。
  4. 晨间简报:检查被扣消息出现在简报中。
  5. 健康检查:运行gbrain doctor --json。所有检查应通过。

结合 live-sync.md 还可以再加两项调度链路的专项验证:编辑一个 brain 文件、commit、push,等下一个同步周期后用gbrain search "<文本>"确认新内容出现(返回旧内容即同步失败);以及gbrain stats中页面数应等于仓库中可同步 markdown 文件数、已嵌入 chunk 数应接近总 chunk 数(大缺口说明gbrain embed --stale没跟在 sync 后面)。


本指南是 GBrain Skillpack 的一部分。延伸阅读:Quiet Hours、Live Sync、Operational Disciplines、cron-scheduler skill、minion-orchestrator skill。

  • 人工智能
  • RAG
  • Agent 记忆
  • MCP 服务
  • 知识管理

【免费下载链接】gbrain

Garry's Opinionated OpenClaw/Hermes Agent Brain

项目地址:https://gitcode.com/gh_mirrors/gb/gbrain
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询