
PostHog MCP Analytics 意图聚类实战指南从 Agent 目标聚类到工具可发现性诊断【免费下载链接】posthog:hedgehog: PostHog is the leading platform for building self-driving products. Our developer tools – AI observability, analytics, session replay, flags, experiments, error tracking, logs, and more – capture all the context agents need to diagnose problems, uncover opportunities, and ship fixes. Steer it all from Slack, web, desktop, or the MCP.项目地址: https://gitcode.com/GitHub_Trending/po/posthog意图聚类Intent Clustering是 PostHog MCP Analytics 中回答Agent 到底想用 MCP 做什么、做得成不成的核心能力它把 Agent 调用工具时携带的自由文本$mcp_intent向量化后按语义相似度分簇再从调用工具的视角反转出一个工具中心视图回答我的工具被 Agent 找到了吗、和谁竞争、服务得怎么样。本文将以 PostHog 开源仓库中products/mcp_analytics/skills/exploring-mcp-intent-clusters/SKILL.md为骨架结合 intent_clustering.py 的源码实现完整讲解快照结构、两个 MCP 工具的调用工作流、可发现性分析方法、覆盖率读法与重新计算的工程细节。什么是意图聚类从调了哪个工具到想达成什么目标聚类流水线读取 Agent 每次工具调用$mcp_tool_call事件上携带的自由文本$mcp_intentAgent 用自然语言陈述的目标对其进行向量化嵌入embedding并将语义相近的目标归入同一簇。它回答的是人们在尝试做什么并且做成没有what are peopletryingto do, and does it work?而不是哪个工具被调用了。其归因attribution是按调用per call进行的每一次调用都被记到它自己携带的 intent 名下没有携带 intent 的调用则继承同一会话中最近一次出现的 intentlast observation carried forwardLOCF。因此一个工具的计数反映的是它实际服务的目标而不是会话开场白。每个簇携带自己的工具分布tool distribution、调用次数与错误率。快照还附带一个工具中心视图tool-centric pivot反转回答同一个问题对于给定的工具是哪些 intent 在驱动它的使用Agent 多久能找到它它和谁竞争与工具质量tool quality和会话sessions这类最终聚合$mcp_tool_call的指标不同聚类需要 embedding 计算无法用 SQL 表达因此由两个类型化 MCP 工具基于一个持久化的快照stored snapshot提供。两个核心工具工具用途posthog:mcp-analytics-intent-clusters-retrieve拉取项目最新的聚类快照posthog:mcp-analytics-intent-clusters-recompute触发一次异步重新计算从 tools.yaml 可以看到两者的注册差异retrieve只读、幂等readOnly: true、idempotent: true需要mcp_analytics:read权限recompute可写、非幂等需要mcp_analytics:write权限且requires_ai_consent: true重算会驱动 embedding 服务产生外部调用需要 AI 使用同意。两者都挂在mcp-analyticsfeature flag 下url_prefix为/mcp-analytics。工作流一读取当前聚类快照posthog:mcp-analytics-intent-clusters-retrieve {}返回的快照包含status、last_computed_at、computed_withembedding 模型、聚类参数与样本覆盖率百分比、一个clusters数组、一个tools数组工具中心视图以及tool_overlaps。簇cluster字段解读每个簇携带以下字段label簇的标签取簇内 medoid即离质心最近的 intent 文本intent_count/call_count/error_count/error_rate_pctrouting_entropy该簇工具分布的归一化香农熵取值 [0, 1]tool_distribution该目标路由到哪些工具含每个工具在簇内的占比与各自的错误率sample_intents簇内代表性 intent 样本每条簇最多 3 条switches出错调用后紧接着换用另一个工具的记录——这是Agent 把这些工具搞混了的最强证据self_retries出错调用后紧接着用同一个工具重试的记录——说明该工具的错误信息没能帮助 Agent 自我纠错。从 intent_clustering.py 的build_snapshot可以看到这些字段的精确生成方式label取 medoid intent_medoid_index按余弦距离取最接近质心的样本tool_distribution按调用量降序排列并计算pct与每个工具的error_rate_pctsample_intents取簇内频率最高的前 3 条。簇最终按call_count降序排序且只有调用量最高的前MAX_SNAPSHOT_CLUSTERS 100个簇见 constants.py会被持久化进快照computed_with.n_clusters保留的是全部簇数量供 UI 说明实际找到了多少簇。如何阅读簇按call_count排序阅读回答Agent 主要在做什么按error_rate_pct阅读回答哪些目标在失败——某个簇的错误率高指向一类工具服务得很差的目标a class of agent goals the tools serve badly。routing_entropy描述簇内工具使用的分散程度低熵意味着一个目标稳定地映射到一个工具高熵意味着 Agent 在为该目标四处寻找正确的工具通常是能力缺失的信号。源码中_routing_entropy的实现在 intent_clustering.py它计算工具分布的香农熵并除以log(工具数)归一化单工具簇熵为 0。工作流二用工具中心视图回答我的工具可被找到吗tools数组中的每个条目携带clusters该工具服务的 intent 簇列表每个簇条目含capture_pct该工具在簇调用中的份额rank该工具在簇内按调用量的排名top_competitor最强的竞争工具及其份额description_fit工具描述与簇质心之间的余弦相似度在描述尚未被捕获前为null。注意工具条目只携带cluster_id不携带簇自身的 label 或总量——需要按 id 与顶层clusters数组 join。n_clusters_served该工具总共服务的簇数量。工具条目列表是有上限的默认MAX_CLUSTERS_PER_TOOL 20因此在说这个工具服务 N 个 intent之前必须先用这个字段核对真实数量。discovery_rate_pct在被抽样的会话中$mcp_tools_list目录里广告过该工具的会话里实际调用它的比例当该工具在不足 5 个被广告的会话中出现时MIN_ADVERTISED_SESSIONS 5见 intent_clustering.py该值为null样本太小视为噪声。contested_score工具各簇的按调用量加权的平均熵——衡量该工具的 intent 与其他工具被拆分的频率。可发现性失败模式的判读高description_fit 低capture_pct 可发现性失败Agent 本应为了该目标找到这个工具却选了别的东西低description_fit 高capture 描述低估了工具实际做的事description undersells what the tool actually does。tool_overlaps列出在相同 intent 上竞争的成对工具用sessions_with_both对比sessions_with_either来区分工作流两个工具在同一会话里配合使用与混乱会话二选一。从源码看contested_calls是每个簇上min(calls_a, calls_b)的累加即两个工具都有可能接走的调用量compute_tool_overlaps对对的会话计数则从calls_by_session中直接统计配对展开是 O(n²) 的所以每个簇只取调用量最高的前MAX_OVERLAP_TOOLS_PER_CLUSTER 20个工具进入配对且配对数量上限MAX_CONFUSION_PAIRS 50。引用数字前先读覆盖率computed_with中的以下字段决定了你能多严肃地引用这些数字sampled_sessions/session_coverage_pct语料占整个时间窗口的比例advertisement_coverage_pct限制了可发现率能看到的范围——只有观测到 tools-list 目录的会话才会进入可发现率的分母而 exec-wrapper 模式下会话只广告 wrapper 工具因此按工具的发现率是在全目录full-catalog会话上测得的。从 build_snapshot 的meta组装可以看到完整的覆盖率字段清单session_coverage_pct、intent_coverage_pct窗口内携带 intent 的调用占比、imputed_call_pctLOCF 继承的调用占比、unattributed_call_pct、corpus_call_coverage_pct、advertisement_coverage_pct、description_coverage_pct以及sampling_warning——它明确声明每工具捕获率与可发现率是样本统计量sample statistics不是总体真实值因为快照来自按工具分层抽样的会话per-tool floors主导工具被设上限。computed_with不是完整性检查computed_with并不对一切负责。只有顶层工具与重叠对的上限会通过dropped_tools和dropped_overlap_pairs报告丢弃量每个簇内的列表是静默截断的MAX_SWITCHES_PER_CLUSTER 10、MAX_SELF_RETRIES_PER_CLUSTER 5所以看到一个簇显示 10 条 switches 或 5 条 self-retries应理解为至少这么多而非恰好这么多。工具的簇条目同样被截断但那里n_clusters_served给出了真实数量。聚类只看事件不读会话摘要聚类只读取事件。按需生成的会话摘要MCPSession.intent即 generate intent 写入的内容被刻意排除摘要描述的是整个会话把它摊到该会话的每次调用上正是逐调用语料per-call corpus要消除的错误归因。因此一个只有摘要 intent、从未在事件上记录过 intent 的会话不会出现在任何簇中——检查intent_coverage_pct看窗口内因此被遗漏的比例需要时直接读会话摘要见 exploring-mcp-sessions。工作流三处理空快照或过期快照空 / 空闲且无簇status: idleclusters: []还没有运行过任何一次聚类。触发一次重算见下并告诉用户它在后台计算。last_computed_at过期建议重新计算。注意 empty_snapshot 的细节一个流量很大但没有任何可归因 intent的窗口与一个完全没有流量的窗口返回的空快照并不相同——前者intent_coverage_pct会如实给出0% 的调用携带 intent这个可行动的信息后者则全是null。工作流四触发重新计算posthog:mcp-analytics-intent-clusters-recompute {}该调用立即返回status: computingHTTP 202实际工作在后台运行。随后轮询posthog:mcp-analytics-intent-clusters-retrieve直到status回到idle完成或error。不要阻塞等待——告诉用户一分钟后再来问。重算在工程上受到节流每个项目同一时刻只允许一次运行已在计算中时再收到 202 只是确认了进行中的那次运行。后台的真实执行是一个 Temporal 工作流管理命令 cluster_mcp_intents.py 用于手动端到端验证它会启动一次DailyIntentClusteringWorkflow执行并等待其完成再打印快照--team-id必填--lookback-days默认用任务默认值 7 天--raw输出原始 JSON。流水线本身由 intent_clustering.py 顶部的 docstring 说明它是一个个纯函数pure functions每个阶段都可独立测试Temporal activity 负责编排并持久化结果——因为算法是整个特性风险最高的部分保持纯函数可以在不触碰 ClickHouse、Postgres 或 embedding 服务的情况下验证算法。底层流水线从采样到快照的五步从源码可以还原完整的重算链路每一步都有对应的纯函数与 SQL分层采样stratified samplingsample_corpus_sessions用cityHash64(session_id)做确定性伪随机排序采样L220-L229保证可复现、可复用 embedding 缓存fetch_tools_by_sessionstratify_session_idsselect_corpus_sessions确保低/中流量工具logs/tracing/metrics不被主导工具exec/scout的流量抹掉——每个工具至少保留MIN_SESSIONS_PER_TOOL 400个会话约等于把捕获率读到 ±5% 的统计下限而任何工具贡献的调用不超过MAX_CALLS_PER_TOOL 1500语料总预算MAX_CORPUS_SESSIONS 6000。归因attributionbuild_call_corpus逐调用把 intent 归属到调用缺失时 LOCF 继承同会话最近的 intent并按频率截取前DEFAULT_TOP_N_INTENTS 1000条L682-L759。嵌入embeddingembed_texts_async用text-embedding-3-small-1536模型EMBEDDING_MODELL59intent 以User intent: 前缀、工具描述以Tool description: 前缀分别缓存MCPIntentEmbeddingCache并发上限EMBED_CONCURRENCY 20嵌入失败逐条吞掉但记录聚合告警。聚类cluster_embeddings使用 sklearn 的AgglomerativeClustering余弦距离 平均链接average linkage距离阈值DEFAULT_DISTANCE_THRESHOLD 0.2越小簇越紧、簇数越多是用户可调的旋钮不产生噪声哨兵L985-L1007。快照组装build_snapshot聚合出簇、工具中心视图、重叠对与computed_with元信息作为一个 JSONB blob 持久化到 PostgresMCPIntentClusterSnapshot模型迁移见 0004_mcpintentclustersnapshot.pySNAPSHOT_VERSION 2。每个阶段都有对应测试见 test_intent_clustering.py。前端聚类界面在 frontend/clustering/MCPAnalyticsClustering.tsx包含簇面板、工具中心面板与重叠表等组件。构造 UI 链接意图聚类页面https://app.posthog.com/project/project_id/mcp-analytics/intent-clustering实用提示簇的好坏取决于$mcp_intent覆盖率如果很少有调用携带 intent簇会稀疏。可用下面的 HogQL 快速交叉核对覆盖率在$mcp_tool_call上countIf(toString(properties.$mcp_intent) ! )高error_rate_pct 高routing_entropy的簇是最强的这些工具服务不好这个目标信号值得深入查看它的sample_intents和tool_distribution。重算被节流为每个项目一次运行计算中再次收到 202 只是确认进行中的运行。采样诚实性computed_with.sampled true、corpus_strategy stratified_by_tool任何下游在使用每工具的捕获率/可发现率时必须警告这是平衡样本balanced sample而非总体统计。相关技能exploring-mcp-tool-quality——每工具的错误率与延迟exploring-mcp-sessions——intent 背后的单个运行明细。【免费下载链接】posthog:hedgehog: PostHog is the leading platform for building self-driving products. Our developer tools – AI observability, analytics, session replay, flags, experiments, error tracking, logs, and more – capture all the context agents need to diagnose problems, uncover opportunities, and ship fixes. Steer it all from Slack, web, desktop, or the MCP.项目地址: https://gitcode.com/GitHub_Trending/po/posthog创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考