news 2026/9/10 8:07:22

OpenHuman Context Scout 深度解析:只读预检代理如何用 `[context_bundle]` 为编排器压缩上下文

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
OpenHuman Context Scout 深度解析:只读预检代理如何用 `[context_bundle]` 为编排器压缩上下文

OpenHuman Context Scout 深度解析:只读预检代理如何用[context_bundle]为编排器压缩上下文

【免费下载链接】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

导读

本文围绕 OpenHuman 内置代理 Context Scout(context_scout)展开,它是一类"只读预检"(read-only pre-flight)代理:在被编排器(orchestrator)执行首轮任务之前,先以极低成本完成记忆、用户画像、已连接集成与联网信息的收集,并返回一个紧凑的[context_bundle]数据包。读完本文,你将掌握该代理的三段式工作流、六大只读信息源、输出契约的每个字段语义,以及它在 agent.toml 与 prompt.rs 中的实现细节与安全设计。

一、设计定位:为什么需要"预检代理"

在 OpenHuman 的多代理架构里,编排器承担"思考并行动"的职责,但它每轮可用的上下文窗口是有限的。如果每收到一个用户请求,编排器都自行去翻记忆、查技能、扫集成列表,既浪费 token,也容易把上下文撑爆。Context Scout 的定位正是把"收集上下文"这一步从编排器中剥离出来、前置到一个廉价只读代理上

从 agent_prepare_context.rs 的模块注释可以看到两种触发方式:

  1. agent harness 首轮前自动触发:在编排器第一个 turn 之前,harness 先跑一次 Context Scout 完成预检;
  2. 父代理显式请求:父代理通过调用agent_prepare_context工具("plan mode as a subagent"),同步地、阻塞式地跑一遍 Context Scout,获得一次临时(ad hoc)上下文收集。

无论哪种方式,Scout 的输出都受max_result_chars(约 1000 tokens)上限约束,因此父代理的上下文只会以有界的方式增长——这正是该设计的核心收益:用一次廉价预检,换取编排器后续每一轮都站在"信息充分"的起点上。

二、工作流程:收集 → 汇总 → 推荐,然后立即停止

Scout 的角色提示词 prompt.md 明确给出了三段式工作流:

  1. 读取请求:读取传入的请求,以及调用方可能附加的[Focus]指令,明确本次预检的靶心。
  2. 只读收集:仅收集"采取行动真正需要"的信息,而不是漫无目的地罗列。
  3. 及时停止:一旦信息足够就立即产出结果——绝不尝试回答请求或执行任务,那是编排器的职责。Scout 拥有的每个工具都是只读的,它从不写、不发送、不安装、不执行任何动作。

这一点在 agent.toml 中有硬约束兜底:sandbox_mode = "read_only",并且工具白名单全部是只读工具(详见第五节)。从源码结构看,Scout 被声明为agent_tier = "worker"叶子 worker:它只收集并停止,从不向下委托(没有[subagents]块,加载器会在 worker 层拒绝任何子代理)。

三、六大只读信息源

Scout 的收集面覆盖六个来源,每一条都映射到具体的只读工具:

信息源工具/载体用途与注意点
记忆(Memory)memory_recall(按 namespace + query 检索);memory_flavour(读取用户风格/偏好画像的一个 facet)只读,绝不能写记忆。memory_flavour的 facet 包括 communication、coding_style、stack、workflow、environment、directives、anti_preferences,当请求依赖"用户喜欢怎么工作"而非某个具体事实时优先使用它
历史对话(Past conversations)经由memory_recall间接访问thread_*系列与transcript_search工具已被移除,因此"用户之前说过什么"只能通过记忆检索触达,而不是线程索引
目标/画像(Goals / profile)注入在 prompt 中的PROFILE.mdMEMORY.md这两份用户文件会随系统提示词一起注入(omit_profile = falseomit_memory_md = false),Scout 直接从中挖掘用户声明的目标与偏好
技能(Skills)list_workflows(列出已安装技能);skill_registry_search/skill_registry_browse(检索技能注册表)若技能明显契合请求,则在recommended_skills中上报,交由编排器运行或安装
已连接集成(Connected integrations)系统提示词中的 Connected Integrations 区块直接告诉 Scout 哪些平台(gmail、notion、slack 等)真实接线可用,用于判断请求是否可由某个已连接应用处理
网络(The web)web_search_tool/web_fetch仅当请求真正依赖新外部事实时才使用;记忆/画像已覆盖时跳过——Scout 被要求"保持廉价"(cheap)

其中记忆检索的底层实现与编排器的记忆工具同源:Scout 的memory_recall走的是 memory/api/provider/retrieval.rs 提供的检索能力(该模块同时承载FastRetrieveQuery快路径,命中数上限为MEMORY_FAST_PATH_LIMIT = 8),但 Scout 侧只暴露只读接口。

四、输出契约:严格单一[context_bundle]数据块

Scout 的产出被约束为唯一一个[context_bundle] … [/context_bundle]数据块,块外不允许有任何前言或收尾散文。其完整模板如下:

[context_bundle] has_enough_context: true|false proposed_goal: <ONE single line — the durable objective this thread should pursue (what "done" looks like), or `none` for a trivial/one-shot request that needs no goal. Keep it on this one line; the harness only reads the text on the same line as `proposed_goal:`.> summary: <≤ ~700 tokens of distilled, source-attributed context. Lead with what matters. Attribute facts: (memory), (transcript: <thread>), (profile), (web: <url>), (integrations).> recommended_tool_calls: - tool: <exact orchestrator tool name from the "Orchestrator tools" list> args: <concrete arg values or a tight sketch> why: <one line> recommended_skills: - skill: <runnable id — for installed skills the `dir_name` slug from list_workflows (NOT the display name), since run_workflow resolves by that id; for registry hits the installable entry id from skill_registry_search> installed: true|false why: <one line — why this skill fits the request> [/context_bundle]

各字段语义如下:

  • has_enough_contexttrue表示编排器此刻即可行动、无需再收集;false表示关键事实仍缺失(须在 summary 中说明缺什么)。
  • proposed_goal:线程的持久目标("完成"的样貌),而非步骤清单。harness 仅在线程尚未设置目标时才将其记录为线程目标——编排器仍保有权威并可后续细化。对闲聊或一次性琐碎请求,填写none即可,不值得记录目标。注意该字段的解析约定:harness 只读取proposed_goal:同一行上的文本,因此目标必须压缩在单行内。
  • summary:不超过约 700 tokens 的蒸馏摘要,要求先讲重点,并为每条事实标注来源:(memory)(transcript: <thread>)(profile)(web: <url>)(integrations)
  • recommended_tool_calls:按编排器应执行的顺序排列的推荐调用。每个tool必须是下方注入的 "Orchestrator tools" 列表中的精确名称——这些是编排器能调的工具,而不是 Scout 自己用过的工具。若已信息充分且答案属知识型、无需更多调用,则返回空列表并置has_enough_context: true
  • recommended_skills:明确契合请求的技能(工作流)清单。已安装技能使用可运行 id——即list_workflows返回的dir_nameslug(而非显示名),因为run_workflow按该 id 解析(installed: true);注册表命中的技能使用skill_registry_search返回的可安装条目 id(installed: false)。仅当技能真正匹配时才包含,否则整节省略或留空,绝不虚构技能 id

整个 bundle 有预算上限,应把预算花在 summary、plan 与真正匹配的技能上,而不是含糊其辞的修饰语上。

五、agent.toml配置逐项剖析

agent.toml 是 Scout 的完整定义文件,关键配置项如下:

id = "context_scout" display_name = "Context Scout" when_to_use = "Pre-flight context collector. Reads memory, the user's goals/profile, connected integrations, and the web, then returns a tight context bundle plus a recommended plan of next tool calls. Read-only; produces a structured bundle, not actions." temperature = 0.3 max_iterations = 8 iteration_policy = "extended" max_result_chars = 5000 sandbox_mode = "read_only" agent_tier = "worker" omit_identity = true omit_memory_context = true omit_safety_preamble = true omit_profile = false omit_memory_md = false [model] hint = "burst" [tools] named = [ ... ]
  • temperature = 0.3:低随机性,保证预检输出稳定、可复现。
  • max_iterations = 8iteration_policy = "extended":注释说明从 6 提升到 8——Scout 如今拥有更宽的只读收集面(transcripts、threads、skills),需要多几步完成"recall → check skills → assess"再产出 bundle 的循环。
  • max_result_chars = 5000:返回 bundle 的字符上限(char-safe)。runner 在交还给父代理前会把最终输出截断到这个长度,从而保证编排器上下文只增长有界量。该值从 4000 提升,为recommended_skills块与 summary、recommended_tool_calls留出空间。
  • sandbox_mode = "read_only":沙箱只读,配合工具白名单构成双重防护。
  • agent_tier = "worker":叶子 worker 层级,禁止向下再委托子代理。
  • 四个omit_*开关omit_identity = trueomit_memory_context = trueomit_safety_preamble = true去掉身份、通用记忆上下文与安全前言;但omit_profile = falseomit_memory_md = false保留PROFILE.md(用户声明的目标)与MEMORY.md(档案员策展的长期记忆)注入——因为 Scout 的整个职责就是让编排器扎根于"用户是谁、想要什么"。
  • [model] hint = "burst":多步收集循环(recall → 可能 fetch → assess)走高通量的burst层(托管后端解析为burst-v1)。设计意图是:Scout 是廉价、延迟容忍、非推理的预检,高速模型上的原始吞吐优于更贵的 agentic/reasoning 层。

工具白名单的取舍艺术

[tools].named是精心策展的只读收集面,没有写工具、没有 shell、没有委托。特别值得注意的是memory_tree故意排除:该工具在一个 ReadOnly 声明的包装器下捆绑了写模式(ingest_documentMemoryTreeIngestDocumentTool),若 Scout 自动运行在可注入的输入上,一旦拿到该工具,就可能"边运行只读、边改写记忆(remember this document)"——这等于给提示注入留下立足点。因此用纯检索的memory_recall覆盖需求。同理,skill_registry_install/skill_registry_uninstall被刻意挡在白名单外,只保留三个只读技能工具。

六、系统提示词构建:prompt.rs的组装流程

prompt.rs 负责在运行时把角色 Markdown 与动态注入块拼装成最终系统提示词。其build()流程为:

  1. include_str!("prompt.md")加载角色提示词(即本文解析的这份文档本体);
  2. 调用render_user_files注入PROFILE.mdMEMORY.md(由include_profile/include_memory_md门控,runner 依据定义的omit_profile = false/omit_memory_md = false设置);
  3. 调用render_tools渲染 Scout 自己的只读工具目录;
  4. 调用render_connected_integrations渲染## Connected Integrations区块——只列出connected == true的平台,空连接时整块省略(见prompt_tests.rsrender_connected_integrations_lists_only_connected测试);
  5. 调用render_workspace追加工作区块。

而"编排器的工具目录"(Scout 推荐回去的那份)不在这里注入——它由AgentPrepareContextTool在 spawn 时注入,prompt.rs只描述 Scout 自身的收集面。二者职责分离非常清晰。

七、与编排器协作的两个实现细节

1. 跳过通用子代理结果契约

通用子代理会被追加一个 "Result Contract" 后缀(Answer / Evidence used / Actions taken / Open uncertainties / Failed tool calls / Recommended next step)。但在 subagent_runner/ops/prompt.rs 的append_subagent_role_contract中,对context_scout做了特判跳过:因为 Scout 定义了自己的严格输出契约(只发一个[context_bundle]),通用契约会与之冲突,导致 Scout 输出通用标题而非 bundle,使编排器拿不到has_enough_context/recommended_tool_calls

2. 有界上下文注入

agent_prepare_context.rs 明确记载:Scout 的输出被max_result_chars约束到约 1000 tokens,父代理上下文只增长有界量。结合 runner 中的截断逻辑,这是整个"预检"设计能够规模化运作的保障。

八、测试验证与质量保障

prompt_tests.rs 锁定了以下行为:

  • build_returns_nonempty_body:构建的提示词非空;
  • body_describes_the_context_bundle_contract:提示词必须包含[context_bundle]has_enough_contextrecommended_tool_calls契约关键词;
  • body_instructs_transcript_and_skill_gathering:提示词必须指引通过memory_recall检索历史对话(因thread_*/transcript_search已移除)、必须定义recommended_skills输出块、必须指向list_workflows技能发现;
  • render_connected_integrations_*:集成区块只列已连接平台,全空时返回空字符串。

这些测试与 loader.rs 中对context_scout的定义加载校验、以及agent_prepare_context_tests.rs对显式调用路径的测试共同构成质量网,防止后续改动悄悄破坏预检契约。

九、延伸阅读

  • 代理定义与注册:loader.rs、agents/mod.rs
  • 提示词构建基础设施:src/openhuman/agent/context/prompt.rsrender_toolsrender_user_filesrender_workspaceConnectedIntegration等均在此)
  • 显式调用工具:agent_prepare_context.rs 及其测试
  • 子代理运行器:subagent_runner/ops/runner.rs(层级门控tier_gate_decision与迭代预算)、subagent_runner/ops/prompt.rs(契约跳过逻辑)
  • 记忆检索后端:src/openhuman/memory/api/provider/retrieval.rs

小结

Context Scout 是 OpenHuman 多代理体系中"以廉价预检换有界上下文"的关键实践:一条严格的角色提示词 + 一份精心配置的agent.toml+ 一个模板化构建器,共同保证了它只收集、不行动、产出唯一[context_bundle],并把"下一步该调用编排器的哪些工具"以结构化形式交还父代理。理解它,也就理解了 OpenHuman 如何在多代理协作中控制上下文成本与注入面。

【免费下载链接】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),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/10 8:03:07

CANN/ge Graph Engine InferValueRangeFuncRegister API

InferValueRangeFuncRegister构造函数和析构函数 【免费下载链接】ge GE&#xff08;Graph Engine&#xff09;是面向昇腾的图编译器和执行器&#xff0c;提供了计算图优化、多流并行、内存复用和模型下沉等技术手段&#xff0c;加速模型执行效率&#xff0c;减少模型内存占用。…

作者头像 李华
网站建设 2026/9/10 8:03:05

CANN/GE IR输入定义结构体

IrInputDef 【免费下载链接】ge GE&#xff08;Graph Engine&#xff09;是面向昇腾的图编译器和执行器&#xff0c;提供了计算图优化、多流并行、内存复用和模型下沉等技术手段&#xff0c;加速模型执行效率&#xff0c;减少模型内存占用。 GE 提供对 PyTorch、TensorFlow 前端…

作者头像 李华
网站建设 2026/9/10 8:02:11

量化交易必备:AutoHedge自动对冲系统设计与实现

做量化的朋友应该都有过这种体验&#xff1a;策略本身跑得好好的&#xff0c;但隔三差五就要被极端行情教训一顿——单边拉涨不敢追&#xff0c;瀑布式下跌舍不得割&#xff0c;仓位稍微重一点&#xff0c;晚上觉都睡不踏实。我前前后后折腾了大半年&#xff0c;试过手工加减仓…

作者头像 李华
网站建设 2026/9/10 8:01:46

CANN/GE图引擎MallocAdvise接口

MallocAdvise 【免费下载链接】ge GE&#xff08;Graph Engine&#xff09;是面向昇腾的图编译器和执行器&#xff0c;提供了计算图优化、多流并行、内存复用和模型下沉等技术手段&#xff0c;加速模型执行效率&#xff0c;减少模型内存占用。 GE 提供对 PyTorch、TensorFlow 前…

作者头像 李华