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

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

2026-09-09 20:34:13作者:齐添朝

导读

本文围绕 OpenHuman 内置代理 Context Scout(context_scout)展开,它是一类"只读预检"(read-only pre-flight)代理:在被编排器(orchestrator)执行首轮任务之前,先以极低成本完成记忆、用户画像、已连接集成与联网信息的收集,并返回一个紧凑的 [context_bundle] 数据包。读完本文,你将掌握该代理的三段式工作流、六大只读信息源、输出契约的每个字段语义,以及它在 agent.tomlprompt.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_name slug(而非显示名),因为 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.rsappend_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 对显式调用路径的测试共同构成质量网,防止后续改动悄悄破坏预检契约。

九、延伸阅读

小结

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

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.16 K
2.78 K
kernelkernel
deepin linux kernel
C
34
18
docsdocs
暂无描述
Markdown
904
5.83 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
934
1.86 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
862
1.36 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.96 K
1.03 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.38 K
1.47 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
535
606
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
549
398
leetcodeleetcode
🔥LeetCode solutions in any programming language | 多种编程语言实现 LeetCode、《剑指 Offer(第 2 版)》、《程序员面试金典(第 6 版)》题解
Markdown
77
23