mcpField
E
exploring-scouts

exploring-scouts

github.com/posthogAgent 工作流95156 次安装今天更新
代码仓库

关于 exploring-scouts

此技能帮助 Agent 通过只读 MCP 工具了解 PostHog 项目中的 Signals scout 配置、运行情况和产出。它还说明如何解读报告、结构化记录、运行元数据及无结果的运行。

主要功能

  1. 01列出 scout 配置与运行计划
  2. 02检查运行状态、摘要及报告
  3. 03查询 scout 的跨运行记忆和备注
  4. 04解读结构化输出与运行元数据
  5. 05识别无效运行及输出渠道状态

适用场景

  1. 01了解项目当前启用的 scout
  2. 02追踪某个 scout 的运行与报告
  3. 03比较提示词变更前后的运行
  4. 04排查 scout 未产生记录的原因

MCP 相关

该技能使用只读 PostHog MCP 工具检查项目资料、scout 配置与运行、记忆、备注及收件箱报告,不涉及写入操作。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/posthog/ai-plugin --skill exploring-scouts

安装后在 Claude Code 中输入/exploring-scouts确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
assessing-performance.md
scout-data-model.md
scripts/
assess_health.py
fleet_survey.py
render_run_report.py

详细介绍

探索 Signals 侦察器

侦察器是一种按计划运行的 Agent,会按自身的时间间隔唤醒,查看一个 PostHog 项目,判断哪些内容确实值得呈现,然后将其写入 Signals 收件箱,作为一份报告,或者以空结果结束(这也是一种真实且有效的结果)。 PostHog 提供了一组规范侦察器——一个跨产品通用侦察器(signals-scout-general),以及针对各个领域的专用侦察器(错误跟踪、日志、AI 可观测性、实验、功能标志、会话回放、Web 分析、调查等)。 一个项目也可能有自定义侦察器,即规范侦察器之外、由团队编写的任意 signals-scout-* 技能(例如 -brand-mentions、-mcp-feedback),它们也会显示在这里,因此不要假设侦察器列表是固定的:scout-config-list 是项目的权威列表。 (有一点需要注意:刚编写的侦察器在协调器下次运行并自动注册之前,或者有人通过写入端的 scout-config-create 注册之前,不会有配置行,因此新侦察器可能会暂时不在列表中。)

此技能完全通过只读 MCP 工具,帮助你了解和探索项目侦察器的运行情况及其表现。 它是 authoring-scouts 技能(讲解如何编写和调整侦察器)以及 inbox-exploration 技能(介绍侦察器生成的收件箱报告)的可观测性配套技能。 (侦察器工具最近已从 signals-scout-* 重命名为 scout-*;如果 scout-* 名称返回未知,服务端可能仍通过旧版 signals-scout-* 名称提供该工具——请搜索工具目录,并调用返回的名称。) 侦察器的输出是收件箱报告,按 1:1 编写。 侦察器会在其 allowed_tools 中列出 emit_report / edit_report,并且直接撰写或编辑收件箱报告;运行的输出会显示为 emitted_report_ids(其撰写的报告)和 edited_report_ids(其更新的报告)。 运行记录还包含 emitted_count / emitted_finding_ids——这些是已弃用的信号发出通道中的旧字段(由流水线汇总的弱 emit_signal 发现)。对于报告通道侦察器,即使运行很有成效,这些字段也会保持为 0 / 空;非零计数表示该运行来自仍使用旧通道的侦察器(旧版自定义侦察器,或尚未移植的规范侦察器)——这是该运行的真实输出,并非噪声。不确定侦察器使用哪个通道时,请通过 skill-get 查看其 allowed_tools。 绝不要把 emitted_count: 0 理解为“什么都没做”——先查看报告列和运行摘要。 配置中包含 structured_output_schema 的侦察器,除了报告之外还有第三种输出通道:经过架构验证的测量记录,在项目中记录为 $scout_structured_output 事件(只有顶层负载中的_标量_键会展平为 output_<key> 属性——对象和数组字段仅存在于完整的 output 属性中,因此缺少 output_<key> 并不代表值缺失;subject 用于命名受评实体),而不是记录为运行行中的列。 这些事件才是事实依据——metadata.derived.has_structured_output 表示该运行至少有一批记录已被接受。这是快速筛选单次运行的方式,但不能确认记录已送达(接受后罕见的捕获失败会导致该值为 true,但实际事件较少甚至没有),因此需要统计记录数量时,请直接统计事件。事件结构见 references/scout-data-model.md。 在 PostHog 提供的侦察器中,signals-scout-mcp-tool-calls 是会记录一系列数据的侦察器:每次运行只要发现 MCP 流量,就会写入按类别汇总的 MCP 工具健康状况,以及逐工具的会话占比行,无论它是否提交报告。因此,可以区分健康的类别和未测量的类别。 没有记录本身并不意味着通道已损坏。 如果项目近期没有 $mcp_tool_call 事件,该运行会提前停止且不记录任何内容;处于干运行状态的侦察器(emit 关闭)也没有可供记录的位置。 在判定通道损坏之前,请先检查运行摘要、not-in-use:mcp_analytics 暂存条目,以及配置中的 emit。 使用 event = '$scout_structured_output' 和 properties.skill_name = 'signals-scout-mcp-tool-calls' 查找这些事件;该侦察器自身的 references/metrics-dashboard.md 中提供了图表和告警配置方法。 每次运行还包含一个 metadata 映射。顶层字段包括来源信息 harness_prompt_version / report_channel(none、emit、edit 或 both)/ skill_origin / github_guidance,用于说明运行接收了哪些指令;还包括路由键(model / runtime_adapter / reasoning_effort / service_tier),仅在门控规则或固定设置覆盖默认值时出现。嵌套在 metadata.derived 下的是由运行框架在运行结束时计算的布尔值(has_emit_report、has_edit_report、has_self_improvement、has_chart、has_self_validation、has_structured_output、has_not_in_use_closeout)。 比较运行(例如提示词变更前后,或不同模型之间)时,先按全部四个来源值进行分组:harness_prompt_version、report_channel、skill_origin 或 github_guidance 中任一值不同的运行,接收的指令就不同,因此不能视为同类样本。早于这些字段的运行都不包含这些值,因此应将来源信息缺失视为未知,并从比较中排除,而不是合并统计。 对于“这是什么类型的运行?”之类的问题——例如是否撰写了自我改进报告,或是否验证了后续处理队列——请读取 derived,而不是解析摘要文本。该字段由服务端根据运行实际执行的操作计算,因此不会与运行自身的输出不一致——但有一个例外:has_structured_output 跟踪的是运行已接受的批次,而不是已送达的事件,所以该字段可能为 true,但实际记录较少甚至没有;如上所述,请统计事件。完全没有 derived 映射表示未知,而不是“全部为 false”——该运行可能早于此字段、在完成前失败,或写入标记失败。此功能上线前的大多数运行都没有该映射,因此不要把缺少映射视为一项发现。 要找出无意义的运行,请查看 has_not_in_use_closeout。当某次运行写入了 not-in-use: 速记条目(快速收尾时发现产品处于关闭状态),且没有生成报告、编辑、发现或结构化输出记录时,该值为 true。运行框架会将这次写入计入创建该条目的沙箱令牌所属的运行,因此,同一团队中其他侦察员的收尾不会计入本次运行。安静地检查过且一无所获的运行,此值为 false。某个侦察员的无意义运行率,是其已完成运行(包含 derived 映射的运行)中该标志为 true 的占比。可据此排定下一个要通过预检查进行拦截的侦察员,并确认上线预检查后该比率是否趋近于零。在此标志上线之前的运行没有 has_not_in_use_closeout 键,因此应将它们排除,而不是计为 false。

你可以通过各自的工具观察舰队的六个方面:

你想了解的内容工具工具提供的信息
哪些侦察员在运行、运行频率及运行状态scout-config-list每个侦察员一行:计划(run_interval_minutes 或 run_cron_schedule)、enabled、status / pause_reason、emit、output_destinations、write_scopes、mcp_gateway_server_ids、last_run_at、consecutive_failure_count、description、scout_origin、owners、tags
侦察员每次运行实际执行了什么scout-runs-list / -retrieve每次运行的状态、时间、运行结束摘要、emitted_report_ids / edited_report_ids;失败运行的 error / failure_reason;深层链接;通过 skill_name 限定范围
舰队在多次运行中学到了什么scout-scratchpad-search按团队持久保存的记忆(基线、噪声、允许列表)
团队向舰队传达了什么scout-notes-list人类 / Agent 留给侦察员的引导备注(针对单个侦察员或整个舰队,按时间从新到旧排列)
某次运行写入或编辑了哪些报告运行记录本身emitted_report_ids / edited_report_ids;通过 inbox-reports-retrieve 解析各个 ID
侦察员向用户展示了什么inbox-reports-list用户看到的侦察员生成的报告(单个侦察员使用 scout: "<skill_name>";整个舰队使用 source_product: "signals_scout")
scout-config-list 接受 tags 参数(以逗号分隔),可将名单缩小到带有任意指定标签的侦察器 — 当车队规模较大、问题仅涉及某个领域时很有用,例如 tags=revenue。
scout-runs-list 接受 skill_name(以及可选的 skill_version),可将数据限定到一个侦察器;对于任何关于单个侦察器的问题,这是常规做法,无需翻查整个车队。

用于了解项目概况的工具是 scout-project-profile-get — 这是每个侦察器冷启动时获取的“项目真实情况”确定性快照。 侦察器没有发现任何内容时,通常就是这个原因。

输出处理:做好将结果写入文件的准备

这两个工具 — scout-runs-list,尤其是 tasks-runs-session-logs-retrieve — 经常会返回超出 MCP 客户端令牌预算的负载,并将其写入文件。 这是正常情况,并非错误。 请提前做好准备,不要等调用失败后才发现这一点:

  • 将 limit 设小,在 scout-runs-list 中约为 10–15。 每一行都包含一段很长的 summary,而运行记录会按时间倒序返回整个车队的记录,因此即使是适中的分页,数据量也很大。
  • 会话日志天生就很大。 单次运行的日志有数百 KB 到数 MB。 使用 call --json 获取(这样保存的文件是真正的 JSON,而非美化后的文本格式 — 可用 jq 处理),并使用 jq / 脚本读取保存的文件,而不要直接内联读取。
  • 不要手动解析会话日志。 附带的 scripts/ 会为你重建日志 — 详见下文。

从这里开始:车队是否已配置?

不要假设项目中有侦察器。 车队仅在启用了 signals-scout 功能标志的团队中运行,而项目可能没有任何配置、所有侦察器都已禁用,或侦察器卡在试运行状态。 每当用户在会话中首次询问其侦察器时,都先运行此工具。

scout-config-list

根据以下三种情况解读结果:

配置列表未分页 — 返回格式为 { results: [...] }(裸数组),不包含 count 字段。 根据以下三种情况解读结果:

  • 为空(results: []) — 尚未注册任何侦察器。 该项目尚未加入侦察器集群(或尚未运行过)。 请如实说明;不要到处查找运行记录。 请引导用户前往 Signals 侦察器设置 / PostHog Desktop 入门流程,而不是凭空编造活动记录。

  • 存在配置,但所有配置的 enabled: false — 已注册侦察器集群,但目前已暂停。 当前没有任何任务在运行。 告诉用户有哪些侦察器,以及它们都已关闭;还要说明是谁关闭了每个侦察器,这由 status 表示:paused_by_user 意味着某个人(或启动种子配置)将其关闭,paused_by_system 意味着系统自动暂停,原因记录在 pause_reason 中(no_output / ignored / repeated_failures)。 两种情况都可通过 scout-config-update 将 enabled 设为 true 来恢复。 repeated_failures 暂停是故障熔断机制:计划运行连续失败次数(consecutive_failure_count;手动运行和工作流触发的运行不计入)超过了计划在 12 小时内可执行的次数,且该次数限制在 5–25 之间(每日计划:5 次,滚动每小时计划:13 次,每小时 cron:15 次;cron 时段按为适应夏令时转换而扩展的窗口计数)。该机制采用半开状态,因此协调器每天会探测一次侦察器,并在运行成功后恢复它(除非项目已达到启用的侦察器数量上限,此时即使探测成功,该记录仍会保持暂停);请查看最新运行记录的 failure_reason,了解持续失败的原因。

  • 至少有一个配置为 enabled: true — 已注册侦察器集群,且该侦察器获准运行。 对每个已启用的侦察器,说明其运行频率(如果设置了 run_cron_schedule,则使用该值;否则使用 run_interval_minutes;以 cron 为准)、emit(false = 试运行,会运行但不会向收件箱写入任何内容)和 last_run_at。 status 为 pending_pause 表示侦察器仍在运行,但系统已标记它即将暂停(原因记录在 pause_reason 中);任何配置编辑都会清除此警告。 在报告“它正在运行”之前,有一点需要注意:运行由 signals-scout 功能标志控制,而不是由 enabled 控制。 如果某个项目曾加入该功能标志,后来又被移出,该项目中 enabled: true 的记录会保留,但协调器不再为其安排运行——因此,已启用侦察器的 last_run_at 过期或为 null,通常意味着项目已不再加入,而不是侦察器处于空闲状态。

    last_run_at 是 派发 时间戳,并不能证明运行已执行。 对于到期的侦察器,协调器一将子工作流加入队列,就会更新该值——此时还没有任何工作进程接手运行。 子任务派发采用即发即弃方式,因此如果工作进程已饱和或不可用,子任务只会排队,永远不会实际运行,但每次调度周期中 last_run_at 仍会不断更新。 因此,较新的 last_run_at 表示“本次调度周期已派发”,而不是“确实有运行正在进行”。 权威的运行状态信号是 scout-runs-list 中最新的实际运行记录,而不是配置时间戳。 请交叉核对:如果 last_run_at 是最新的,但超过预期计划间隔后仍未出现该侦察器的运行记录,请在判断运行是否排队或滞留之前,检查记录的预检查结果。 不要仅凭 last_run_at 就报告“正在运行”。

    计划预检查可能会跳过任务,且不会生成运行记录。 首先读取配置中的 last_precheck_at 和 last_precheck_outcome,并按 authoring-scouts → references/scheduled-precheck.md → “Diagnose a tick with no run row”中的说明操作。 如果本次调度周期有近期记录的 skip,就可能是任务静默的原因;如果结果数据已过期或缺失,则原因仍不明确。 请将 scout-config-precheck-test 用于查询测试:现在执行的检查无法证明先前调度周期发生了什么,而且你的访问权限可能与计划检查的执行用户不同。 跳过一次并不能证明侦察器整体运行正常。

已启用(enabled: true)但 emit: false 的侦察器,是用户困惑“我的侦察器怎么什么都没做”的最常见原因:它确实会在每个调度周期运行并进行推理,只是尚未获准发布报告。 报告侦察器状态时,务必说明其 emit 设置。 有关配置、运行和便笺条目的所有字段、运行状态值,以及各部分如何关联,请参阅 references/scout-data-model.md。

工作流:巡查整支队伍

“我有哪些 scout / 它们在做什么?”——先调用 scout-config-list,再为每个 scout 补充最近一次运行的信息,让用户了解它们是否在正常运行,而不只是查看配置。

  1. scout-config-list——获取 scout 名单。
  2. 调用一次 scout-runs-list,并设置较小的 limit,然后按 skill_name 选出每个 scout 最新的运行记录(整个队伍的运行记录会按时间从新到旧返回,因此通常一次调用就能涵盖所有 scout);如果某个 scout 不在结果页中,则再次调用,并设置 skill_name。 报告 status 和运行距今多久。

将结果整理成便于用户浏览的表格,列出 scout、运行频率、运行方式、上次运行和上次结果,并指出任何异常情况(从未运行、上次运行出错、长时间停留在 dry-run 状态)。

工作流:全面了解一个 scout

“我的错误追踪 scout 是如何工作的 / 状况如何?”

  1. 读取配置——在 scout-config-list 中找到 signals-scout-error-tracking 对应的行:运行计划、运行方式和上次运行。
  2. 读取正文——posthog:skill-get {"skill_name": "signals-scout-error-tracking"} 会返回团队实际使用的指令集(可能是规范默认版本,也可能是经过修改、与默认版本不同的条目)。 这是每次运行时告知 Agent 要做什么的内容——包括它区分信号与噪声的方式、探索模式和排除条件。 要了解 scout _为何_会有这样的行为,请阅读其正文。
  3. 读取最近的运行记录:调用 scout-runs-list 并设置该 scout 的 skill_name(可添加 text 来搜索其摘要中的某个主题)。 每次运行结束时的 summary 是 scout 对其查看内容和决策的说明;运行失败时则会附带 failure_reason。
  4. 读取它记住的内容——调用 scout-scratchpad-search(见下文)。 scout 写入的记忆条目会展现它对该项目已内化的基准情况和噪声。
  5. 读取它收到的指示——scout-notes-list {"skill_name": "signals-scout-error-tracking"} 会返回人类留给该 scout 的指导备注,以及适用于整个队伍的通用备注——也就是它运行时实际读取的先前上下文。 每条备注都带有 origin:human 表示直接留下的备注;其他类型则表示由收件箱自动转发的派生备注:report_dismissal(忽略或延后处理的备注)、report_discussion(在报告的 Discuss 框中输入的问题)、report_feedback(留下赞或踩评分时附带的备注)、report_reviewer_correction(有人添加或移除了建议的审核者)。派生备注约 30 天后过期;由于其中引用了报告内容,没有报告读取权限(task:read)的调用者看不到这些备注,因此只有 signal_scout:read 权限的凭据只能看到人类留下的备注。 发给 pipeline:report-research 的备注会指导报告流水线的研究阶段,而不是此 scout,因此不会显示在这里。 行为变化如果无法追溯到技能编辑或便笺条目,通常就能追溯到某条备注。 如果用户要求通过备注来_指导_ scout(而非观察),请转交给 authoring-scouts 技能;该技能涵盖备注渠道的写入操作。

工作流:读取最近运行记录

scout-runs-list 会返回整个集群中最近的运行记录,按时间从新到旧排列(最多 100 条)。 用它来回答“最近发生了什么?”

  • 限定到某个 scout:使用 skill_name(并使用 skill_version 隔离某个主体版本的运行记录)。当问题涉及单个 scout 时,这是首选的限定方式。
  • 限定时间范围:使用 date_from / date_to(ISO-8601;按 created_at 筛选,包含下限、不包含上限)。 向前回溯时,传入更早的 date_to。
  • 搜索摘要:使用 text——对每条运行记录的运行结束时 summary 进行不区分大小写的子字符串匹配。 无头 scout 用这种方式去重;你也可以用它查找“是否已有运行记录检查过结账错误激增?”
  • 按输出筛选:使用 emitted——emitted=true 只返回至少撰写了一份报告的运行记录(或在旧版运行记录中,至少发出一条发现),emitted=false 只返回未撰写任何内容的运行记录。 这是直接回答“哪些运行记录实际写入了内容?”的方式,无需解析文字。 有个例外:只编辑了现有报告的运行记录不算作 emitted=true——在认为这类运行记录没有输出前,请检查 edited_report_ids。

每条摘要行都包含 run_id、skill_name、skill_version、status、started_at、completed_at、emitted_report_ids / edited_report_ids(运行记录撰写或编辑的报告,即其输出)、emitted_count / emitted_finding_ids(旧版信号通道的计数;当前 scout 中为 0 / 空)、task_url(指向 Tasks UI 的深层链接,可查看完整记录)、summary 摘要文字,以及在运行未正常完成时的 error(完整的 TaskRun 错误)和 failure_reason(简洁的推断说明)。 向用户叙述时,请以 summary 为主——这是 scout 用通俗语言写下的结尾说明;并且务必提供 task_url,以便查看完整推理过程。

工作流:深入查看单次运行

当用户想了解某次运行的完整情况(或粘贴了运行 ID / Tasks URL)时:

scout-runs-retrieve
{ "id": "<uuid>" }

注意字段名称的变化:scout-runs-list 将每条运行记录的 ID 作为 run_id 返回,但 scout-runs-retrieve 接收的字段名是 id。 将 run_id 的值作为 id 传入。

返回完整的运行记录:status、started_at / completed_at(根据这两个字段计算时长)、skill_name / skill_version(运行了什么、使用的是哪个主体版本)、运行结束时的 summary、emitted_report_ids / edited_report_ids、metadata 和 task_url。 记录——包括实际的工具调用和推理——位于 task_url 指向的 Tasks UI 中,不在此载荷里;用户想查看每一步时,请提供该链接。 失败的运行记录,其 summary 为空;请先查看 failure_reason(一行诊断,说明是运行预算超时、某个工具持续报错,还是沙盒始终未能启动),再查看包含完整 TaskRun 错误文本的 error。 这两个字段本身就能回答大多数“为什么失败了?”的问题;只有在需要了解导致失败的一系列调用时,才查看记录。

无需打开 UI:tasks-runs-session-logs-retrieve 会以数据形式返回运行记录的会话日志(每次工具调用、消息和推理步骤)——在诊断故障或想要追踪运行记录具体操作时很实用,无需离开当前对话。 将该运行记录的 task_run_id 作为 id,并传入它的 task_id(两者都在运行记录行中)。 原始流很大(从数百 KB 到几 MB),直接内联会溢出,因此请用 call --json 获取,并让内容写入文件,然后通过 scripts/render_run_report.py 处理,而不要手动解析。 该工具默认返回 100 条,每次调用最多返回 5000 条;分页状态不在响应正文中,因此请传入 limit: 5000 并重复请求,将 offset 增加前一页实际返回的条目数(而不是 limit),直到某一页返回空结果,然后在渲染前拼接各页内容。短页不代表已经到末尾,因为页面也可能在达到字节上限时提前结束;若按 limit 跨过这种页面,就会跳过遗漏的条目,因此只获取一个默认页面可能会漏掉失败记录。

⚠️ 不要用 exclude_types: "tool_call_update,…" 来精简内容。 这很诱人——流中大部分内容都是增量的 tool_call_update 块——但每个工具的实际输入只存在于这些块中:基础 tool_call 事件的 rawInput 为空,流式更新会逐个 token 地构建输入(以及最终的 rawOutput)。 排除这些块后,你只会看到工具的_名称_,却不知道侦察器实际查询了什么。 请获取完整日志,并让脚本重新组装每次调用(它按 toolCallId 分组,保留信息最丰富的 rawInput,并附上完成事件中的 rawOutput / status)。

运行是否写入了内容是一个一等字段:emitted_report_ids / edited_report_ids。 非空的 emitted_report_ids 会按顺序列出该运行通过 emit_report 撰写的报告;edited_report_ids 会列出该运行通过 edit_report 修改的报告(可针对收件箱中的任何报告,不限于侦察器撰写的报告)。 高效的运行通常会在其中列出一个 ID,并带有类似 Report authored: <id> 的摘要;可通过 inbox-reports-retrieve 查询任意 ID,以阅读报告正文。 不要从摘要的文字中解析输出——例如,“已报告 P1……未重新提交”这样的表述描述的是_先前_的运行,因此依靠摘要子串匹配并不可靠;ID 字段才是权威统计依据。 有一种侦察器会打破“没有报告 ID”就意味着“没有写入内容”这一对应关系:测量侦察器在正常运行时不会提交报告,因为其输出是记录流;因此,在判定此类运行为空之前,请检查 metadata.derived.has_structured_output(以及事件本身)。

旧版运行:emitted_count / emitted_finding_ids。 来自已弃用的信号发出通道的运行(未启用 allowed_tools 选项的侦察器——旧版自定义侦察器,或尚未移植的规范侦察器)会将输出统计为 emitted_count 个弱发现;每个 finding_id 都映射到一个 Signal,其 source_id = run:<run_id>:finding:<finding_id>。 仅针对这些运行,scout-runs-emission-reports(传入 run_id)会将每个发出的发现映射到其信号归入的收件箱报告(若未归入任何报告,则为 null)。 对于报告通道侦察器,这些字段始终为 0 / 空值——不要据此做出判断。 完整的字段参考请见 references/scout-data-model.md。

status 为 complete 且摘要为空手而归(“surface at baseline, nothing to report”)的运行是健康结果,而非失败——大多数运行都应该以无结果收尾。 应将一连串空结果视为整支侦察队正常履行职责,而不是出现故障。

工作流:检查侦察队的发现

便笺是侦察队持久化的团队级记忆——侦察器会写入其中的文字条目,让后续运行变得更聪明、更安静。 阅读它可以了解侦察队对这个项目的看法。

scout-scratchpad-search
{ "text": "error_tracking" }

按最新到最旧的顺序返回条目:默认 20 条,limit 最高为 1000;text 不区分大小写地匹配 content 和 key。 省略 text 可浏览全部内容;传入 keys_only=true 可快速扫描现有记忆,或传入 content_max_chars 预览较长的正文,并将 date_to 设为最旧条目的 updated_at,以便继续遍历超过上限的内容。 除非设置 include_expired=true,否则会排除已过期的条目(expires_at 早于当前时间);每个条目还包含 created_by_skill,即最初的创建者(探查器的技能名称,或流水线阶段的 pipeline:report-research / pipeline:implementation)。这是溯源信息,并不代表当前文本的作者:同一团队级键被其他写入者更新时,原始创建者和 created_by_run_id 都会保留,因此这两个字段都不能说明共享键的当前写入者;应将其视为未知,而不是把内容归功于该技能。 每个条目的 key 都带有类别前缀,用于说明这类经验的_类型_:

前缀含义
pattern:基线:该团队的数据通常呈现的形态
watch:正在跟踪但尚未达到报告标准的待处理问题
followup:探查器的验证队列:后续运行会重新执行探测,以确认修复有效或问题复现
noise:整个团队决定忽略的模式(仅开发环境、单个用户……)
addressed:团队已修复或不再关注的问题
dedupe:防止针对特定问题 / 指纹重复提交的门槛
allowlist:已审核、不应再次出现的实体
not-in-use:该团队不使用的产品 / 界面(结项备忘录)
mcp-gap:探查器发现、值得稍后提出的工具缺口
improve:自定义探查器建议对其自身技能正文进行的更改,等待所有者审核
reported:规范探查器记录的技能缺口,已向上游反馈给 PostHog
report:探查器编写的报告:存储 report_id,供后续运行据此编辑 / 去重
reviewer:已确定的区域负责人(GitHub 登录名),缓存后用于 suggested_reviewers 路由

这些是通用词汇,并非封闭集合——探查器会按需创建自己的前缀和 <domain> 标签(例如,当前运行的探查器大量使用 watch:),因此应将不熟悉的前缀视为另一种类别。 条目通过 [[key]] Wiki 链接相互引用。 键遵循 <prefix>:<domain>:<entity> 格式(例如 dedupe:error_tracking:019e8375-…)。

当用户问“为什么我的探查器不再标记 X 了?”时,请在便笺中搜索 noise:、addressed:、dedupe: 和 allowlist: 条目——整个运行中的探查器可能已刻意学会抑制它。 规范的前缀词汇和整个运行中的探查器采用的四态去重分类,记录在 authoring-scouts 技能的 references/dedupe-and-memory.md 中。 自定义 scout 会自我报告技能改进。 如果某次运行产生了具体证据,表明自定义(由团队编写的)scout 的技能正文误导了它,运行框架会邀请它写入一条 improve:<skill-name>:<topic> 条目,其中包含建议的更改、证据和带日期的观察记录;并在后续运行中就地重新确认该记录。 使用报告通道的自定义 scout 会进一步上报反复出现或影响重大的建议:它会提交一份关于自身的收件箱报告(标题为 Scout self-improvement: <skill-name> – <topic>),并将 report_id 存入 improve: 条目,以便最有力的建议像其他报告一样通过收件箱传达给所有者,而不只是写在草稿区。 评估自定义 scout 时,搜索 {"text": "improve:"},并向用户展示这些条目:在多次运行中重新确认的条目,是所有者可以进行的最有力改动。 审查并应用这些建议属于写入操作——请交由 authoring-scouts 技能处理。 规范 scout 永远不会写入 improve: 条目(它们的技能正文与 PostHog 的 fleet 同步),因此,规范 scout 的领域中若出现 improve: 条目,本身就值得标记。 相反,规范 scout 会通过 agent-feedback MCP 工具(feedback_type: "scout")向 PostHog 团队提交技能内容缺口,并进行泛化处理,以免传出项目数据;同时会保留一条 reported:<skill-name>:<topic> 条目,作为已提交内容的本地记录——因此,reported: 条目表明某个缺口已向 PostHog 提出,而不是向这个团队提出。

工作流:查看 scout 写了什么

Scout 的输出会以收件箱报告的形式呈现给用户。 按 scout 的技能名称筛选收件箱,指定多个名称时用逗号分隔:

inbox-reports-list
{ "scout": "signals-scout-error-tracking", "limit": 20 }

每一行还包含 scout_name,因此,查看整个 fleet 的页面时,可以知道每项内容由哪个 scout 撰写。 若要一次查看整个 fleet,可改为按来源筛选:{ "source_product": "signals_scout", "limit": 20 }。 Scout 撰写的每份报告都带有标记为 source_product="signals_scout" 的支撑信号;该筛选会保留其贡献信号中包含此标记的任何报告,因此结果就是整个 fleet 撰写的报告集合。 这两种筛选都不会涵盖仅编辑现有报告的工作:例如,scout 在某份管道报告中附加备注时,不会新增 signals_scout 信号,因此该报告不会匹配;应通过运行行中的 edited_report_ids 跟踪此类编辑。 默认情况下,已抑制的报告处于隐藏状态,因此在判断 scout 的输出有多少被过滤时,请添加 include_all_statuses: true(或 status: "suppressed")。即便如此,scout 和 source_product 筛选都无法找到被安全性评判器抑制的报告,因为两者都是通过信号解析报告,而不安全报告的信号永远不会被索引;要审计信号与噪声,运行行中的 emitted_report_ids 才是完整清单。

结果为空,意味着 fleet 尚未撰写任何报告(至少目前还没有),并不表示筛选器出了问题。 Scout 的标准很高——大多数运行结束时都不会写入内容——因此,对于不活跃或新加入的项目,没有 scout 报告是正常且符合预期的状态。 请注意,收件箱只显示已呈现的报告:被安全性评判器抑制的报告(或标记为 not_actionable 的报告)仍会以 SUPPRESSED 状态保留,但不会出现在默认收件箱视图中。 对于按运行查看的视图,请改为从运行记录入手:scout-runs-list?emitted=true 会列出所有撰写过报告的运行记录,每条运行记录的 emitted_report_ids / edited_report_ids 会准确列出其创建或更新的报告 ID——通过 inbox-reports-retrieve 获取这些报告。 解释缺口时,也要考虑另一面:运行记录可能会在 summary 中描述「撰写了一份报告」,但写入操作被预检门禁静默丢弃(当时处于 dry-run 模式、组织尚未批准 AI 处理,或 signals_scout 来源已禁用)——这类情况的 emitted_report_ids 会为空,因此,声称已创建却实际不存在的报告本身就是一条诊断线索。 若要更广泛地浏览收件箱,请使用 inbox-exploration 技能(状态、建议的审核者,以及深入查看报告的底层信号)。 每份报告背后的报告规范——报告门槛、证据、可执行性、审核者路由——记录在 authoring-scouts 技能的 references/report-contract.md 中。

报告的状态并不代表其全部情况:也要查看检查项。 检查项是 Scout 或报告流水线附加到报告上的后续测量——包含一项预期以及测试时间——因此,报告已解决时,检查仍可能在进行。 inbox-report-checks-list 会按时间倒序返回某份报告上的所有检查项,包括其 status(pending、active、passed、failed、errored、expired、cancelled)、last_outcome 和计划安排(next_run_at、run_interval_minutes、runs_remaining、expires_at);inbox-report-checks-retrieve 会返回某个检查项的完整配置。 按以下方式解读各行:

  • pending——检查项正在等待报告解决,之后才会开始计时。
  • active 且 next_run_at 在未来——即将得出判断。不要手动重新推导答案;说明结果将在何时出炉。
  • 其他所有状态均为终止状态。仍值得关注的主张需要新建检查项,这属于写入操作——请转交给 authoring-scouts。

判断结果本身不在检查项行中:每个结果都是报告上的一个 check_result 工件,因此请通过报告的工件列表读取。 对于无权读取其所描述数据的凭据,query 和 baseline_value 会显示为 null。 已解决报告上的 failed 检查通常也会有一份新报告与之对应(违规情况会作为关联到已解决报告的新报告再次浮现),因此在报告复发尚未处理之前,先查找是否有这类新报告。 完整机制——两种检查项类型、观察期,以及每种判断结果的后续处理——见 authoring-scouts 技能的 references/report-checks.md。

工作流:评估健康状况和性能

“我的 scout 真的在工作 / 值得花这笔成本吗?” 没有单一指标可以回答这个问题——应在一定时间范围内,根据多次运行评估 scout。 拉取运行记录(使用带有 date_from 的 scout-runs-list),然后根据以下维度进行判断。 完整的操作指南(包括如何解读各项信号和常见故障模式)见 references/assessing-performance.md。

  • 频率遵循情况:运行是否大致按照 run_interval_minutes 的间隔进行,或在每个 run_cron_schedule 时段启动? 对于 cron scout,应根据其时段而非间隔来判断:仅在工作日运行的 scout 周末没有运行是符合计划的,不代表停滞;assess_health.py 也会跳过对它的基于间隔的评分(其频率列显示为 cron)。 较大的间隔意味着协调器跳过了它(已禁用、因标记而耗尽,或在繁忙时段达到上限)——_或者_虽然已派发,但运行记录尚未生成。 使用 last_run_at 区分这两种情况:如果配置中的 last_run_at 也已过时,说明协调器已停止为其安排运行;如果 last_run_at 是最新的,但最新的运行记录已是数小时前的,则属于上述派发与执行不一致的情况(工作进程积压 / 停止运行,或运行被搁置);单靠 scout-runs-list 无法发现这一点。
  • 成功率——有多少次运行以正常的 status 结束,而不是报错? 连续报错意味着 scout 已损坏,而非运行较少;按 failure_reason 对失败的运行分组,查看是否有同一原因反复出现。
  • 报告率——有多少比例的运行写入或编辑了报告,而不是以无内容结束? 直接读取每次运行的 emitted_report_ids / edited_report_ids(或者使用 runs-list?emitted=true / ?emitted=false 拆分时间范围;注意仅编辑的运行会显示为未发出报告)。 对于活跃的信息源,长时间范围内报告率接近零,可能意味着判别条件过于严格(也可能是该信息源确实很安静);接近 100% 通常意味着噪声太多。 测量 scout 不应按此指标评分——报告率接近零是其设计行为,因此应查看其记录流。 大多数健康的 scout 很少写入报告。
  • 信噪比——它写入的内容中,有多少作为可执行的收件箱报告显示出来,而不是被抑制或忽略? 使用 inbox-reports-retrieve 解析每次运行的 emitted_report_ids 并查看报告状态——在一个时间范围内,已撰写报告中仍处于生效状态且未被抑制的比例,就是 scout 的命中率。
  • 记忆增长——健康的 scout 会随着时间推移积累 pattern: / noise: / dedupe: 条目。 多次运行后暂存区仍为空的 scout 并没有在学习。

辅助脚本

该技能在 scripts/ 下附带三个用于处理常见需求的纯格式化工具。 它们不会进行网络 I/O——它们属于“Agent 获取数据,脚本格式化”的后半部分。 流程始终相同:

  1. 使用 MCP,通过 call --json(原始 JSON,而非美化后的文本格式)获取每个数据载荷并保存到文件。 对于较大的数据(scout-runs-list、tasks-runs-session-logs-retrieve),这本来就是必需的——它们会超出内联限制并写入文件,你可以将该文件传给脚本。
  2. 使用这些文件运行脚本。

这三个脚本都只使用 Python 3.11+ 标准库,并将纯文本输出到 stdout(或 --out)——专为在终端中易于阅读而设计,因此请将输出保存为 .txt。

scripts/render_run_report.py — 深入查看单次运行

生成检查单次运行时所需的详细报告:标题(状态、时长、态势)、叙述式时间线,其中穿插 Agent 的叙述以及每次工具调用及其真实输入、运行结束摘要,以及任何暂存区记忆。

# fetch (note --json), saving each to a file:
#   call --json scout-runs-retrieve { "id": "<run_id>" }            -> run.json
#   call --json tasks-runs-session-logs-retrieve { "id": "<task_run_id>", "task_id": "<task_id>", "limit": 5000, "offset": 0 }  -> log.json   (FULL, no exclude_types; page with offset until an empty page, then concatenate)
#   (optional) call --json scout-scratchpad-search { ... }          -> mem.json
#   (optional) call --json scout-config-list {}                     -> cfg.json
python scripts/render_run_report.py --run run.json --log log.json \
    --scratchpad mem.json --config cfg.json --out report.txt

模式(--mode,默认为 detailed):

模式包含内容是否需要 --log?
summary标题 + 态势 + 收尾说明否
detailed+ 叙述式时间线(含工具输入)+ 工具统计 + 暂存区是
full+ 行内显示每次工具调用的(截断后)输出是

其他标志:--show-output(在详细模式下显示输出)、--input-width / --output-width(截断宽度)、--no-art(跳过刺猬横幅)、--base-url(默认为 us.posthog.com)。

scripts/fleet_survey.py — 调查整个集群

一张便于快速浏览的表格,列出侦察器、是否启用、态势、运行频率、上次运行和上次结果;另设“值得关注”部分,标记从未运行、一直处于干运行状态以及上次运行失败的侦察器。

#   call --json scout-config-list {}                 -> cfg.json
#   (optional) call --json scout-runs-list { "limit": 30 }  -> runs.json   (small limit!)
python scripts/fleet_survey.py --config cfg.json --runs runs.json --now <current-ISO-time>

传入 --now(当前时间,ISO-8601 格式)即可获取相对“之前多久”的列;上次结果列直接读取运行行中的 emitted_report_ids / edited_report_ids,显示该次运行写入的内容。

scripts/assess_health.py — 评估一段运行时间内的健康状况

实现上述“评估健康状况和性能”工作流:按侦察器列出表格(运行次数、成功率、报告率、相对于间隔的运行频率偏差、遵循度、中位时长、记忆增长),并设有“值得关注”部分,标记全部失败的侦察器、疑似超时的失败、运行频率停滞、数据过时以及空暂存区。

#   call --json scout-runs-list { "limit": 100, "date_from": "<ISO>" }  -> runs.json
#   (optional) call --json scout-config-list {}                          -> cfg.json
#   (optional) call --json scout-scratchpad-search {}                    -> mem.json
python scripts/assess_health.py --runs runs.json --config cfg.json \
    --scratchpad mem.json --now <current-ISO-time> [--skill signals-scout-general]

--config 用于评估运行频率遵循度(预期间隔;具有 run_cron_schedule 的侦察器会标记为 cron,不参与基于间隔的遵循度、停滞和过时标记)以及数据过时情况(权威的 last_run_at;当 100 行上限截断最新运行记录时,时间窗口内的运行记录可能会遗漏该值)。 不传入 --scratchpad 时,记忆列显示 n/a,且不会触发记忆相关标记。 报告率直接读取运行行中的 emitted_report_ids / edited_report_ids,因此数值精确——但只统计写入;请通过 inbox-reports-list 中的报告状态判断信号与噪声比。

提示

  • 始终说明 emit 姿态。“正在运行,但处于试运行模式”是用户误以为 scout 出故障的最常见原因。
  • **没有内容的收尾也表示成功。**大多数运行都应该一无所获。 不要把一连串干净的空运行报告为问题。
  • **运行写入的内容是运行的一项一等字段。**读取每次运行的 emitted_report_ids / edited_report_ids(或使用 runs-list?emitted=true 进行筛选),即可找到写入的内容,无需解析文字形式的 summary。 source_product: "signals_scout" 收件箱筛选器会列出整个 scout 集群发现的_报告_;结果为空,表示它尚未写入任何内容(scout 的门槛很高),而不是筛选器出了问题。
  • emitted_count: 0 并不表示“什么都没做”。emitted_count / emitted_finding_ids 是旧版信号通道字段——对于报告通道的 scout,无论有没有产出,这些字段都会保持为 0 / 空。 应根据报告列判断输出;旧版统计值非零,意味着该运行来自仍使用旧版通道的 scout,这就是该次运行的实际输出。
  • **持续约 15 分钟的 failed 运行通常是超时,而不是 scout 出故障。**每次运行的预算为 15 分钟;已完成的运行只需几分钟。 failure_reason 会明确说明是否超时,因此在根据时长推断之前先检查它。 最常见的情况是 scout 过度调查并耗尽了全部预算(集群会通过写入“紧凑运行方案”的暂存区条目来自我纠正)——但也有一些是误报超时:scout 实际上几分钟就已完成,之后运行却卡在丢失的收尾步骤上。 会话日志(上文)可以区分这两种情况:真正的过度调查会一直持续调用工具,直到时间耗尽;误报超时则会早早变得沉寂。 不要仅凭时长就认定是过度调查。
  • 先展示运行的 summary,再提供 task_url 以查看完整记录——不要把原始运行行直接丢给用户。
  • last_run_at: null 表示协调器从未调度过该 scout,并不表示它从未运行:手动运行(scout-run-now)和由工作流触发的运行不会更新这个时间戳,因此在认定 scout 从未运行之前,请先检查 scout-runs-list。然后确认它已启用且项目已加入;按 cron 调度的 scout 创建后也会等到第一个时段才运行。
  • 要解释 scout 为什么没有动静,请读取项目资料。scout-project-profile-get 会显示它监控的表面是否正在使用——没有日志的项目,其日志 scout 无事可做。
  • **此技能为只读。**要更改 scout 的计划、姿态或正文,请转交给 authoring-scouts 技能——该技能涵盖 scout-config-update 和 skills-store 编辑路径。

评论

支持 Markdown