资讯详情

OpenHuman Morning Briefing Agent:从 prompt.md 到定时投递的“每日晨报“实现全解

📅 2026/9/10 5:01:45 | 华诺云谱 👁 阅读
OpenHuman Morning Briefing Agent:从 prompt.md 到定时投递的“每日晨报“实现全解
OpenHuman Morning Briefing Agent从 prompt.md 到定时投递的每日晨报实现全解【免费下载链接】openhumanOpenHuman is an open source personal AI for Mac, Windows and Linux — local-first memory, agent orchestration, and deep research.项目地址: https://gitcode.com/GitHub_Trending/op/openhumanMorning Briefing 是 OpenHuman 内置的主动式proactive日常代理它按用户本地时间每天 7:00 触发从日历、任务、邮件与近 24 小时记忆中汇总出可在 30 秒内扫完的早间简报。本文以该代理的系统提示词 prompt.md 为主体逐条拆解其内容规范、数据获取协议与输出结构并结合 prompt.rs、agent.toml、cron/seed.rs 等源码说明这份提示词在 OpenHuman 中如何被装配、注入运行时上下文并最终通过定时任务投递到用户频道。一、定位一个被降级为提示词工程问题的每日例行代理agent.toml 对该代理的定义是Proactive daily agent — runs at a scheduled time (default 7 AM) to review the users upcoming day and deliver a concise morning summary covering tasks, calendar events, important emails, and relevant context from connected skills.即它不是响应式对话代理而是由 cron 调度器按表达式触发的主动代理。在 src/openhuman/cron/seed.rs 中onboarding 完成后会调用seed_proactive_agents幂等地种入一个名为morning_briefing的日任务调度表达式为0 7 * * *每天 7:00设备本地时区后续用户可通过cron.update_job调整时间或时区任务以SessionTarget::Isolated运行——每次简报在独立会话中完成不与主聊天混线投递方式为mode: proactive、best_effort: true由 channels 模块的ProactiveMessageSubscriber路由到用户当前活跃的频道不指定具体 channel创建时默认enabled false属于 opt-in 设计因为简报是一次完整的主动式 agent 推理必须等用户在设置/Routines 中显式启用后才开始消耗推理配额。在 agent 注册表层面loader.rs 将其注册为内置代理toml指向上述配置文件prompt_fn指向 prompt.rs 中的build函数——这是理解prompt.md 如何生效的关键入口。二、提示词主体prompt.md逐节拆解以下是 prompt.md 的核心内容按原文脉络展开并在对应位置补充仓库中的实现佐证。2.1 使命声明只用真实数据缺源即跳过提示词开头给出唯一使命在用户一天开始时用一份简明、可执行的摘要帮助他清晰启动。两条原则被反复强调拉取真实数据不虚构、不假设Pull real data — dont fabricate or assume数据源未连接时优雅跳过If a data source isnt connected, skip it gracefully。这与后文 Tone 一节Honest about gaps拿不到日历就明说 Calendar not connected而不是假装没有日程首尾呼应构成整份提示词的诚实性基线。2.2 内容清单按优先级排序的五类信息提示词规定简报内容按如下优先级组织这也是模型在信息冲突或篇幅受限时裁剪的依据优先级内容关键约束1Calendar— 今天的会议、通话、日程关注 lead time提前量、冲突、值得注意的空档2Tasks action items— 近 24h 内创建或变更的待办、今日截止项、逾期项系统已将任务工具结果限制在 24h 窗口内composio_execute返回什么就应视为近期不要试图重拉整个 backlog3Important emails / messages— 时间敏感或来自关键联系人的未读线程不要罗列所有 newsletter4Crypto / market context— 隔夜显著行情、清算事件、今日截止的治理投票仅限 2-3 条且以用户确实关注市场为前提5Recent memory— 近 24h 内各连接源实际发生的事对话、线程、活动以及已到期的承诺如你说过周三前完成提案以 24h 窗口为准其中第 2 条特别点出一个重要的工程约定系统已经限制任务工具结果到 24h 窗口。这并非提示词的空口承诺而是有真实实现支撑的——见后文 task_window.rs 的任务时间窗收窄机制。2.3 数据获取协议三段式工作流提示词用How to gather data一节规定了三步取数流程第一步近 24h 记忆。调用memory_tree工具的mode: cover_window参数为since_ms now − 24h、until_ms now均为epoch 毫秒当前时间取自随消息提供的Current Date Time:行——提示词明确要求用那一行算出 since/until而不是让模型自己猜时间返回值是覆盖该窗口所需的最小节点集整段落在窗口内的区域返回浓缩摘要condensed summaries否则返回原始近期消息raw recent messages按 source 分组、旧→新排序这被声明为权威的近记忆上下文——全量记忆 blob 被刻意不注入因此模型do not rely on it若只需单一来源可传source_id/source_kind过滤。仓库中对应的 agent 侧工具包装器是 cover_window.rs 中的MemoryTreeCoverWindowTool工具名memory_tree_cover_window其参数 schema 与提示词描述完全一致{ type: object, properties: { since_ms: { type: integer, description: Inclusive window start, epoch-milliseconds. }, until_ms: { type: integer, description: Inclusive window end, epoch-milliseconds. }, source_id: { type: string, description: Exact source id (e.g. slack:#eng, gmail:abc). }, source_kind: { type: string, enum: [chat, email, document] }, limit: { type: integer, minimum: 0, description: Max hits to return (default 200). } }, required: [since_ms, until_ms] }工具描述同样自述其用途Use for time-bounded recaps (e.g. a last-24h morning brief) instead ofquery_source(which is all-time)——与提示词最小覆盖集 vs 全量查询的表述互为印证。实现上还有一个细节source_id可能携带 PII因此日志只记录其是否存在而不记录值见 cover_window.rs 中的has_source_id{}调试日志。第二步实时数据。用composio_list_connections查看已连接的集成对每个相关集成日历、邮件、任务管理器依次composio_list_tools→composio_execute拉取今日数据。第三步对账。24h 记忆告诉你发生了什么实时调用告诉你现在排了什么/什么未读——不要重复上报同一条目。这一步是提示词里最容易被忽略、但对输出质量最关键的一条去重规则。2.4 消息结构从问候到收尾的四段式提示词要求简报读起来像私人助理的便签而不是原始数据倾倒并规定了严格的组装顺序个性化问候。必须按名称呼用户。名字取自本提示词中的## User块- name:字段若像真实名字只用 first name若该块缺失、或值看起来像 handle/邮箱片段则退回不带名字的温暖问候不猜测。要求逐日变换问候语且与Current Date Time:行上的实际本地小时匹配——下午或晚上不许说 good morning。界定范围Frame the scope。问候后紧跟一句白话导入说明简报同时覆盖最近发生了什么与今天将要发生什么。只允许给真实的过去活动recent-memory recap挂上 last 24 hours / since yesterday 标签即将到来的会议、未读邮件、未完成任务属于当前或未来事项不能标成过去 24 小时事件。且不得声称自己没有实际取过数据的窗口。结构化正文。按固定顺序组织为四个桶buckets且只渲染有实际内容的桶空桶连标题都不出现真正平静的一天可收敛为一行 nothing pressing came up而不是搭空架子Highlights— 今天最重要的消息、线程、会议或事件Action items— 需要回复、决策或已到期/逾期的一切以用户必须做什么打头Mentions— 用户被直接 或被要求出面的消息/线程FYI— 知道即可、无需行动的低优先级更新市场背景、环境活动。可选收尾。合适的场合加一句简短温暖的 sign-off如 Have a great day — tell me if you want to dig into any of these限一行简报已经很紧凑时省略。2.5 语气与格式200–400 词的咖啡时间阅读Warm but efficient像助理而非机器人反例 Good morning! Here is your briefing.也不过度闲聊Scannable清晰的标题或列表用户 30 秒内能扫完全文Actionable说用户可能想做什么而不只是存在什么Honest about gaps取不到数据就直说不伪装Brief全文目标200-400 词。2.6 硬性规则Rules永不虚构事件、邮件或任务——只包含实际从工具或记忆中取回的数据尊重时区——Current Date Time:行携带用户本地日期时间与 IANA 时区直接读它不得反问用户时区仅当该行确实缺少该字段时才退回 UTC 并加说明拒绝陈旧数据——工具调用失败或返回空时如实说明不得回退到昨天的数据忠于时间线——cover_window查询已把近记忆限制在最近 24h其内容可视为真实近期但每条命中都携带真实time_range应按发生顺序旧→新呈现。对于从更长生命周期笔记或实时工具结果中带过来的条目与今日日期比对早于简报当日的必须显式点名日期如 from your May 25 note…不得伪装成今天的事隐私优先——不放入完整邮件正文或消息内容只总结发件人与主题。三、装配链路prompt.md 如何变成模型看到的系统提示词3.1 构建顺序与 KV cache 约定prompt.rs 中的build(ctx: PromptContext)是最终产物——注释明确写着输出即 LLM 所见runner 不做后处理。其拼装顺序为ARCHETYPE——即include_str!(prompt.md)编译期内嵌的整份提示词见 prompt.rs 的const ARCHETYPErender_user_files用户文件段非空才追加render_tools可用工具清单render_workspace工作区信息render_ambient_environment——放在最尾部。源码注释解释了原因该块内嵌Local::now()导致内容每轮都变因此按SystemPromptBuilder::with_defaults的 KV cache 约定置于提示词末尾最大化前缀缓存命中它同时携带宿主运行时信息、用户身份## User块与当前日期时间直接对应 issue #926——桌面应用明明知道时区简报代理却还问用户你在哪个时区的修复。提示词正文中反复引用的Current Date Time:行、## User块的 name/email 字段正是这一装配步骤的产物——提示词作者能放心写从这一行读时间/从## User块读名字因为装配代码保证了它们的存在。3.2 测试把提示词规则钉死prompt_tests.rs 用一组断言把关键行为固化进 CI任何后续对 prompt.md 的编辑若丢掉这些要素都会直接失败build_includes_runtime_and_datetime_sections断言产物包含## Runtime与## Current Date Time两个小节且日期时间小节中包含match the actual local hour的接地规则针对 #926 / #3602问候必须锚定真实时钟具体的现在由每轮用户消息注入测试因此只钉住规则而非易变的时间戳prompt_pins_personalisation_and_structure_rules断言 ARCHETYPE 中必须含 by name按名问候、Frame the scope范围界定以及**Highlights**/**Action items**/**Mentions**/**FYI**四个输出桶针对 #3806build_includes_user_identity_when_present当认证缓存已填充user_identity时产物必须出现## User、- name: Ada Lovelace、- email: adaexample.com并且断言全文不含 token——身份块按构造只携带 id/name/email 三个字段任何未来加字段的行为都会强制更新这个测试build_omits_user_section_when_identity_unset无身份CLI 流程、未登录会话时## User段必须缺席——这正是提示词中若该块缺失则退回不带名字问候分支的现实触发条件。四、配置项与配套机制源码佐证4.1 agent.toml 的关键参数agent.toml 各字段的取值都有明确动机字段值作用temperature0.5汇总型任务比纯创造性低比机械抄录略高max_iterations8工具循环上限——够完成cover_window 逐集成 list/execute的多轮取数sandbox_moderead_only简报只读不执行有副作用的操作omit_identity/omit_memory_context/omit_safety_preamble均为true见下方专述[model].hintagentic路由到具备工具调用能力的模型档位[tools].wildcard{}技能skill类别通配——代理需要自行发现并调用用户所连集成日历、邮件、任务等的任意 Composio 动作其中三个omit_*开关的注释把设计取舍写得非常直白The brief pulls its recent memory itself viamemory_tree_cover_window(last 24h, source-grouped). We therefore suppress the injected all-time memory blob (## User Memory, the namespace root summaries): it is stale relative to today and would compete with the fresh windowed tool result. Identity/safety boilerplate stays off too — the prompt carries its own voice.这与 prompt.md 中the all-time memory blob is intentionally NOT injected, so do not rely on it形成提示词与装配代码的双向契约提示词告诉模型别依赖全量记忆omit_memory_context true保证全量记忆确实不在场。身份样板被关掉也是因为这份提示词自带完整的人格设定Your mission 一节即其 voice。4.2 近 24h 任务承诺的底层实现提示词对模型说系统已经限制任务工具结果到 24h 窗口别重拉 backlog——实现位于 task_window.rs。该模块的头部注释交代了背景与分层cron runner 为简报这一轮安装current_task_recency_window对应 harness/task_recency_context.rs 中的任务局部窗口第一层尽力而为的服务端收窄apply_window_args在调用方未提供时注入 provider 能理解的排序 /*_since参数——只减少载荷、改善排序正确性不依赖它且调用方显式值优先第二层权威的客户端后过滤filter_response丢弃时间戳早于now - window的行这才是真正的执行层优雅降级哲学只处理响应结构已验证的 slug未知 slug 退化为不过滤不可解析的时间戳按保留处理——never a crash and never a silently-emptied result若后过滤删了行会清掉markdown_formatted字段避免 agent 读到过滤前 stale 的整 backlog markdown 而忽略过滤后的 JSON。也就是说提示词里treat whatcomposio_executereturns as recent by construction这句话背后是两层收窄 明确的降级策略而非模型的自觉。4.3 注册与投递闭环把前几节串起来完整链路是注册loader.rs 将morning_briefing的 toml 与prompt::build注册进内置代理表种任务cron/seed.rs 在 onboarding 后幂等种入0 7 * * *的禁用任务SessionTarget::Isolated proactive 投递用户 opt-in 后由cron.update_job启用触发调度器到点启动独立会话为简报轮次安装任务近因窗口装配提示词prompt::build按 archetype → user files → tools → workspace → ambientRuntime/User/Current Date Time 置尾 的顺序拼出系统提示词执行模型按 prompt.md 的三段式协议取数cover_window → composio 实时 → 对账产出 200–400 词、四桶结构的简报投递mode: proactive交付交由 channels 模块路由到用户活跃频道best_effort保证投递失败不阻塞。五、可借鉴的设计要点从这份提示词及其配套源码中可以提炼出若干在构建个人助理类定时代理时值得复用的模式窗口化记忆替代全量注入用最小覆盖集的cover_window检索代替向提示词塞全量记忆 blob既省 token 又避免相对今天而言是陈旧的上下文与新鲜工具结果互相竞争——提示词侧声明不依赖全量记忆配置侧omit_memory_context true兑现承诺两边必须成对出现把系统保证写进提示词提示词敢于说任务结果已是近 24h前提是 task_window.rs 真的在composio_execute层做了后过滤。提示词中的每一条你不必/不需要做 X都应能对应到一段真实实现时间接地grounding三层防御Current Date Time:行提供时钟避免反问时区、问候必须匹配真实本地小时#3602、跨日条目必须显式点名日期——测试钉住规则而不钉死时间戳兼顾了现在每轮注入导致的易变性易变内容置尾携带Local::now()的环境块放在系统提示词末尾保护前缀 KV cache 命中这是把 LLM 服务成本约束写进提示词布局的工程实践用测试做提示词回归防线prompt_tests.rs把按名问候、范围界定、四个输出桶、身份块无 token 字段固化为断言使提示词从文档升级为受 CI 保护的契约——对任何把核心行为编码在 system prompt 中的代理都值得照搬默认禁用的 opt-in 主动任务主动式推理有成本seed.rs 用创建即禁用保证未启用的用户不产生任何推理账单同时保留一次性原子插入避免竞态。综上Morning Briefing 的 prompt.md 并不只是一段自然语言描述而是与 agent.toml 的上下文裁剪开关、prompt::build的装配顺序、memory_tree_cover_window的窗口检索、Composio 任务近因过滤以及 cron 的 opt-in 投递共同构成的一套提示词—实现—测试三位一体的工程产物。阅读这篇提示词的正确方式是把它当作接口语法它承诺的每一条行为都能在仓库中找到对应的代码兑现或测试钉扎。【免费下载链接】openhumanOpenHuman is an open source personal AI for Mac, Windows and Linux — local-first memory, agent orchestration, and deep research.项目地址: https://gitcode.com/GitHub_Trending/op/openhuman创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。