news 2026/8/29 9:55:17

从长文本到紧凑图:实现 /show-me 风格的 Agent Skill

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
从长文本到紧凑图:实现 /show-me 风格的 Agent Skill

实际使用 AI Agent 时,模型输出长文本是非常常见的问题:解释一个流程能写二十行,对比两个方案能列满一屏。但人眼真正需要的往往是结构,是能一眼看出节点关系、先后顺序和差异点的图形。/show-me 这类 agent skill 正是为这个场景出现的:它以斜杠命令形式加载一套固定的渲染能力,把复杂的结构化信息压缩成紧凑的视觉表示。这篇文章会从 agent skill 的概念讲起,说明它和 MCP 到底有什么区别,再动手实现一个最小可运行的 /show-me 风格渲染技能,最后给出验证、排错和落地建议。

1. 先理解 /show-me 是什么,它解决 Agent 的什么问题

1.1 Agent 输出长文本带来的阅读成本

让 Agent 解释"用户登录后请求如何流转",默认回答往往是:

用户请求先到达 Nginx,Nginx 根据路由规则把请求转发到网关服务,网关完成认证和鉴权后,再把请求分发到用户服务,用户服务查询数据库后返回结果,最后网关把响应汇总并返回给前端。

这段描述信息量没问题,但阅读成本很高。你需要先记住 Nginx、网关、用户服务、数据库四个节点,再在脑子里把它们串成一张图。如果流程里有分支、重试、降级逻辑,文本描述会成倍膨胀,很容易漏掉关键依赖。

换成紧凑视觉表示,同样的信息变成下面这样:

┌──────────────────┐ │ Nginx │ └──────────────────┘ │ ▼ ┌──────────────────┐ │ Gateway │ └──────────────────┘ │ ▼ ┌──────────────────┐ │ User Service │ └──────────────────┘ │ ▼ ┌──────────────────┐ │ Database │ └──────────────────┘

人眼扫描这张图只需要几秒,节点关系、执行顺序、调用方向全都明确。这正是 /show-me 这类 agent skill 的核心价值:在不依赖图片生成能力的文本通道里,通过固定格式输出,让复杂信息变得可扫读、可定位、可讨论。

1.2 紧凑视觉表示到底包括哪些形式

"紧凑视觉表示"并不是指高大上的图表渲染,而是指在文本通道里用少量字符表达空间关系和结构信息。常见形式包括:

  • 使用框线字符绘制的流程图和状态图。
  • |-拼出来的结构表格。
  • 用字符长度表示数值大小的条形图。
  • 用缩进和分支符号表示的树形依赖关系。
  • 用标记符号标注差异点的对比清单。

这些形式非常适合终端、聊天窗口、代码注释和 Markdown 文档。它们不依赖图片渲染服务,也不会因为图片无法加载而丢失信息。更重要的是,它们可以被固定成模板,由代码生成,而不是每次让模型自由发挥。

2. Agent Skill 是什么:它和普通工具调用的边界在哪里

2.1 Skill 的组成与最小文件结构

Agent Skill 可以理解为"给 Agent 准备的可复用技能包"。它不是简单的单一函数,而是一个包含描述文件、脚本、模板、示例的目录。模型在对话中遇到匹配场景时,会把整个技能包加载进来,按里面定义的流程执行。

一个典型的 Skill 目录结构如下:

show-me/ ├── SKILL.md ├── scripts/ │ └── render.py └── examples/ └── flow.json

SKILL.md 是这个技能包的入口描述,告诉模型"这个技能解决什么问题、什么时候用、怎么用"。scripts 目录存放真正执行逻辑的脚本。examples 目录提供示例输入,帮助模型理解如何把用户意图转成脚本需要的参数。

这种设计思路和普通工具调用有明显差别。普通工具调用是模型在运行期从一组预声明 API 里选择一个函数执行,重点在"调用";Skill 则把一段完整的工作方法打包,包括提示词、命令约定、脚本和边界条件,重点在"复用整套能力"。

2.2 一次 Skill 调用的完整路径

理解 Skill 最好的方式,是看一次完整调用路径。

  1. 用户在对话里输入触发表达,例如"画一下登录流程"。
  2. Agent 框架把已注册的 Skill 描述注入上下文,模型根据 SKILL.md 中的 description 判断当前需求是否匹配。
  3. 匹配后,模型或运行时把用户意图整理成脚本要求的输入结构,例如一个 JSON。
  4. 脚本在受控环境里执行,返回文本结果。
  5. Agent 把脚本结果直接返回给用户,而不是重新解释一遍。

最后一步非常关键。如果 Agent 拿到脚本输出的流程图后,因为"想帮忙"而重新表述,表格会被改坏,对齐会被破坏。所以 Skill 描述里通常要明确写一句:脚本输出保持原样,不要二次排版。这也是区分"纯工具调用"和"Skill 工作流"的细节差异。

3. Agent Skill 和 MCP 的区别:一张表说清定位差异

3.1 MCP 解决的是连接标准化问题

MCP,即 Model Context Protocol,是一种标准化的连接协议。它解决的是"模型如何按统一方式访问外部工具和数据源"的问题。一个 MCP Server 通过协议暴露工具、资源和提示,MCP Client 负责连接并管理会话。这样模型就不需要为每个外部系统单独实现一套集成逻辑。

可以这样理解:MCP 关心的是"连到哪里、怎么连、权限怎么控制",而 Skill 关心的是"拿到任务后,按什么流程把活干完"。两者的层次不同,解决的问题也不同。

3.2 一张表看清 Skill 与 MCP 的差异

对比维度Agent SkillMCP
定位可复用的能力包和执行流程模型与工具/数据源的标准连接协议
基本组成SKILL.md、脚本、模板、示例Server、Client、协议定义
触发方式斜杠命令或场景匹配后加载模型按协议发现并调用工具
运行依赖通常本地目录即可,依赖轻通常需要启动 Server 进程或远程服务
权限边界以目录和脚本执行权限为主协议层面的工具发现和授权
典型场景画流程图、整理表格、批量处理文件查数据库、调外部 API、操作 SaaS 工具
维护重点提示词质量、脚本稳定性、模板覆盖Server 可用性、鉴权、数据格式兼容

从这张表可以看出,Skill 偏"经验流程",MCP 偏"连接通道"。Skill 可以完全离线运行,适合把重复性工作固化成稳定产出;MCP 则天然适合连接多个异构系统,解决的是生态互通问题。

3.3 两者不是二选一:组合使用的典型结构

实际项目中,Skill 和 MCP 经常配合出现。一个常见结构是:

用户意图 │ ▼ Agent 框架 │ ├── Skill 层:负责流程编排和渲染 │ │ │ └── /show-me 渲染脚本 │ └── MCP 层:负责数据获取 │ ├── 数据库 MCP Server ├── 监控系统 MCP Server └── 内部 API MCP Server

比如用户想把最近一小时的接口错误率画成图。MCP Server 负责从监控系统拉取数据,/show-me 这类渲染 Skill 则负责把数据变成紧凑的文本条形图或表格。Skill 不直接接触数据源,MCP 不直接负责版面呈现,各管一段。

4. 实现一个最小 /show-me 风格渲染 Skill

4.1 目录设计:把渲染逻辑和描述文件分开

下面给出一个思路对齐 /show-me 能力定位的最小实现。你可以把它当成复刻这类技能的起点,实际使用时要根据自己项目的目录和框架版本调整。

先创建目录结构:

mkdir -p show-me/scripts show-me/examples

然后把技能描述写入show-me/SKILL.md

--- name: show-me description: 生成紧凑的文本视觉表示,支持流程和表格两种类型。用户要求画流程图、整理对比表格、梳理结构时使用。 usage: /show-me flow <主题> /show-me table <行列数据> /show-me compare <方案A> <方案B> --- # show-me Skill 当用户需要把复杂信息转成可扫读的视觉结构时,使用本技能。 执行步骤: 1. 把用户意图整理成 JSON 输入。 2. 调用 scripts/render.py,type 指定 flow 或 table。 3. 把脚本输出原样返回,不要重新排版。 注意: - 脚本输出就是最终结果,禁止二次格式化。 - 如果输入信息不足,先向用户确认节点或列名,不要猜测。

这里最重要的是descriptionusage。模型靠 description 判断是否触发技能,靠 usage 学习命令格式。注意:如果 description 写得过于宽泛,模型会在不该触发时误触发;如果写得太狭窄,又会漏触发。

4.2 核心脚本:用 JSON 输入生成紧凑视觉输出

渲染脚本只做一件事:读取结构化 JSON,输出文本图。不要把业务判断放进脚本里,判断交给模型,渲染交给代码。

#!/usr/bin/env python3 """show-me 最小渲染脚本:把 JSON 描述转成紧凑文本图。""" import json import sys from argparse import ArgumentParser def render_flow(nodes): """渲染竖向流程图,节点之间用箭头连接。""" if not nodes: return "(empty flow)" width = max(len(n) + 4 for n in nodes) parts = [] for index, node in enumerate(nodes): top = "┌" + "─" * (width - 2) + "┐" mid = "│ " + node.ljust(width - 4) + " │" bottom = "└" + "─" * (width - 2) + "┘" parts.append("\n".join([top, mid, bottom])) if index < len(nodes) - 1: indent = " " * ((width - 1) // 2) parts.append(indent + "│") parts.append(indent + "▼") return "\n".join(parts) def render_table(headers, rows): """渲染紧凑表格,列宽按内容自适应。""" if not headers or not rows: return "(empty table)" cols = len(headers) widths = [ max(len(headers[i]), max(len(str(r[i])) for r in rows)) + 2 for i in range(cols) ] def fmt(cells): return ( "|" + "|".join( " " + str(cells[i]).ljust(widths[i] - 2) + " " for i in range(cols) ) + "|" ) sep = "|" + "|".join("-" * widths[i] for i in range(cols)) + "|" return "\n".join([fmt(headers), sep] + [fmt(r) for r in rows]) def main(): parser = ArgumentParser(description=__doc__) parser.add_argument( "--type", choices=["flow", "table"], default="flow" ) parser.add_argument("--data", required=True, help="JSON 字符串") args = parser.parse_args() try: data = json.loads(args.data) except json.JSONDecodeError as exc: print(f"JSON 解析失败: {exc}", file=sys.stderr) return 2 if args.type == "flow": print(render_flow(data.get("nodes", []))) else: print(render_table(data.get("headers", []), data.get("rows", []))) return 0 if __name__ == "__main__": sys.exit(main())

这段代码实现两个核心函数。render_flow根据节点列表生成竖向流程图,框线宽度由最长节点决定。render_table根据表头和行数据生成 Markdown 风格表格,列宽自动计算。main 函数统一处理 JSON 解析和错误返回,脚本退出码可以用于后续自动化检查。

4.3 接入 Agent 运行环境与本地验证

不同 Agent 框架接入 Skill 的方式不同。常见做法是把show-me目录放到框架指定的 skills 目录,框架启动时扫描注册;也有的框架要求把 SKILL.md 内容维护在系统提示词里,脚本单独存放,模型需要时再触发执行。

如果你使用的框架还不支持目录型 Skill,可以退化成两步:第一步把 SKILL.md 的说明段落放入系统提示词,第二步在模型决定使用渲染时调用render.py。这种方式同样能验证技能逻辑,后续再迁移到完整目录支持即可。

先做本地验证,不依赖 Agent 框架:

python3 scripts/render.py --type flow --data '{"nodes":["request received","validate token","load user","return data"]}'

正常输出:

┌──────────────────┐ │ request received │ └──────────────────┘ │ ▼ ┌────────────────┐ │ validate token │ └────────────────┘ │ ▼ ┌────────────┐ │ load user │ └────────────┘ │ ▼ ┌─────────────┐ │ return data │ └─────────────┘

再验证表格类型:

python3 scripts/render.py --type table --data '{"headers":["option","latency","cost","risk"],"rows":[["local cache","<1ms","low","consistency"],["redis","1-5ms","mid","ops"],["sql query","5-20ms","high","slow"]]}'

正常输出:

| option | latency | cost | risk | |---------------|---------|------|-------------| | local cache | <1ms | low | consistency | | redis | 1-5ms | mid | ops | | sql query | 5-20ms | high | slow |

本地验证这一步很重要,它能排除掉 Agent 框架的影响,单独确认脚本本身可用。之后接入框架时,如果出现问题,可以二分定位是脚本问题还是框架调用问题。

5. 运行验证:输入、输出和异常分支都要测

5.1 三组典型测试输入

除了正常输入,还要覆盖边界和异常情况,否则技能在真实对话里会表现在意想不到的地方。

第一类测试是正常场景。比如"画一下用户登录流程",模型应输出flow类型 JSON;"对比三种缓存方案",模型应输出table类型 JSON。这类测试用来确认主流程可用。

第二类测试是边界输入。空节点列表、只有一行数据的表格、列数不匹配的表格,脚本都要有明确表现。示例:

python3 scripts/render.py --type flow --data '{"nodes":[]}'

预期输出(empty flow),退出码为 0。这样模型在接到空输入时不会拿到乱码,而是能根据提示决定补充询问。

第三类测试是异常输入。JSON 格式错误、缺少字段、--type传了不支持的值,都应该有非零退出码和 stderr 错误信息。示例:

python3 scripts/render.py --type flow --data 'not-json'

预期输出JSON 解析失败: ...,退出码为 2。Agent 框架可以据此判断调用失败,而不是把一段错误文本当图形返回。

5.2 判读输出是否合格的检查清单

技能接入后要建立一套可复用的验收清单:

  • 脚本直接执行退出码为 0,stderr 无异常。
  • 输出在等宽终端和聊天代码块中都对齐。
  • 输出不包含多余反引号、转义反斜杠等会被 Markdown 误解的内容。
  • Agent 拿到脚本结果后保持原样返回,没有被重新排版。
  • 空输入、错误 JSON、缺少字段时有明确报错,而不是静默失败。
  • 中文内容在终端中能正常显示、不乱码。
  • 表格列宽按显示宽度计算,中文和英文混排不歪斜。

其中最后两条在中文场景里很容易踩坑。下面的排错章节会详细展开。

6. 常见问题排查:从现象倒推到修复

6.1 输入 /show-me 但没有任何反应

现象:用户在对话里输入/show-me flow ...,Agent 完全忽略,或者回复一段文字而不是图。

可能原因依次检查:

  1. 技能目录没有被框架扫描到。
  2. SKILL.md 里的namedescription与触发场景不匹配。
  3. 模型在系统提示词里看不到技能注册信息。
  4. 框架日志里根本没有触发记录。

排查方式:先确认技能目录位置和框架约定一致;再直接问模型"你现在能调用哪些技能",看它列出的列表里有没有 show-me;最后查看框架日志里是否存在技能加载失败的记录。注意:不要在 SKILL.md 里写复杂的语法规则,description 越直白,模型越容易准确触发。

6.2 脚本可用,但输出对不齐

现象:单独执行render.py输出正常,通过 Agent 返回后表格错位或框线断裂。

常见原因有三个:模型二次排版破坏了空格;聊天窗口不是等宽字体;中文显示宽度和英文不一致。

模型二次排版是最隐蔽的一个。脚本输出的对齐依赖空格数量,模型只要把某一行的空格重新调整,整张图就废了。所以 SKILL.md 里要写死"保持原样返回"。字体问题建议在技能说明里提示用户切换到等宽字体,或者在生成表格时减少对严格对齐的依赖。第三个问题需要更细致的宽度计算,下面单独说明。

6.3 中文字符和宽度计算问题

现象:中文节点绘图时,框线上下左右对不齐,看起来是"阶梯状"。

原因是 Python 内置的len()函数把中文字符按长度 1 计算,但绝大多数终端把中文按宽度 2 渲染。上面的示例只用了英文节点,所以对齐正常;换成"收到请求"这类中文节点,框线宽度就偏小。

问题现象常见原因检查方式处理建议
中文节点框线错位字符显示宽度未按 CJK 计算在终端直接执行脚本观察使用wcwidth计算显示宽度
中文乱码运行环境编码不是 UTF-8查看输出的字节序列设置PYTHONIOENCODING=utf-8
列宽计算偏小len()不区分字符宽度打印每列计算值宽度计算函数抽象出来单独测试

修复方式是在渲染函数里引入wcwidth库,用它替代len()计算宽度。这个改动看起来小,但对中文 Agent 场景是刚需,建议在技能一开始就处理好,而不是等用户反馈后再补。

6.4 和 MCP 工具职责重复

现象:项目里同时有渲染 Skill 和某个 MCP Server,MCP 也能生成图表,两个能力看似重复。

排查时先明确各自边界。如果 MCP Server 提供的是数据查询能力,只是返回了原始数据,那么渲染仍然应该由 Skill 完成;如果 MCP Server 本身就是一个专业的图表生成服务,那么 Skill 可以退化为一个薄封装,负责把用户意图转成 MCP Server 的调用参数。

问题现象常见原因检查方式处理建议
Skill 和 MCP 同时被触发两者 description 描述重叠查看调用日志收紧 Skill 的触发条件
MCP 返回数据后 Skill 不渲染编排层未把数据传给脚本检查框架上下文明确数据流方向
输出格式不一致多套渲染逻辑竞争对比历史输出固定一套渲染器,MCP 只供数据

7. 最佳实践与扩展方向:让技能保持干净

7.1 让 Skill 保持"渲染器"的纯粹性

给 Agent 设计技能时,最容易犯的错误是把判断逻辑也塞进脚本里。脚本一旦开始做语义判断,就失去了确定性,也难测试。

推荐边界是:模型负责把开放问题转成结构化输入,代码负责把结构化输入稳定渲染成输出。理解意图是模型的长处,精确排版是代码的长处。让两边各干各的,技能才可靠。

具体落地建议:

  • 输入格式固定为 JSON,字段含义写在 SKILL.md 里。
  • 渲染脚本不做业务推理,只做格式转换。
  • 为每个渲染函数写单元测试,覆盖正常、空输入、异常输入。
  • 模板样式集中管理,不要散落在系统提示词里。

7.2 接入生产环境前要补齐的能力

学习环境里跑通脚本,和生产环境接入 Agent 工作流,中间还有一段距离。生产环境至少要考虑以下能力:

关注点开发/学习阶段生产环境要求
配置来源脚本参数写死技能目录、JSON schema、风格配置外置
日志直接打印记录触发时间、输入摘要、退出码、耗时
权限本机执行限制脚本可访问的目录和环境变量
回滚直接改文件技能包版本化,可快速切换版本
测试覆盖手动验证输出快照测试、回归测试
资源消耗忽略超时、重试、输入长度上限

7.3 扩展方向

最小实现跑通后,可以考虑以下扩展:

  • 增加更多布局类型:横向流程图、树形结构、环形依赖图。
  • 输入格式从 JSON 扩展为 YAML,降低模型生成参数的难度。
  • 输出端增加终端配色或 HTML 片段,适用不同展示场景。
  • 接入 MCP Server 获取真实数据,再由 Skill 渲染成图,形成完整数据链路。
  • 对超大结构做分段渲染,避免一次输出超过聊天窗口限制。
  • 增加多语言宽度处理,让中英文混排和纯中文内容都能对齐。

对新手来说,最有价值的练习不是把脚本写得多完善,而是先想清楚一条边界:哪些判断交给模型,哪些判断交给代码。/show-me 这类技能给出了一个很好的答案——把渲染这种确定性工作交给代码,把理解意图这种开放工作留给模型。明白这条边界之后,你就能为自己的 Agent 设计出更多干净的技能包,而不是每次让模型在长文本里自由发挥。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/29 9:55:16

推广CodeWhisperer三个月被卸载率打脸:我漏算的变量叫迁移学习

推广CodeWhisperer三个月被卸载率打脸:我漏算的变量叫迁移学习 周一例会上,当我展示团队试用 CodeWhisperer 的统计数据时,沉默持续了整整十秒--17 个人里 7 个选择了卸载,还有 3 个虽然留着插件但几乎没触发过补全。老板问了一句:“工具不好用,还是我们没用对?” 我当时想当…

作者头像 李华
网站建设 2026/8/29 9:55:09

运营级在线客服系统源码怎么选?落地与避坑实战指南

简介&#xff1a;在线客服系统是连接企业与用户的实时沟通桥梁&#xff0c;其核心价值在于稳定、高效地支撑多角色协同工作。构建一套真正可运营的客服系统&#xff0c;首先需理解其底层原理&#xff1a;基于WebSocket实现双向低延迟通信&#xff0c;配合心跳保活与自动重连机制…

作者头像 李华
网站建设 2026/8/29 9:53:10

LocalSend 跨平台文件传输三步指南

LocalSend 跨平台文件传输三步指南 【免费下载链接】localsend An open-source cross-platform alternative to AirDrop 项目地址: https://gitcode.com/GitHub_Trending/lo/localsend LocalSend 是一款开源的跨平台文件传输工具&#xff0c;让同一局域网内的 Android、…

作者头像 李华
网站建设 2026/8/29 9:50:54

Python零基础学习路线:爬虫与数据分析实战指南(含代码)

看到一套标注着“几百集”的Python教程&#xff0c;大部分人的第一反应是收藏&#xff0c;第二反应是从第1集开始跟着敲&#xff0c;敲到第10集左右就搁置吃灰。这并不是自制力的问题&#xff0c;而是缺少一条清晰的学习路线&#xff1a;不知道每个阶段该掌握什么&#xff0c;不…

作者头像 李华
网站建设 2026/8/29 9:50:40

前端性能优化面试全攻略:从指标采集到白屏排查

1. 面试官到底想从“性能优化”里问出什么1.1 性能优化在面试中的真实定位铜九铁十&#xff0c;秋招和跳槽季一起挤过来&#xff0c;前端岗位的面试题翻来覆去就那么几大类&#xff1a;框架原理、工程化、手写代码、计算机基础&#xff0c;剩下的就是性能优化。性能优化这玩意儿…

作者头像 李华