如果你正在调试一个稍微复杂一点的 Agent,一定遇到过这种场景:模型返回了一长串 JSON,或者输出了一堆毫无结构的日志,你盯着终端半天,脑子里只剩一个疑问——它到底想告诉我什么?
这其实是当前 Agent 应用里非常隐蔽、却非常普遍的痛点。我们花了很多精力让模型“会干活”,却没有认真设计它“怎么说话”。结果是:Agent 的能力越来越强,输出越来越难懂。人类和 Agent 之间缺少一种高效、紧凑的沟通方式。
show-me就是冲着这个问题来的。从它在 Hacker News 上的标题就能看出,这是一个agent skill,目标是生成compact visual representations,也就是紧凑的可视化表示。本文会讲清楚四个问题:Agent Skill 到底是什么、它和 MCP 有什么区别、show-me 这类 skill 是怎么工作的、以及你在自己的项目里该怎么用、有哪些坑。
先说一个判断:show-me 这类 skill 的价值,不是让 Agent 多长出一只手,而是重新定义了 Agent 的“表达方式”。在调试、数据探查、报告生成这类场景里,这种改变带来的体感差异是质的。
1. 这篇文章真正要解决的问题
先对齐一下读者画像。如果你属于以下三类人,这篇文章会比较适合你:
- Agent 应用开发者:正在用 Claude、GPT、Qwen 等模型搭建 Agent,对工具调用、function call 已经有一定了解,但对“Agent Skill”这个概念还不够清楚。
- Prompt Engineer 或 AI 应用架构师:需要为团队设计一套可复用的 Agent 能力体系,想知道 Skill 和 MCP 应该怎么选、怎么配合。
- 技术负责人或技术选型者:想评估要不要引入 Agent Skill 这种新形态,它到底解决了什么问题,适合哪些业务场景。
这篇文章主要解决三个问题:
- 认知层面:Agent Skill 不是 MCP 的替代品,也不是 function call 换个名字。它的本质是给 Agent 一套“能力使用方法”,而 show-me 是这套思路的一个具体落地。
- 实践层面:我们带着“如何写一个类似 show-me 的 skill”这个目标,从 skill 的目录结构、描述文件、核心脚本到调用链路,一步步拆开看。
- 避坑层面:skill 设计里最容易被忽略的边界条件、权限问题和上下文占用问题,哪些坑需要在项目早期就规避。
关于 show-me 这个项目本身,目前公开的信息主要是它在 Hacker News 上的标题与简介,完整 API 和内部实现要以项目仓库为准。所以本文更侧重于讲清楚这一类 Agent Skill 的设计思路和工程实现方式,你可以把 show-me 当成一个非常有代表性的案例来理解。
2. 基础概念:Agent Skill 到底是什么
2.1 一个类比:新员工的入职手册
想理解 Agent Skill,可以把它想象成给 AI 员工准备的一份“岗位操作手册”。
假如你是一家公司的主管,招进来一个能力很强、但对你公司一无所知的新人。你不可能只丢给他一句“你去把客户搞定”就完事。你会给他一份文档,里面写着:公司的客户是谁、常用的 CRM 系统怎么登录、报价单模板在哪里、遇到售后问题该找哪个部门。这份文档就是“Skill”。
所以 Agent Skill 在技术上的定义是:一段结构化的能力描述与操作说明,配合必要的脚本和资源,让模型在需要时按说明调用和执行。
常见的 Skill 结构大致如下:
skills/ show-me/ SKILL.md scripts/ to_svg.py to_table.py assets/ template.svgSKILL.md是核心,它负责告诉模型这个 skill 是干什么的、什么场景下用、参数是什么、输出是什么规范。模型本身不需要预先掌握 show-me 的实现细节,它只需要读到这份文档,然后在合适的任务里调用对应的脚本。
2.2 它解决了什么问题
在没有 Skill 机制之前,Agent 的能力扩展主要靠 function calling。你需要预先定义一堆函数,模型根据用户指令去匹配函数。这种方式的问题是:
- 函数越多,模型选错函数的概率越高。
- 函数的定义本身缺少使用上下文,模型不知道“什么时候该用哪个”。
- 函数通常是单次调用,难以表达“先转换数据,再生成可视化,再进行解释”这样的组合流程。
Skill 的引入改变了这一点。它不是给模型一个孤立的函数,而是给模型一个完整的操作手册。手册里不仅写了函数签名,还写了使用场景、处理流程、注意事项。模型在读取手册之后,可以自己决定怎么执行,甚至可以在多步任务中自由组合多个 Skill。
2.3 为什么 2025 年之后这个概念突然火了
一个非常直接的原因是:模型本身的指令跟随能力和长上下文能力变强了。以前模型读一份几百行的手册很容易迷失重点,现在主流模型可以稳定地按照手册执行任务。于是“给模型一份说明书,让它自己干”这种模式开始变得可靠。
同时,Agent 的落地场景在从“问答”转向“干活”。问答只需要模型输出文本,干活则需要模型操作工具、处理数据、生成成果物。Skill 恰好是连接“模型思考”和“实际动作”的一种结构化载体。
3. Agent Skill 与 MCP 的区别:一张表和两条路径
提到 Agent Skill,很多人会立刻想到 MCP(Model Context Protocol)。这是当前最热的话题,也是最容易搞混的地方。我们直接给出结论:
MCP 解决的是“Agent 怎么连上外部工具和数据”,Agent Skill 解决的是“Agent 怎么正确使用一个能力”。
它们是两个层面的事情。
3.1 核心对比
| 对比维度 | MCP(Model Context Protocol) | Agent Skill |
|---|---|---|
| 本质 | 标准化协议 | 能力包/操作手册 |
| 解决的问题 | 外部工具与模型的连接标准化 | 模型对特定任务的操作方法 |
| 类比 | USB-C 接口标准 | 设备驱动 + 使用说明书 |
| 关键组件 | MCP Server、MCP Client、工具暴露 | SKILL.md、脚本、模板、资源 |
| 是否需要网络 | 通常需要访问 Server | 可以完全本地静态 |
| 动态性 | 工具列表可实时发现 | 能力相对静态、按需执行 |
| 典型场景 | 让 Agent 查询数据库、调 API、访问知识库 | 让 Agent 按固定流程生成图表、写文档、做数据分析 |
| 设计目标 | 可互操作、动态发现 | 可复用、可组合、低上下文开销 |
3.2 它们是怎么配合的
一个比较常见的实践是:用 MCP 让 Agent 连接企业内部的数据服务,用 Skill 来定义“拿到数据之后怎么加工、怎么呈现”。
举个例子:
- MCP Server 暴露了一个
query_sales_data工具,Agent 可以通过它查询销售数据库。 - 查询完成后,Agent 需要把结果用紧凑图表展示给用户。
- 此时 Agent 调用 show-me 这个 Skill,读取 SKILL.md,调用内部脚本把查询结果转换成 SVG 图表或紧凑表格。
两者不是竞争关系,而是协作关系。MCP 是“水管”,Skill 是“水龙头和过滤网”。一个负责输送数据,一个负责把数据变成可用的东西。
3.3 为什么不能互相替代
只靠 MCP 不行,因为协议本身不规定“某个工具该怎么用才符合业务规范”。连接上数据库之后,模型仍然不知道报表应该用什么格式、口径是什么、敏感字段要不要隐藏。这些知识必须沉淀在 Skill 里。
只靠 Skill 也不行,因为没有统一的连接标准,每个 Skill 都要自己实现外部系统对接,重复建设且难以复用。
所以,更合理的架构是:
Agent ├── MCP Client → MCP Server → 外部数据/工具 └── Skill 目录 → SKILL.md → 处理脚本/模板4. show-me 的核心思路:紧凑可视化表示
4.1 为什么是“compact”而不是“rich”
一提到可视化,很多人会想到大屏、炫酷的 Dashboard、各种各样的图表库。但 show-me 的标题里特别强调了一个词:compact,紧凑。
这个选择很有意思。它没有选择“最丰富”的可视化,而选择了“最省”的可视化。
原因可以从三个角度理解:
第一,Token 成本。Agent 生成一张复杂图表,背后往往是一大段 SVG 代码或者 HTML 脚本。大而全的可视化会消耗大量输出 Token,而且生成时间更长。紧凑表示则能用最少的字节传递核心信息。
第二,人机协作的注意力。市面上绝大多数 Agent 输出的是文本。当 Agent 在做数据分析时,它可能生成 500 行 JSON,但用户只关心其中的峰值、趋势和异常。紧凑可视化把关键信息提炼成一目了然的形式,避免用户在信息海洋里做人工检索。
第三,上下文连续性。在多轮对话中,Agent 如果每次都输出超长可视化代码,很容易撑爆上下文窗口。紧凑表示体积小,可以保留在上下文里供后续推理使用。
4.2 什么是紧凑可视化表示
从常见的实现方式来看,紧凑可视化表示可能包括以下几种形式:
- 小型 SVG 图形,适合直接嵌入 Markdown 或 HTML。
- 终端友好的 ASCII 表格或图表,适合 CLI 场景。
- 极简的二维文本表格,适合快速展示数据结构和统计信息。
- 小型 HTML 片段,适合网页内嵌展示。
这些形式有一个共同点:体积小、人可读、可渲染、无需重型依赖。
4.3 show-me 解决的真实场景
假设你在调试一个 Agent,它需要从一份数据里找出异常值。传统输出可能是:
{"status": "ok", "data": [{"region": "east", "value": 120}, {"region": "west", "value": 3}, ...]}人眼扫过去,很难立刻形成判断。但如果 Agent 用 show-me 输出一张紧凑图表:
区域 | 预期值 | 实际值 | 偏差 东区 | 100 | 120 | +20% 西区 | 50 | 3 | -94% ⚠️异常一目了然。这就是“紧凑可视化表示”在真实工作流里的价值。
5. 实操准备:环境与前置条件
下面我们进入实践部分。先说明一点:本节给出的示例是通用实现思路,用于帮助你理解 Agent Skill 的构建和调用流程。如果你要使用 show-me 项目本身,请以该项目 README 和官方文档为准。
5.1 环境要求
你需要准备以下环境:
| 依赖项 | 说明 |
|---|---|
| Python 3.9+ | 推荐 3.10 或 3.11,用于运行演示脚本 |
| 一个支持 Agent Skill 的模型运行时 | 例如支持 Claude Skills 的客户端,或你自建的 Agent 框架 |
| 基础 Python 库 | 如jinja2,用于模板渲染(如需要) |
| 终端 | 支持 ANSI 或 UTF-8 的现代终端 |
如果你还没有支持 Skill 的运行时,也可以选择自建一个最简框架。本文的演示代码不依赖任何特定厂商 SDK,核心思路可以迁移到不同平台。
5.2 理解 Skill 目录结构
在动手之前,我们先约定一个最小目录结构:
my-agent/ skills/ show-me/ SKILL.md scripts/ to_table.pySKILL.md主要负责给模型看,scripts/里的脚本用于实际执行。这里尤其要注意:SKILL.md 的质量直接决定了模型会不会正确使用这个 Skill,它比脚本本身更重要。
6. 完整示例:写一个类似 show-me 的最小 Skill
这一节我们分三步走:先写SKILL.md,再写转换脚本,最后通过一个 Agent 调用链路把它跑起来。
6.1 第一步:编写 SKILL.md
新建文件skills/show-me/SKILL.md:
--- name: show-me description: 将结构化的数据转换为紧凑的可视化表示,适用于数据摘要、结果简报、调试信息展示等场景。 --- # show-me 将输入数据转换成适合在终端、Markdown 或 Web 页面中快速展示的紧凑可视化表示。 ## 适用场景 - 需要快速查看数据结构和统计信息 - 需要把查询结果或日志摘要呈现给用户 - 需要生成可嵌入文档的图表或表格 ## 输出格式规则 1. 优先输出 Markdown 表格,字段不超过 6 列。 2. 如果数据量较大,先聚合再展示,保留 Top 5 或异常项。 3. 输出必须紧凑,不使用冗余前缀和解释性废话。 4. 除非用户明确要求,不生成完整 HTML 页面。 ## 输入参数 - `data`: JSON 数组,每个元素是一个对象 - `columns`: 可选,需要展示的字段列表 ## 示例 用户输入: data: [{"city":"北京","value":120},{"city":"上海","value":80}] columns: ["city", "value"] Agent 输出: | 城市 | 数值 | | --- | --- | | 北京 | 120 | | 上海 | 80 |这里的关键是:让模型知道“这个技能输出什么格式”“什么场景下调用”。模型在运行时会先读取这份文档,再决定是否使用。
6.2 第二步:编写转换脚本
新建文件skills/show-me/scripts/to_table.py:
#!/usr/bin/env python3 # 文件路径:skills/show-me/scripts/to_table.py # 功能:将 JSON 数据转换为 Markdown 紧凑表格 import json import sys def to_markdown_table(data, columns=None): """将 JSON 数组转换为紧凑的 Markdown 表格。""" if not data: return "_空数据_" # 自动从第一条数据推导字段 if columns is None: columns = list(data[0].keys()) # 表头 lines = [] lines.append("| " + " | ".join(columns) + " |") lines.append("| " + " | ".join(["---"] * len(columns)) + " |") # 数据行 for row in data: cells = [] for col in columns: val = row.get(col, "") # 对于较长的值,截断显示 if isinstance(val, str) and len(val) > 20: val = val[:17] + "..." cells.append(str(val)) lines.append("| " + " | ".join(cells) + " |") return "\n".join(lines) if __name__ == "__main__": # 从标准输入读取 JSON payload = json.load(sys.stdin) data = payload.get("data", []) columns = payload.get("columns") print(to_markdown_table(data, columns))这个脚本做的事情很简单:读取标准输入里的 JSON,输出一个 Markdown 表格。核心逻辑包括字段自动推导、长文本截断、空数据处理。
你可以先用命令行验证脚本本身:
echo '{"data": [{"city": "北京", "value": 120}, {"city": "上海", "value": 80}]}' | python3 skills/show-me/scripts/to_table.py预期输出:
| city | value | | --- | --- | | 北京 | 120 | | 上海 | 80 |这里字段名展示的是原始英文键,如果你希望展示中文列名,可以在调用时指定columns参数,或让 Agent 在输出前做一次列名映射。后面我们会讲到。
6.3 第三步:写一个 Agent 调用示例
现在模拟一个 Agent 调用链路。下面这段 Python 代码不是某个厂商 SDK 的完整实现,而是演示“模型判断需要调用 skill → 执行脚本 → 返回结果”这个过程的最小骨架。
# 文件路径:demo_agent.py # 功能:模拟一个支持 skill 调用的最小 Agent 执行流程 import json import subprocess def parse_user_intent(user_message): """ 这里在真实项目中应该调用大模型,由模型判断是否使用 show-me。 本示例为了演示,直接通过关键词简单判断。 """ return "show-me" in user_message or "图表" in user_message def call_skill(skill_script, input_data): """调用 skill 脚本,传入 JSON 数据,返回结果文本。""" proc = subprocess.run( ["python3", skill_script], input=json.dumps(input_data), text=True, capture_output=True, check=True, ) return proc.stdout.strip() def main(): user_message = "把下面的销售数据用紧凑图表展示:东区 120,西区 3,南区 89,北区 45" # 真实项目中,这里应该由 LLM 完成意图识别和参数抽取 if parse_user_intent(user_message): # 假设模型从用户消息中抽取的结构化数据 extracted_data = { "data": [ {"region": "东区", "value": 120}, {"region": "西区", "value": 3}, {"region": "南区", "value": 89}, {"region": "北区", "value": 45}, ], "columns": ["region", "value"], } result = call_skill("skills/show-me/scripts/to_table.py", extracted_data) print("=== Agent 输出的紧凑可视化 ===") print(result) else: print("未触发 show-me skill,走普通对话流程。") if __name__ == "__main__": main()运行:
python3 demo_agent.py预期输出:
=== Agent 输出的紧凑可视化 === | region | value | | --- | --- | | 东区 | 120 | | 西区 | 3 | | 南区 | 89 | | 北区 | 45 |到这里,我们已经跑通了一个 Skill 的最小闭环。真实项目中,意图识别和参数抽取是由大模型完成的,但整体架构一致:模型读 Skill 描述 → 判断要不要用 → 执行脚本 → 返回结果。
6.4 更接近 show-me 的思路:输出 SVG 缩略图
如果我们希望“可视化”更进一步,可以扩展脚本,让它输出一个小型 SVG 柱状图。这也是 compact visual representations 里很典型的一类实现。
新建文件skills/show-me/scripts/to_svg.py:
#!/usr/bin/env python3 # 文件路径:skills/show-me/scripts/to_svg.py # 功能:将简单数值数据渲染为内联 SVG 柱状图 import json import sys import html def to_svg_bars(data, width=240, height=120): """根据数据生成紧凑的 SVG 柱状图。""" if not data: return "" values = [item["value"] for item in data] max_val = max(values) n = len(values) bar_width = max(8, (width - 20) // n - 4) padding = 4 labels = [html.escape(str(item.get("label", i + 1))) for i, item in enumerate(data)] bars = [] for i, (item, label) in enumerate(zip(data, labels)): h = int((item["value"] / max_val) * (height - 30)) x = 10 + i * (bar_width + padding) y = height - 20 - h bars.append( f'<rect x="{x}" y="{y}" width="{bar_width}" height="{h}" ' f'fill="#4C8BF5" rx="2" />' ) bars.append( f'<text x="{x + bar_width // 2}" y="{height - 6}" ' f'font-size="9" text-anchor="middle">{label}</text>' ) svg = ( f'<svg xmlns="http://www.w3.org/2000/svg" width="{width}" height="{height}" ' f'viewBox="0 0 {width} {height}">' + "".join(bars) + "</svg>" ) return svg if __name__ == "__main__": payload = json.load(sys.stdin) data = payload.get("data", []) print(to_svg_bars(data))这段脚本把 JSON 数据渲染成内联 SVG,体积很小,可以直接嵌入 Markdown 或 HTML 文档。对应地,SKILL.md 里应该增加一段说明:“当用户希望看到图形化展示时,使用 to_svg.py 将数据渲染为 SVG。”
这种“文本表格 + 小型图形 + 紧凑体积”的组合,就是 show-me 这类 agent skill 的核心气质。它不追求大而全的可视化平台,而是追求在 Agent 工作流里快速生成、快速理解、低成本携带。
7. 运行结果与效果验证
7.1 如何验证 Skill 是否正常工作
建议按照以下顺序验证:
- 单测脚本:先不经过 Agent,直接给脚本输入 JSON,确认输出格式正确。
- 模拟调用:用示例代码模拟 Agent 调用脚本,确认调用参数和返回路径没有问题。
- 真实模型接入:接入大模型,用几个典型问题测试模型是否能在合适的时机主动调用 Skill。
7.2 成功判断标准
一个 Skill 接入成功,至少应该满足以下条件:
- 模型能在合适场景主动触发 Skill,而不是用户反复提醒。
- 输出格式稳定,没有明显字段错位。
- 输出结果体积显著小于原始数据,体现“紧凑”价值。
- 在多轮对话中,紧凑表示能被继续引用,不会因过长被模型忽略。
7.3 失败时先看哪里
如果模型没有正确触发 Skill,第一步不是调代码,而是检查SKILL.md的描述是否清晰。
- 描述里有没有明确触发场景?
- 示例是否足够具体?
- 模型读完之后,能不能判断“现在该用”还是“不该用”?
很多时候,问题不在代码逻辑,而在“说明书”写得不够好。
8. 常见问题与排查思路
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| 模型从不调用 show-me | 描述触发条件不明确 | 查看 SKILL.md 的 description 和场景说明 | 补充更具体的触发场景和示例,必要时在描述中加入“当用户需要查看数据摘要时”等显式表述 |
| 模型乱用 show-me | 覆盖场景过宽 | 检查模型实际输入和系统提示词 | 收紧适用场景,明确“不适用”条件 |
| 输出表格列名是英文,不够友好 | 缺少列名映射 | 检查脚本是否做了字段映射 | 在脚本中增加中文名映射字典,或让模型输出前重命名列 |
| 输出太长,失去“紧凑”意义 | 数据未做聚合 | 检查生成逻辑是否限制行数 | 在脚本或 SKILL.md 中规定最多展示 5 行,超过则聚合 |
| 多轮对话后输出被截断 | 可视化体积过大 | 检查 SVG/HTML 代码长度 | 压缩生成代码,去掉冗余属性,优先使用小型 SVG |
| Skill 脚本与模型运行环境隔离不足 | 脚本执行权限过高 | 检查运行方式 | 使用沙箱或受限用户执行脚本,禁止 shell 拼接 |
| 模型读不懂 SKILL.md | 文档结构混乱 | 检查 SKILL.md 是否按标准模板编写 | 使用标准 Frontmatter,加清晰示例,控制文档长度 |
这里的每一个问题在真实项目中都很常见。尤其是“模型乱用 Skill”和“输出过长”这两个问题,几乎必然出现,必须在设计阶段就做好约束。
9. 最佳实践与工程建议
9.1 Skill 设计原则
- 一个 Skill 只解决一类问题。show-me 的核心是“输出紧凑可视化”,不要在这个 Skill 里顺带做数据清洗或存储。
- SKILL.md 要短而准。模型读文档也是要花 Token 的。文档太长,重点反而容易被淹没。
- 用示例代替描述。模型对示例的理解能力远强于抽象描述。每个 Skill 至少给两个示例,一个简单,一个略复杂。
- 定义“不要怎么做”。很多 SKILL.md 只写了适用场景,没写不适用场景。建议明确写出“不适用于 XX 情况”,可以减少误调用。
9.2 输出规范设计
在团队里落地 Skill 时,建议把输出规范上升为工程标准。比如:
- 所有数据类输出默认使用 Markdown 表格,字段不超过 6 列。
- 表格行数超过 10 行时必须先聚合。
- 数值型字段保留两位小数。
- 禁止输出冗余的前缀解释,如“根据您的问题,以下是查询结果”。
这些规则可以写进 SKILL.md,也可以写进系统提示词。关键在于,所有 Skill 的输出风格要一致,否则用户会觉得很散。
9.3 与 MCP 的工程配合
在实际项目中,MCP 和 Agent Skill 通常是配合使用的。推荐的落地路径是:
- 用 MCP Server 统一暴露数据源和外部工具。
- 为每个关键业务动作设计一个 Skill,沉淀操作规范。
- MCP 负责“取数”,Skill 负责“加工和呈现”。
- 在模型评测阶段,分别记录打开 MCP 和打开 Skill 时的任务成功率,验证叠加效果。
9.4 安全边界与权限控制
这是最容易被忽略的部分。Skill 本质上是让模型执行一段预置脚本,一旦策略不当,可能带来风险:
- 脚本执行应遵循最小权限原则,不要让 Agent 以高权限账户运行。
- 对 Skill 的输入参数做校验,防止传入恶意路径或命令。
- 对输出内容做长度限制,防止 Agent 生成超大文件拖垮服务。
- 记录 Skill 调用日志,便于审计模型的行为。
- 涉及生产环境操作时,必须先在小范围验证,并准备回滚方案。
9.5 评测与迭代
Skill 不是写完就结束的,它需要持续评测。建议准备一组固定测试用例,每次修改 SKILL.md 或脚本后都回归一遍:
- 测试模型是否在合适时机触发 Skill。
- 测试输出格式是否符合预期。
- 测试极端输入(空数据、超大输入、非法字符)是否会导致崩溃。
10. 总结与后续学习方向
回到 show-me 这个项目。它给我们的最大启发是:Agent 的能力建设不只是“模型更强”“工具更多”,还包括“输出形态的设计”。当 Agent 能把复杂信息压缩成人类一眼能看懂的可视化表示时,Agent 才真正从“能回答问题”进化到“能交付结果”。
如果你现在正在做 Agent 应用,下一步可以这样做:
- 先在你的 Agent 里设计一个最小的 show-me 风格 Skill,比如“把 JSON 转成紧凑表格”。
- 观察模型会不会在合适时机主动调用它。
- 基于测试结果不断调优 SKILL.md 的描述和示例。
- 再补充 SVG 图表能力,让输出更丰富一些。
- 等流程稳定后,再把多个 Skill 组合起来,形成完整的 Agent 工作流。
值得继续深入研究的方向包括:Agent Skill 的可组合性、多 Skill 之间的调度策略、Skill 输出与 RAG 检索结果的融合、以及 Skill 在复杂多步任务中的评测方法。这些方向会直接影响 Agent 应用在生产环境中的稳定性。
最后提醒一句:Agent Skill 和 MCP 不是二选一的关系。理解这个区别,比记住任何一个具体项目都重要。show-me 只是一个很好的起点,但它代表的方向——让 Agent 学会“用紧凑的方式表达复杂信息”——会在未来很长一段时间里影响 Agent 应用的产品形态。