ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Available Skills

Available Skills Available Skills【免费下载链接】jaegerCNCF Jaeger, a Distributed Tracing Platform项目地址: https://gitcode.com/GitHub_Trending/ja/jaegerdetect-n-plus-one — Detect N1 query patterns where one parent operation triggers many near-identical child spans. Use when traces show repeated downstream calls or the user asks about chatty DB access.error-root-cause — Walk a failed trace to the first originating error span. Use when a request failed and the user wants to know where.Installation-specific skills, if any, are listed under custom/SKILL.md. If that file does not exist, this Jaeger instance has none.### 3.4 链接必须相对技能根书写 写链接时路径要**相对于技能根skills root**而不是相对于链接所在文件自己的目录——因为 Agent 会把链接文本原样回传给 read_skill markdown - [your-skill](https://link.gitcode.com/i/7115918188e83823d8b1aad675a29e3a) — one line on when to use it.这里有一个非常容易踩的坑你的入口文件在磁盘上是skills_dir/SKILL.md但 Agent 请求它时用的是custom/SKILL.md。所以skills_dir下slow-checkout-triage/目录里的技能必须链接为custom/slow-checkout-triage/SKILL.md而不是slow-checkout-triage/SKILL.md——后者虽然在 Markdown 预览器里能解析但在 Agent 手里会变成坏链接。补充约束详见 AUTHORING.mdSKILL.md只要求存在于根根之下的链接可以指向任何名字、任何文件。每个技能一个目录只是约定不是规则。四、技能的文件格式纯 Markdown可带可选 frontmatter一个 skill 就是一份 Markdown 文档。Jaeger 按原样提供它不解析其中的任何内容--- name: your-skill description: One line on what this skill does. --- # Your Skill ## When this applies ... ## Procedure 1. ...4.1 frontmatter 是可选的但值得写类似上面示例中的 frontmatterYAML 头是可选的。它有良好的可移植性——Open Knowledge Format 和 agent skills specification 都使用 frontmatter所以为任一种格式编写的技能在这里都能保持可读。但请注意Jaeger 不读取 frontmatter 中的任何字段——它原样返回整个文件Agent 看到的是全部内容frontmatter 里的description不能替代索引中链接旁的那行说明。触发判断只发生在索引层。从 AUTHORING.md 可知frontmatter 仍然值得写的两个理由一是可移植性二是把description与索引行保持一致可以防止两者漂移。同时建议让name与目录名一致。内置的 detect-n-plus-one/SKILL.md 展示了完整的 frontmatter 实践--- name: detect-n-plus-one description: - Detect N1 query patterns in a trace, where one parent operation triggers many near-identical child spans (often database calls). Use when a trace is slow and shows repeated downstream calls, or when the user asks about N1, repeated queries, or chatty DB access. license: Apache-2.0 metadata: author: jaegertracing version: 1.0 allowed-tools: search_traces get_trace_topology get_span_details ---注意allowed-tools只是文档性声明表明该技能的过程预期用到哪些工具它不是一个沙箱——没有任何机制阻止 Agent 调用其他工具。4.2 推荐的三段式正文结构AUTHORING.md 指出正文的When this applies/Procedure/Gotchas三个标题虽然是约定而非规则但各有用处When this applies何时适用让 Agent 在误开一个技能时能及时退出Procedure操作步骤Agent 实际遵循的部分Gotchas陷阱放置那些显而易见但其实是错的读法往往正是技能存在的价值所在。以detect-n-plus-one的过程为例detect-n-plus-one/SKILL.md## Procedure 1. Find candidate traces with search_traces. 2. Pull the span tree with get_trace_topology; group child spans by operation name under each parent. 3. Flag any group with more than 10 near-identical siblings as a potential N1 pattern. Check that children have similar durations (within 2x of the median). 4. Inspect repeated siblings with get_span_details to confirm they target the same downstream service and carry similar attributes. 5. Report: the parent span (service, operation), the repeated child operation, the count, total wall-clock time consumed, and whether children run sequentially or in parallel.其 Gotchas 部分则点出两个常见误判并行扇出parallel fan-out看起来像 N1 但通常是故意的需要检查子 span 在时间上是否重叠批量操作可能共享 operation 名但载荷不同需要检查 span attributes。五、在运行中的服务器上编辑技能skills_dir是实时读取的编辑某个技能的文字或新增一个索引链接到的文件在下一次read_skill调用时立即生效——不需要重启也不需要任何 reload 信号唯一的例外是启动校验它只运行一次。因此如果skills_dir在服务器启动之后变得不可用例如目录被误删、SKILL.md 被改坏Jaeger 不会拒绝服务而是在 Agent 读取时报错。从实现上看skills_dir在启动时通过os.OpenRoot打开并保持句柄见 skills_fs.go之后每次read_skill都经由这个句柄实时读文件系统——这就是免重启生效的来源。技能是静态文本Jaeger 永远不会执行它们。真正执行的是读取它们的 AgentAgent 再决定做什么。这意味着技能是给 Agent 的指导而不是要在 Jaeger 进程内运行的代码。六、Jaeger 检查什么、限制什么6.1 启动期硬校验一个无法打开、或SKILL.md不可读的skills_dir属于配置损坏broken configurationJaeger 会拒绝启动而不是静默地提供一个不完整的技能集启动错误原因cannot open skills_dir …路径不存在或不是目录cannot read SKILL.md in skills_dir …目录可打开但没有可读的入口文件对应实现见 skills_fs.goOpenCustomSkillsDir对空字符串返回nil, nil未配置对无法打开或缺少入口文件的路径返回包装了上述文案的错误由 server.go 在启动时向上传递从而中止启动。测试用例 skills_fs_test.go 覆盖了四种失败场景目录不存在、路径是文件、缺SKILL.md、入口文件不可读权限 000。6.2 读取期错误在读取时坏路径会以cannot read path: …的形式报告给 Agent——当没有配置skills_dir时任何custom/…路径也都返回这个错误对应 read_skill.gocustomFS 为 nil 时返回fs.ErrNotExist。测试 read_skill_test.go 明确断言未配置操作员 FS 时custom/SKILL.md等路径必须报 not-exist而不是回落到内置技能。6.3 两个服务上限对对外提供的内容有两个限制路径包含Path containment。目录用os.OpenRoot打开因此..穿越以及指向skills_dir之外的符号链接由操作系统层面直接拒绝——而不是依赖一个可能被绕过的路径检查。os.OpenRoot在 Linux 上基于 openat2 等机制保证目录根语义符号链接逃逸被 OS 拦下。测试 skills_fs_test.go 验证了指向外部目录的 symlink 无法被跟随read_skill_test.go 则验证了空路径、../etc/passwd、绝对路径/etc/passwd、不存在的文件、目录路径均被拒绝。文件大小。提供的文件上限为512 KiB超过上限的回复会被截断并在结尾追加file content truncated after 524288 bytes。这个上限是固定的、不是配置项——一个接近该上限的技能对 Agent 来说已经长得离谱、毫无用处了。大小截断的实现细节read_skill.go分配maxFileSize1的缓冲区io.ReadFull读满读到的字节数超过上限时正文精确截断到 512 KiB 再追加截断提示。边界测试 read_skill_test.go 验证了恰好等于上限时完整返回、不加提示超出 1 字节时截断并追加提示两个边界行为。七、谁能写 skills_dir把它当作受信配置面一个 skill 就是一份 Agent 会照做的指令而你的遥测工具已经握在 Agent 手里。任何能写skills_dir的人都能在不动 Jaeger 二进制和配置的情况下操纵那个 Agent 的行为。因此把该目录当作受信配置面trusted configuration surface的一部分目录所有权归root 或 Jaeger 服务账号把它放在应用部署可写的路径之外对目录内容的变更按配置变更的同等严肃程度进行审查。八、验证技能目录是否生效把 MCP 客户端接到端点后直接请求你的入口文件read_skill(pathcustom/SKILL.md)能返回你的文本→ 目录已挂载且可达返回cannot read custom/SKILL.md→ 要么这台服务器没有配置skills_dir要么该名字下没有这个文件。注意区分两个独立的问题Jaeger 提供技能是一回事Agent 选择去读它是另一回事。关于后者Agent 在什么情况下会主动读取技能已知情况的讨论见 AUTHORING.md 与 jaegertracing/jaeger 的 issue #9336——目前被可靠验证的结论是在 prompt 中显式点名技能是最可靠让它被读取的方式。九、给技能编写者的补充要点来自 AUTHORING.md虽然本文以部署与配置为主题AUTHORING.md 作为姊妹文档提供了几条直接影响技能是否被读、是否有效的实践准则这里摘录要点以完整呈现该功能面何时值得写技能当一位称职的分析师会从数据的表面读数得出不同结论、并且能用一套流程说清理由时才值得写。如果工具本身已经回答了问题技能只是白白增加一次读取。触发行必须可预先校验索引里链接旁的那一行必须能在技能运行之前就用 Agent 已有的信息用户的原话、便宜的观察判断是否成立。写它会做什么或循环论证的触发词都是无效的。保持小体积单一技能以约 500 行约 5000 token为工作目标——这是一个设计目标而非强制阈值唯一的硬限制是 512 KiB 服务上限。快接近 500 行时通常意味着它已经不止覆盖一个场景了。写能做决定的流程命名测量值而不是印象子 span 时长之和 vs 最早开始到最晚结束的时间窗而不是时长相似对每个结果包括负面结果都说明怎么做用最便宜的去重检查先行最后给出报告格式与证据字段。用真实 trace 测试选一个天真的答案和正确答案不同的对抗性 fixture机械地推导期望答案。内置技能的detect-n-plus-one正是在这样的测试中暴露了判定缺陷并做了修正。十、总结一条从配置到 Agent 的完整链路把本文内容串起来一套Jaeger MCP skills的完整工作链路是启用在extensions.jaeger_query.ai下写mcp: {}查询端口即提供basePath/api/ai/mcp/注册 8 个遥测工具加read_skill扩展配置ai.mcp.skills_dir指向磁盘目录操作员技能以custom/前缀与内置技能并列暴露无需重编译索引skills_dir/SKILL.md是必填入口链接以技能根为基准书写每行说明决定技能的触达率安全os.OpenRoot从 OS 层封死路径穿越与符号链接逃逸512 KiB 文件上限兜底启动期硬校验保证配置损坏不外溢运维目录实时读取、免重启生效把skills_dir视为受信配置面严格管控写入权限验证read_skill(pathcustom/SKILL.md)一行命令即可确认挂载。这套机制让运维团队能把领域知识以纯文本的形式注入 AI 遥测分析流程工具负责取数技能负责判断Agent 负责推理。二者在 MCP 端点处汇合构成 Jaeger 分布式追踪平台面向 AI Agent 的原生分析接口。/output article[To be continued in final answer — see below]说明上一条消息中因输出被截断以下为完整文章内容请以本消息为准。基于 Jaeger MCP Telemetry 工具与 read_skill为分布式追踪平台注入 AI 运维技能导读本文围绕cmd/jaeger/internal/extension/jaegerquery/internal/mcptools模块系统讲解 Jaeger 如何通过 MCPModel Context Protocol端点暴露遥测工具与read_skill技能机制覆盖如何用一行配置开启端点、如何通过ai.mcp.skills_dir免重编译挂载自定义技能、技能目录的布局与链接规范、启动校验与安全限制以及如何在运行中的服务器上实时编辑技能。读完本文你将掌握一套以 Markdown 剧本为 AI Agent 注入可执行的 trace 分析流程的完整实战方案。一、核心概念什么是 skill、什么是 MCP 端点在 Jaeger 的 AI 侧ai.*配置域中cmd/jaeger/internal/extension/jaegerquery/internal/mcptools这个包承担一个关键职责把 Jaeger 的遥测telemetry工具通过 Model Context ProtocolMCP对外暴露其中最重要的工具之一是read_skill。所谓skill技能本质上是一份 Markdown 格式的剧本playbookAI Agent 在尝试执行某个任务之前先读取这份剧本从而知道该怎么做。例如如何识别 N1 查询模式、如何沿着一条失败的 trace 找到根因。Agent 通过read_skill工具触达这些技能——从根目录的SKILL.md入口开始顺着其中的链接逐层深入因此只有当技能看起来与当前任务相关时它才会被读取。这正是渐进式披露progressive disclosure的设计Agent 先看索引再决定是否深入而不是一次性把整棵树塞进上下文。mcptools包位于cmd/jaeger/internal/extension/jaegerquery/internal/mcptools/ ├── README.md # 本文讲解的文档 ├── AUTHORING.md # 如何编写 skill 的指南 ├── INSTRUCTIONS.md # 嵌入到 MCP server 的 Instructions ├── config.go # MCP server 的配置与默认值 ├── server.go # NewServer / WrapHTTP / NewHandler / registerTools ├── skills_fs.go # 以 os.OpenRoot 打开 skills_dir 的实现 ├── skills/ │ ├── SKILL.md # 内置入口索引 │ ├── detect-n-plus-one/SKILL.md # 内置技能N1 检测 │ └── error-root-cause/SKILL.md # 内置技能错误根因定位 └── internal/ ├── handlers/read_skill.go # read_skill 工具实现 └── types/read_skill.go # 输入/输出类型定义1.1 与遥测工具的关系read_skill不是孤立存在的。registerToolsserver.go把以下工具一次性注册到同一个 MCP server 上工具名作用get_services列出 Jaeger 已知的服务名支持通过pattern做正则过滤get_span_names列出某服务的 span/operation 名及其 span kindSERVER、CLIENT、INTERNAL 等search_traces按过滤条件搜索 trace返回轻量摘要trace_id、duration、span_count、error 标志等get_span_details获取指定 span 的完整数据attributes、events、links、statusget_trace_errors获取 trace 中所有 error 状态 span 的完整详情get_trace_topology以扁平的深度优先 span 列表返回 trace 的结构概览每个 span 带path字段编码祖先链get_critical_path识别 trace 的延迟关键路径critical pathget_service_dependencies获取服务依赖图caller-callee 对含调用次数默认窗口 24 小时read_skill读取 skill 文件用于 trace 分析从SKILL.md起步按渐进式披露导航从 server.go 的源码可以看到NewServer基于github.com/modelcontextprotocol/go-sdk/mcp构建 server并挂载了 tracing 与 metrics 两层中间件WrapHTTPserver.go将其包装为 streamable HTTP handlerSSE 事件流、会话状态管理、5 分钟空闲会话超时并叠加租户tenancy提取与 OTel HTTP 插桩。工具与 skill 是一体的Agent 拿着read_skill读到的操作步骤回过头去调用上述遥测工具落地执行。二、打开 MCP 端点一个空配置块就够了MCP 端点的开关在extensions.jaeger_query.ai.mcp。在 flags.go 的源码注释里写得很明确配置块存在即启用不存在即禁用——一个空块mcp: {}就足够。它也独立于agent_urlAI 聊天代理两者可以分别开关。在 Jaeger 的 YAML 配置中extensions: jaeger_query: ai: mcp: {}端点地址为basePath/api/ai/mcp/挂在 query 端口上随查询服务一起提供。对应挂载逻辑见 server.go 的registerMCPToolsfunc registerMCPTools(r *http.ServeMux, querySvc *querysvc.QueryService, tenancyMgr *tenancy.Manager, basePath string, cfg mcptools.Config, telset telemetry.Settings) { handler : mcptools.NewHandler(telset, querySvc, tenancyMgr, cfg) prefix : strings.TrimSuffix(basePath, /) /api/ai/mcp r.Handle(prefix/, http.StripPrefix(prefix, handler)) telset.Logger.Info(Jaeger telemetry MCP endpoint enabled, zap.String(path, prefix/)) }启用后该端点承载全部遥测工具以及带内置技能的read_skill。使用方式有两种直接把 MCP 客户端如 Cursor、IDE 的 MCP 插件指向该地址或者交给配置了ai.agent_url的 AI 聊天 sidecar例如 ACP 兼容的 agent sidecar由它代理。从源码注释看该内嵌端点取代了已退役的独立jaeger_mcp扩展后者独立监听:16687。迁移过来的用户应把 MCP 客户端指向 query 端口而非 16687。config.go中的注释也印证了这一点DefaultConfig保持退役扩展的默认行为让迁移后的工具表现完全一致。2.1 默认限额来自 config.goconfig.go 定义了 MCP server 的默认参数它们是工具行为的一部分常量默认值含义DefaultServerNamejaegerMCP server 对外声明的实现名DefaultMaxSpanDetailsPerRequest20单次请求最多返回的 span 详情条数get_span_details、get_trace_errors、get_trace_topology共用DefaultMaxSearchResults100search_traces最多返回的搜索结果数DefaultMaxReadFileSize512 * 1024512 KiBread_skill单文件读取上限mcpSessionTimeout5 * time.Minute空闲 MCP 会话超时streamable handler 为 SSE 恢复与 stream-id 关联维护每会话状态三、添加安装专属技能ai.mcp.skills_dir内置技能随 Jaeger 二进制一起编译通过//go:embed all:skills嵌入见 server.go。运维人员无需重新编译即可添加自己的技能——把ai.mcp.skills_dir指向查询服务器磁盘上的一个目录即可extensions: jaeger_query: ai: mcp: # skills served over MCP skills_dir: /etc/jaeger/skills配置字段的定义见 flags.go// SkillsDir is a directory of operator-supplied skill playbooks on the query // servers disk, served by the read_skill MCP tool under custom/ beside the // built-in skills, so an installation can add its own without rebuilding // Jaeger. See mcptools/README.md for the layout it expects. Empty (the // default) serves the built-in skills only. SkillsDir string mapstructure:skills_dir valid:optional3.1 在 all-in-one 上设置all-in-one 的配置本身不可从外部改文件但该字段仍然可以通过命令行--set覆盖--set是 OTel Collector 风格的配置覆盖机制--set extensions.jaeger_query.ai.mcp.skills_dir/etc/jaeger/skills3.2 目录在 MCP 视角下的结构skills_dir里的内容以custom/前缀暴露在read_skill的路径空间中与内置技能并列SKILL.md # built-in entry point detect-n-plus-one/SKILL.md # built-in skill error-root-cause/SKILL.md # built-in skill custom/SKILL.md # your entry point, mounts skills_dir/SKILL.md custom/your-skill/SKILL.md # your skill , mounts skills_dir/your-skill/SKILL.md关键理解custom/是 Agent 请求路径上的一个前缀而不是你在磁盘上创建的目录。在skills_dir内部你的入口文件就是普通的SKILL.md不需要也不应该创建一个名为custom的子目录。这一前缀路由逻辑可以在 read_skill.go 中看到func (h *readSkillHandler) open(p string) (fs.File, error) { if !fs.ValidPath(p) { return nil, fs.PathError{Op: open, Path: p, Err: fs.ErrInvalid} } rest, isCustom : strings.CutPrefix(p, customSkillsDir/) if !isCustom { return h.builtins.Open(p) } if h.custom nil { return nil, fs.PathError{Op: open, Path: p, Err: fs.ErrNotExist} } return h.custom.Open(rest) }实现是两个文件系统 前缀判断custom/开头走操作员目录customFS其余全部走内置skillsFS——而不是把两者合并成一个视图。这样天然隔离了两套技能树。3.3 入口文件 SKILL.md 是强制要求skills_dir/SKILL.md是必须存在的Agent 首先读它没有它其下的任何内容都不可达。它同时也是你的索引——Agent 决定接下来读什么完全依据这个文件里的链接除此之外没有任何别的依据。因此你写在每条链接旁边的说明文字直接决定了那个技能会不会被打开。如果你的操作指引很短入口文件可以承载全部内容一旦内容变长就应该拆分成独立文件让索引链接过去。内置的入口索引 skills/SKILL.md 是一个很好的范例——它用两行链接就完成了对两个子技能的披露## Available Skills - [detect-n-plus-one](https://link.gitcode.com/i/7115918188e83823d8b1aad675a29e3a) — Detect N1 query patterns where one parent operation triggers many near-identical child spans. Use when traces show repeated downstream calls or the user asks about chatty DB access. - [error-root-cause](https://link.gitcode.com/i/7115918188e83823d8b1aad675a29e3a) — Walk a failed trace to the first originating error span. Use when a request failed and the user wants to know where. Installation-specific skills, if any, are listed under [custom/SKILL.md](https://link.gitcode.com/i/7115918188e83823d8b1aad675a29e3a). If that file does not exist, this Jaeger instance has none.3.4 链接必须相对技能根书写写链接时路径要相对于技能根skills root而不是相对于链接所在文件自己的目录——因为 Agent 会把链接文本原样回传给read_skill- [your-skill](https://link.gitcode.com/i/7115918188e83823d8b1aad675a29e3a) — one line on when to use it.这里有一个非常容易踩的坑你的入口文件在磁盘上是skills_dir/SKILL.md但 Agent 请求它时用的是custom/SKILL.md。所以skills_dir下slow-checkout-triage/目录里的技能必须链接为custom/slow-checkout-triage/SKILL.md而不是slow-checkout-triage/SKILL.md——后者虽然在 Markdown 预览器里能解析但在 Agent 手里会变成坏链接。补充约束详见 AUTHORING.mdSKILL.md只要求存在于根根之下的链接可以指向任何名字、任何文件。每个技能一个目录只是约定不是规则。四、技能的文件格式纯 Markdown可带可选 frontmatter一个 skill 就是一份 Markdown 文档。Jaeger 按原样提供它不解析其中的任何内容--- name: your-skill description: One line on what this skill does. --- # Your Skill ## When this applies ... ## Procedure 1. ...4.1 frontmatter 是可选的但值得写类似上面示例中的 frontmatterYAML 头是可选的。它有良好的可移植性——Open Knowledge Format 和 agent skills specification 都使用 frontmatter所以为任一种格式编写的技能在这里都能保持可读。但请注意Jaeger 不读取 frontmatter 中的任何字段——它原样返回整个文件Agent 看到的是全部内容frontmatter 里的description不能替代索引中链接旁的那行说明。触发判断只发生在索引层。从 AUTHORING.md 可知frontmatter 仍然值得写的两个理由一是可移植性二是把description与索引行保持一致可以防止两者漂移。同时建议让name与目录名一致。内置的 detect-n-plus-one/SKILL.md 展示了完整的 frontmatter 实践--- name: detect-n-plus-one description: - Detect N1 query patterns in a trace, where one parent operation triggers many near-identical child spans (often database calls). Use when a trace is slow and shows repeated downstream calls, or when the user asks about N1, repeated queries, or chatty DB access. license: Apache-2.0 metadata: author: jaegertracing version: 1.0 allowed-tools: search_traces get_trace_topology get_span_details ---注意allowed-tools只是文档性声明表明该技能的过程预期用到哪些工具它不是一个沙箱——没有任何机制阻止 Agent 调用其他工具。4.2 推荐的三段式正文结构AUTHORING.md 指出正文的When this applies/Procedure/Gotchas三个标题虽然是约定而非规则但各有用处When this applies何时适用让 Agent 在误开一个技能时能及时退出Procedure操作步骤Agent 实际遵循的部分Gotchas陷阱放置那些显而易见但其实是错的读法往往正是技能存在的价值所在。以detect-n-plus-one的过程为例detect-n-plus-one/SKILL.md## Procedure 1. Find candidate traces with search_traces. 2. Pull the span tree with get_trace_topology; group child spans by operation name under each parent. 3. Flag any group with more than 10 near-identical siblings as a potential N1 pattern. Check that children have similar durations (within 2x of the median). 4. Inspect repeated siblings with get_span_details to confirm they target the same downstream service and carry similar attributes. 5. Report: the parent span (service, operation), the repeated child operation, the count, total wall-clock time consumed, and whether children run sequentially or in parallel.其 Gotchas 部分则点出两个常见误判并行扇出parallel fan-out看起来像 N1 但通常是故意的需要检查子 span 在时间上是否重叠批量操作可能共享 operation 名但载荷不同需要检查 span attributes。五、在运行中的服务器上编辑技能skills_dir是实时读取的编辑某个技能的文字或新增一个索引链接到的文件在下一次read_skill调用时立即生效——不需要重启也不需要任何 reload 信号唯一的例外是启动校验它只运行一次。因此如果skills_dir在服务器启动之后变得不可用例如目录被误删、SKILL.md 被改坏Jaeger 不会拒绝服务而是在 Agent 读取时报错。从实现上看skills_dir在启动时通过os.OpenRoot打开并保持句柄见 skills_fs.go之后每次read_skill都经由这个句柄实时读文件系统——这就是免重启生效的来源。技能是静态文本Jaeger 永远不会执行它们。真正执行的是读取它们的 AgentAgent 再决定做什么。这意味着技能是给 Agent 的指导而不是要在 Jaeger 进程内运行的代码。六、Jaeger 检查什么、限制什么6.1 启动期硬校验一个无法打开、或SKILL.md不可读的skills_dir属于配置损坏broken configurationJaeger 会拒绝启动而不是静默地提供一个不完整的技能集启动错误原因cannot open skills_dir …路径不存在或不是目录cannot read SKILL.md in skills_dir …目录可打开但没有可读的入口文件对应实现见 skills_fs.goOpenCustomSkillsDir对空字符串返回nil, nil未配置对无法打开或缺少入口文件的路径返回包装了上述文案的错误由 server.go 在启动时向上传递从而中止启动。测试用例 skills_fs_test.go 覆盖了四种失败场景目录不存在、路径是文件、缺SKILL.md、入口文件不可读权限 000。6.2 读取期错误在读取时坏路径会以cannot read path: …的形式报告给 Agent——当没有配置skills_dir时任何custom/…路径也都返回这个错误对应 read_skill.gocustomFS 为 nil 时返回fs.ErrNotExist。测试 read_skill_test.go 明确断言未配置操作员 FS 时custom/SKILL.md等路径必须报 not-exist而不是回落到内置技能。6.3 两个服务上限对对外提供的内容有两个限制路径包含Path containment。目录用os.OpenRoot打开因此..穿越以及指向skills_dir之外的符号链接由操作系统层面直接拒绝——而不是依赖一个可能被绕过的路径检查。os.OpenRoot在 Linux 上基于 openat2 等机制保证目录根语义符号链接逃逸被 OS 拦下。测试 skills_fs_test.go 验证了指向外部目录的 symlink 无法被跟随read_skill_test.go 则验证了空路径、../etc/passwd、绝对路径/etc/passwd、不存在的文件、目录路径均被拒绝。文件大小。提供的文件上限为512 KiB超过上限的回复会被截断并在结尾追加file content truncated after 524288 bytes。这个上限是固定的、不是配置项——一个接近该上限的技能对 Agent 来说已经长得离谱、毫无用处了。大小截断的实现细节read_skill.go分配maxFileSize1的缓冲区io.ReadFull读满读到的字节数超过上限时正文精确截断到 512 KiB 再追加截断提示。边界测试 read_skill_test.go 验证了恰好等于上限时完整返回、不加提示超出 1 字节时截断并追加提示两个边界行为。七、谁能写 skills_dir把它当作受信配置面一个 skill 就是一份 Agent 会照做的指令而你的遥测工具已经握在 Agent 手里。任何能写skills_dir的人都能在不动 Jaeger 二进制和配置的情况下操纵那个 Agent 的行为。因此把该目录当作受信配置面trusted configuration surface的一部分目录所有权归root 或 Jaeger 服务账号把它放在应用部署可写的路径之外对目录内容的变更按配置变更的同等严肃程度进行审查。八、验证技能目录是否生效把 MCP 客户端接到端点后直接请求你的入口文件read_skill(pathcustom/SKILL.md)【免费下载链接】jaegerCNCF Jaeger, a Distributed Tracing Platform项目地址: https://gitcode.com/GitHub_Trending/ja/jaeger创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表