恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
gbrain Open-Loop Engine 实战指南:让 Agent 知道谁在等你、你承诺过什么
首页
资讯中心
/
gbrain Open-Loop Engine 实战指南:让 Agent 知道谁在等你、你承诺过什么
gbrain Open-Loop Engine 实战指南:让 Agent 知道谁在等你、你承诺过什么
发布时间:2026/9/20 23:51:32
gbrain Open-Loop Engine 实战指南让 Agent 知道谁在等你、你承诺过什么【免费下载链接】gbrainGarrys Opinionated OpenClaw/Hermes Agent Brain项目地址: https://gitcode.com/gh_mirrors/gb/gbrain导读本文围绕 gbrain 的 open-loop engine开放回路引擎展开它解决的问题不是搜索我的邮件而是把邮件沉淀为一个结构化的承诺记录谁在等你回复、你承诺过什么、需要什么上下文来回应。读完本文你将掌握gbrain waiting与gbrain loops全家族命令的使用方法、确定性线程状态机与 LLM 承诺提取器两条检测链路的工作原理、关闭/静音/排序等完整语义以及它们背后由 src/core/google/loop-detect.ts、src/core/google/loops-extract.ts 与 src/core/loops/loops-store.ts 支撑的源码级实现细节。Open-Loop Engine 是什么摄入邮件的意义不在于能搜索我的邮件而在于回答这是正在等你的三个人、你承诺过的事情、以及回复所需的上下文。这条命令给出答案gbrain waitingopen-loop engine 在open_loops表schema 定义见 src/schema.sql#L886-L921中维护一份结构化记录承诺、未回复消息与待定决策数据来源是 google source kind 摄入的邮件每次同步时保持更新。它不删除任何记录只做状态迁移因此审计轨迹永远存在。引擎由两条互补的检测链路组成一条零成本、永远在线一条调用一次 LLM、负责语义级承诺抽取检测器实现LLM成本状态确定性线程状态机src/core/google/loop-detect.ts无免费始终开启线程回路unanswered_inbound / unanswered_outboundLLM 承诺提取器src/core/google/loops-extract.ts每个近期线程一次调用默认对 google 源开启承诺回路commitment_owed_by_me / commitment_owed_to_me / decision_pending检测器一确定性线程状态机loop-detect.ts 是一个纯函数detectThreadLoop 一个薄薄的 apply 步骤applyThreadLoopVerdict由runGoogleSync对每个触碰的线程调用且绝不让检测失败拖垮同步。它对每个已同步的 Gmail 线程按以下规则判定最后一封实质性消息是对方的且你在To:收件人中且未回复 ≥24h → 打开unanswered_inbound——他们在等你最后一封实质性消息是你自己的且其中含有问号且对方未回复 ≥72h → 打开unanswered_outbound——你在等他们一封回复落地 → 回路自行关闭closed_by: reply_detected。宽限期常量定义在 loop-detect.ts#L40-L41INBOUND_GRACE_HOURS 24、OUTBOUND_GRACE_HOURS 72。宽限期的存在意义是新鲜的邮件还不是回路——它同时是一条被红队验证过的防线如果宽限期内对方的新提醒被当作回复而关闭回路那么回路会在对方最焦急的 24 小时内恰好被隐藏这是注释中明确记录的教训loop-detect.ts#L58-L62。精度规则什么永远不会打开回路注释里写着Precision IS the product精度即产品。以下类别永不打开回路噪声发送者noreply / notifications / mailer-daemon / donotreply 等子串见 google-render.ts#L20-L35 的NOISE_SENDER_SUBSTRINGS列表邮件带List-Unsubscribe即 RFC 2369 批量标识仅 CC 投递不在To:中就不欠回复FYI/转发——自己发出的消息里没有问号就不是请求自线程所有参与者都是你自己的地址如笔记、草稿被静音的发送者/线程gbrain loops mute见下文。已发送邮件的摄入是未回复判定诚实的根基——你自己的回复是负面过滤器。如果 gbrain 不摄入 Sent 邮件就无法知道你已经回复过所有回路都会永远挂着。Google Calendar 系统邮件的结构性排除Google Calendar 发出的Invitation:、Updated invitation:、Accepted:、Declined:、Tentative:、Canceled event:等通知是代表真人发出的——它们来自你同事的真实地址因此isNoiseSender识别不到loops mute sender也无法安全地屏蔽它屏蔽地址会连同事的真实邮件一起屏蔽。识别的主信号是结构化的text/calendar部件自带 Content-Type 头中携带的 iCalendarMETHODRFC 5546 的REQUEST、REPLY、CANCEL、PUBLISH、COUNTER、DECLINECOUNTER、REFRESH、ADD白名单见 google-render.ts#L63-L65。只有白名单内的值算数空 method如人类直接附上一个.ics文件或无法识别的值都不算印章——把它们误判为系统邮件会让真实的、带问号的人类邮件既不能打开回路也不能关闭回路。主题前缀只是 MIME 未被捕获时的后备信号锚定主题开头、只匹配 Calendar 自己的本地化头部英文之外还覆盖俄、西、法、德见 google-render.ts#L67-L79并拒绝任何带Re:/Fwd:前缀的主题——人类转发以 Invitation: ... 开头的邀请线程仍然打开回路google-render.ts#L81-L93。这类通知既不开也不关回路邀请不是回复让它翻转回合等于悄悄回答一个真实的出站回路。但它们仍作为普通可搜索页面摄入继续喂养日历/会议上下文。完整行为由 test/google-loop-detect.test.ts#L493-L709 的专项测试锁定同事同地址真实邮件仍开回路、邀请不关闭真实出站回路、本地化主题后备、裸.ics附件仍开回路等。精度语料库fixture 先于修复所有误报类别都由 test/google-loop-detect.test.ts 中的带标签 fixture 语料库钉死corpus has at least 40 labeled casesL407每一条都断言精确结论——要么无回路要么恰好一个预期类型的回路和预期对手方零误报是断言本身每个新的误报类别在修复前先获得 fixture 行。测试使用冻结时钟NOW new Date(2026-08-25T12:00:00Z)因此宽限期边界完全确定、无时钟抖动test/google-loop-detect.test.ts#L24-L32。检测器二LLM 承诺提取器loops-extract.ts 对每个近期线程做一次模型调用默认对 google 源开启提取承诺commitment带方向我周五前发你 deck →commitment_owed_by_me我欠别人别人承诺给我 →commitment_owed_to_me待定决策pending decision线程中尚未解决的一个明确问题/选择。Judge 的系统提示loops-extract.ts#L146-L160要求输出严格 JSON{commitments:[{direction:owed_by_me,text:...,counterparty_name:...,counterparty_email:...,due_iso:YYYY-MM-DD|null,quote:...}],decisions_pending:[{text:...,quote:...}]}其中quote必须是线程中的逐字句子最长 200 字符、绝不转述due_iso仅当日期明确或可清晰推导如by Friday时填写。一个提取器三项投影每条提取项同时落入三个基板src/core/google/loops-extract.ts的注释称ONE extractor, not twoopen_loops行本身dedup key 为commit:sha8(JSON.stringify({t: threadId, d: direction, x: text.toLowerCase()}))detector 标记为llm_extractL437-L454一条facts行kindcommitmentfence-first、去重、带validUntil到期日其fact_id落在open_loops.fact_id上——于是entity、context_pack、recall通过既有读路径零新增读代码即可看到承诺L403-L419一条类型化边线程页 → 人物页owes_to/awaiting_reply_fromL458-L473关系检索谁欠我、我在等谁可以遍历它。loops_close关闭承诺回路时会同步让这条投影出的 fact 过期UPDATE facts SET expired_at now()见 src/core/ops/loops.ts#L435-L442实体卡片不再携带已完成的承诺。护栏设计注入硬化模型看到线程的最新 12k 字符page.compiled_truth.slice(-12_000)长线程上最新回复对 judge 永远可见同时对输入做INJECTION_PATTERNS清洗并把内容包在thread数据标签里L336-L352ALL-or-nothing 解析屏障parseLoopsJson必须整体通过commitments/decisions 数组、每个元素的方向枚举、text/quote 非空、due_iso走真实日历日期检查isCalendarDate——2026-13-45这种幻觉日期会被拒任何畸形元素 → 整体返回 null什么都不写L216-L245逐字引文校验quote必须在模型实际看到的线程内容中可匹配空白归一化后幻觉或被注入的引文被丢弃——回路仍落地但伪造证据永不呈现L384-L393近因窗口只提取最近 30 天邮件LOOPS_EXTRACT_WINDOW_DAYS 30深度回填从不被提取总开关gbrain config set loops.extraction_enabled falseloops-extract.ts#L135-L142 读取该配置false/0/off视为关闭读取失败时 fail-open 为默认开启无聊天提供者时keyless 安装或提供者宕机时sweep 不排队任何提取任务并记录一行原因google-source.ts#L515-L523——邮件页面照常导入线程在下次触碰或gbrain sync --source id --full之后、提供者就位时再被提取任务在宕机中途撞上则重试若最终死亡则释放槽位而不是空着完成LoopsExtractRetryableErrorloops-extract.ts#L273-L281。已声明的瞬态结局llm_unavailable/truncated/parse_barrier必须抛异常而不是返回skipped否则 minion 任务会被成功完成并永久消耗 revision-keyed 幂等槽位L326-L382静音共享loops mute同时拦住 LLM 通道为被静音发送者/线程重建承诺或决策L297-L323。发送者静音只看线程里谁写了信senders:frontmatter 的全部作者不只最新作者绝不管收件人/CC——只静音一个人不会隐藏群线程里其他人的承诺外部发送者也无法通过 CC 一个已被静音的地址来逃避提取。线程页面在 frontmatter 里携带senders:列表与participants:并列渲染逻辑见 google-render.ts#L234-L259。哪些线程能到达提取器结构性资格门loopExtractionEligibilityloops-extract.ts#L90-L133在排队之前先运行让批量邮件既不为模型调用买单也不把真实通信挤出货道形态是否合格SPAM/TRASH否——无论谁写的账户所有者写过实质性消息SENT标签或已知所有者地址Calendar RSVP 等其他噪声不算是覆盖下面所有规则纯噪声发送者 / 纯日历通知否CATEGORY_PROMOTIONS/CATEGORY_SOCIAL/CATEGORY_FORUMS否除非所有者参与过List-Unsubscribe批量否除非所有者参与过CATEGORY_UPDATES是——发票、合同、文件请求都在这里普通人类通信是所有者参与规则是承重墙你自己的外发消息正是你承诺所在的地方所以回复一封带批量标签的线程时写下的 Ill send this by Friday 仍然可达。每条规则都是结构性的——Gmail 标签、List-Unsubscribe、calendar 部件、谁写了消息——没有发送者、域名、主题或正文匹配因此无需维护任何厂商名单。sweep 按原因记录计数loops_extract eligibility:日志见 google-source.ts#L1127-L1129可以审计是否过度过滤而邮件内容不进日志。排队语义队列即积压并发即限速每个合格线程都被排队按最新优先排序——只是排序不会因更旧而丢弃。关键设计google-source.ts#L504-L594MinionQueue 是积压worker 并发是限速线程只在变化时重新成为候选因此严格的每次 sweep 上限会静默丢失线程历史教训曾经只保留最新 50 个并把其余记为 deferring但未变化的线程永远不会再触发——那是静默数据丢失不是延迟任务以页面修订为键loops:source:slug:newestMs——未变化线程的重新扫描是 no-op这个键是唯一去重机制不设maxWaiting其撞上限时会把全新键合并到别的线程等待任务上500/sweep 的宽松安全上限LOOPS_EXTRACT_ENQUEUE_CEILING10 倍于旧上限纯粹是病态 sweep 的支出后盾而且按等待深度预算waiting/delayed/active 都计数防止宕机中每轮 sweep 再堆一层的积压触顶时日志如实点名被延迟的线程google-source.ts#L550-L576。使用面命令、Skill 与 MCPgbrain waitinggbrain waiting [--top N] [--json] [--stale-ok]排好序的对手方列表你欠他们什么/他们欠你什么、证据引文、Gmail 深链、实体卡片上下文、一份可直接粘贴的摘要。参数细节见 src/commands/loops.ts#L73-L134--top N默认 3--source id收敛范围--json输出 agent envelope--stale-ok强制放行过期数据。过期拒答当所有 google 源超过 24h 没有成功同步时gbrain waiting拒绝输出而不是给出可能过期的自信结论并打印精确修复命令gbrain sync --source idsrc/commands/loops.ts#L100-L122。新鲜度判定在 src/core/ops/loops.ts#L43-L76STALE_AFTER_MS 24hDB 错误时朝过期方向失败stale: true——这个表面的不变量就是过期但自信比没有更糟。一个新鲜账户就能保持输出流动每个源自己的同步年龄始终汇报。gbrain loops 家族gbrain loops list|show id # 检查 gbrain loops done id | drop id # 关闭关闭承诺回路会同时使投影出的 fact 过期 gbrain loops mute sender email # 不再为此发送者打开回路 gbrain loops mute thread id # ...或此线程既有回路保持状态 gbrain loops unmute sender email # 撤销静音——检测器可再次打开回路 gbrain loops unmute thread id # ...gbrain loops list还支持--status open|done|dropped|stale与--type loop_type过滤src/commands/loops.ts#L157-L204。默认作用域gbrain waiting和gbrain loops list默认跨大脑中的每个源读取——回路住在 google 源里而不是default如果按 default 作用域读会得到一切干净的假象而人们其实还在等。--source id显式收敛。不带--source的loops mute自动解析到大脑的 google 源没有或不止一个时拒绝并给出精确修复loops unmute用同样的方式解析源所以 unmute 不可能指向 mute 之外的另一个源src/commands/loops.ts#L241-L264。Unmute 是精确且仅向前的它删除 mute 写入的那一条(source_id, kind, value)行——同样的小写化因此unmute sender BOBExample.com恰好逆转mute sender bobexample.com兄弟源、其他 kind、不同 value 一概不动实现见 loops-store.ts#L289-L302。它不会重开回路抑制只门控 NEW 检测静音期间关闭或从未打开的回路保持原状检测器只是从下一次同步开始恢复开环。重复 unmute 是 no-op返回removed: false且退出码 0脚本可以无条件调用src/commands/loops.ts#L279-L295。对 Agent 说谁在等我Who is waiting on me? / open loops 路由到 google-loops skillskills/google-loops/SKILL.md插件镜像在 plugin/skills/google-loops/SKILL.md。其每日操作 runbook 覆盖静音agent 运行gbrain loops mute sender email停止追踪某发送者gbrain loops unmute sender email撤销unmute 没有自己的触发器agent 直接调用命令。skill 明确列出反模式不要用query/search回答谁在等我搜索结果没有回路状态语义不要静默绕过过期拒答不要在用户确认前替用户把回路标为 done——线程回路会在下次同步看到 Gmail 里的回复时自行关闭。MCP 操作四个 MCP 操作定义在 src/core/ops/loops.tsopen_loops读、loops_close写、loops_mute写、loops_unmute写。open_loops对远程调用者是 fail-closed 的证词脱敏计数、对手方、摘要、到期日可见逐字引文、深链、可注入的text摘要只对可信本地开放ctx.remote false。远程调用者还必须持有已解析的源作用域无作用域的远程读直接被拒而不是横跨整个大脑写操作要求与调用者授权匹配的单源作用域——loops_unmute也一样解除另一个源的抑制与植入它同样属于定向写src/core/ops/loops.ts#L247-L288、L462-L478、L497-L514open_loops支持按调用作用域参数source_id传输层绑定到别的源的 MCP 客户端可以把读指向 google 源远程调用者做授权检查和all_sources可信本地横跨大脑远程留在授权内当作用域内完全没有 google 源时结果携带no_google_sources: true摘要明确说明此大脑没有可供回路引擎读取的邮件而不是You are clean——通过网关或 agent 自建 collector 收邮件的大脑没有东西可读这与空收件箱不是一回事。修复路径任选gbrain google setup自带 OAuth或在sources add上用--access command|env复用现有 Google CLI 或发 token 的网关见 google-connect.md#other-ways-to-reach-google-no-gbrain-oauth。记忆动词实体卡片的open_threads[]条目只要由回路行支撑就携带附加的可选字段direction、due、counterparty、status、loop_id任何 harness 上经entity、context_pack、delta可见行为由 test/entity-card-loops.test.ts 锁定已关闭回路不出现、loop-backed 条目最多 3 条且按最新活动排序、闭环后的事实不再出现在open_threads中。关闭语义线程回路回复落地时确定性关闭reply_detected。只有回合翻转才是关闭信号——宽限期、仅 CC、列表邮件、FYI、抑制等一切门可以阻止新开但绝不伪造reply_detected关闭loop-detect.ts#L112-L118承诺回路手动关闭gbrain loops done或过期关闭——逾期 14 天且 14 天无活动仍在积极讨论的逾期承诺保持打开或 90 天完全无活动 → 标记stalemarkStaleLoopsloops-store.ts#L241-L258与承诺事实衰减半衰期对齐Closed means closed已关闭回路done / dropped / stale只有遇到真正更新的线程活动才会重开——例行的重新扫描看到同一线程永远不会复活你手动关闭的回路。这在upsertOpenLoop的 SQLWHERE里强制WHERE open_loops.status open OR EXCLUDED.last_activity_at open_loops.last_activity_atloops-store.ts#L119-L136承诺的回复即履行检测是未来工作代码明确不做假装。排序确定性排名对手方按以下因素排序开放回路数、到期日临近度、最旧回路年龄、以及此人在你大脑中的连接度backlink 数。rankGroups打分公式src/core/ops/loops.ts#L177-L190loop_count * 10到期日加分已到期 50、≤3 天 30、≤7 天 15、否则 5年龄加分min(20, ageDays)backlink 加分min(20, backlinks)无 slug 则不计。确定性——同样的数据同样的顺序gbrain waiting无 LLM、零成本适合反复调用。存储层open_loops 与 loop_suppressionssrc/schema.sql#L886-L933 定义了核心表open_loopsidBIGSERIAL、source_id外键到 sources级联删除、dedup_key(source_id, dedup_key)唯一去重依据、loop_typeCHECK 约束限定五种commitment_owed_by_me/commitment_owed_to_me/unanswered_inbound/unanswered_outbound/decision_pending、counterparty_slug/counterparty_email、summary、evidenceJSONB经$N::text::jsonb绑定遵守项目 JSONB 纪律、thread_id、page_slug、due_at、statusCHECKopen/done/dropped/stale、detectorCHECKdeterministic_thread/llm_extract/manual、confidence、fact_id、opened_at、last_activity_at、closed_at、closed_by。三个部分索引分别服务状态排序、对手方分组与线程查找schema.sql#L916-L921loop_suppressions(source_id, kind, value)唯一kindCHECK 限定sender/thread值统一小写存储——这就是 mute/unmute 精确匹配与大小写不敏感的落点schema.sql#L923-L933。访问层 loops-store.ts 在两个引擎上用完全相同的 SQL 文本构造上保证一致性并处理了 PGLite 与 postgres.js 的类型差异BIGSERIAL 返回 string vs number、timestamptz 返回 Date vs stringnormalizeRow统一转 ISO 字符串。抑制集按(engine, sourceId)缓存 60 秒WeakMap epoch 测试缝并刻意按 engine 身份而不是 sourceId 单独键控防止单进程服务两个大脑时源 id 撞车共享静音集loop-detect.ts#L179-L210。成本与现实边界承诺提取会把近期邮件文本≤30 天、每次 sweep ≤50 个线程在飞发给配置的聊天提供者——skill 的成本诚实一节建议在设置时告知用户一次关闭开关是gbrain config set loops.extraction_enabled false未回复线程检测免费且不受影响skills/google-loops/SKILL.md#L141-L146。无提供者时 sweep 不排队、记一行日志邮件页面照常导入提供者就位后gbrain sync --source id --full可重排所有窗口内线程。这套既有确定性兜底、又有 LLM 语义抽取、全链路可审计的架构让谁在等我从一次性的情绪检查变成每天可依赖的自动化事实。【免费下载链接】gbrainGarrys Opinionated OpenClaw/Hermes Agent Brain项目地址: https://gitcode.com/gh_mirrors/gb/gbrain创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考