关于 exploring-scouts
此技能帮助 Agent 通过只读 MCP 工具了解 PostHog 项目中的 Signals scout 配置、运行情况和产出。它还说明如何解读报告、结构化记录、运行元数据及无结果的运行。
主要功能
- 01列出 scout 配置与运行计划
- 02检查运行状态、摘要及报告
- 03查询 scout 的跨运行记忆和备注
- 04解读结构化输出与运行元数据
- 05识别无效运行及输出渠道状态
适用场景
- 01了解项目当前启用的 scout
- 02追踪某个 scout 的运行与报告
- 03比较提示词变更前后的运行
- 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.mdscout-data-model.mdscripts/assess_health.pyfleet_survey.pyrender_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 补充最近一次运行的信息,让用户了解它们是否在正常运行,而不只是查看配置。
scout-config-list——获取 scout 名单。- 调用一次
scout-runs-list,并设置较小的limit,然后按skill_name选出每个 scout 最新的运行记录(整个队伍的运行记录会按时间从新到旧返回,因此通常一次调用就能涵盖所有 scout);如果某个 scout 不在结果页中,则再次调用,并设置skill_name。 报告status和运行距今多久。
将结果整理成便于用户浏览的表格,列出 scout、运行频率、运行方式、上次运行和上次结果,并指出任何异常情况(从未运行、上次运行出错、长时间停留在 dry-run 状态)。
工作流:全面了解一个 scout
“我的错误追踪 scout 是如何工作的 / 状况如何?”
- 读取配置——在
scout-config-list中找到signals-scout-error-tracking对应的行:运行计划、运行方式和上次运行。 - 读取正文——
posthog:skill-get {"skill_name": "signals-scout-error-tracking"}会返回团队实际使用的指令集(可能是规范默认版本,也可能是经过修改、与默认版本不同的条目)。 这是每次运行时告知 Agent 要做什么的内容——包括它区分信号与噪声的方式、探索模式和排除条件。 要了解 scout _为何_会有这样的行为,请阅读其正文。 - 读取最近的运行记录:调用
scout-runs-list并设置该 scout 的skill_name(可添加text来搜索其摘要中的某个主题)。 每次运行结束时的summary是 scout 对其查看内容和决策的说明;运行失败时则会附带failure_reason。 - 读取它记住的内容——调用
scout-scratchpad-search(见下文)。 scout 写入的记忆条目会展现它对该项目已内化的基准情况和噪声。 - 读取它收到的指示——
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 获取数据,脚本格式化”的后半部分。
流程始终相同:
- 使用 MCP,通过
call --json(原始 JSON,而非美化后的文本格式)获取每个数据载荷并保存到文件。 对于较大的数据(scout-runs-list、tasks-runs-session-logs-retrieve),这本来就是必需的——它们会超出内联限制并写入文件,你可以将该文件传给脚本。 - 使用这些文件运行脚本。
这三个脚本都只使用 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 编辑路径。