
在调试 Agent 链路时经常遇到一个很尴尬的处境对话上下文里的数据对象、工具调用记录、状态变更全都堆在一起肉眼很难快速判断当前到底执行到哪一步。尤其当多个 Agent 协作、工具链变长之后靠纯文本来“脑补”结构关系不仅慢还特别容易漏掉关键节点。后来接触到一个叫/show-me的 agent skill它解决的问题挺直接让 Agent 在对话中间输出一份“紧凑的可视化表示”把当前上下文、数据流、配置结构或 Schema 关系用尽量小的篇幅呈现出来。这篇教程就围绕这个项目展开会先讲清楚 agent skill 到底是什么、它和 MCP 有什么区别再带着大家从零实现一个/show-me风格的 skill最后补上常见报错和工程落地建议。无论你是刚开始接触 Agent 开发还是已经在做多工具编排这篇文章都能给你一条可复制的实操路径。1. 背景与核心概念从一条斜杠命令说起1.1 它是什么/show-me的定位/show-me是一个 agent skill准确说是一个“技能包”。当用户或上层编排器在对话中唤起它时Agent 会把内部状态或指定对象转换成紧凑的可视化表示例如 ASCII 结构图、Mermaid 片段、缩进式树形图或小型 SVG。它面向的不是最终产品里的复杂大屏而是开发调试阶段的高频需求。比如查看当前 Agent 的上下文结构。查看一次工具调用的执行路径。查看配置项之间的依赖关系。查看数据库表之间的关联维度。查看多条消息记录里的关键数据流。在没有这类 skill 时Agent 只能把上游数据原样返回用户需要自己从大段 JSON 或日志里提取信息。有了/show-me之后Agent 可以直接给出“人眼友好”的结构化表达而且输出体积能做到非常小适合放在对话窗口、终端和提交说明里。1.2 为什么需要“紧凑”的可视化表示“紧凑”这个词是理解这个项目的关键。传统的可视化方案通常由前端图表库生成完整图片信息量虽大但有两个问题生成成本高需要额外渲染流程、颜色管理和布局计算。传递成本高完整图片在聊天窗口、终端或代码评审场景中并不方便插入。Agent 场景下的可视化目的是让用户“秒懂结构”而不是做一张炫酷大图。所以/show-me强调的是行数少一般控制在 20~60 行以内。文本化不依赖图片直接以 Markdown 或纯文本输出。信息密度高每个节点都尽量携带有效信息。解析友好不牺牲可读性的前提下可以被后续工具继续处理。换句话说它输出的是一份“结构速写”而不是“完整蓝图”。1.3 它解决什么问题、适用哪些场景/show-me解决的核心问题是Agent 内部状态的透明度不足。传统开发中我们可以用断点、日志和单测来观测程序状态。但 Agent 是一个基于自然语言和工具调用的运行时它的状态分散在 Prompt、消息记录、工具返回值和内存存储中。调试时很难直接回答“当前 Agent 到底知道什么”。/show-me把这类状态显式化。适用场景包括Agent 开发调试观察上下文成长过程。多 Agent 协作梳理消息传递关系。工具链排错定位哪一步调用异常。配置审查快速识别配置依赖和潜在冲突。2. Agent Skill 到底是什么2.1 从“提示词”到“技能包”Agent Skill 可以理解为“一套可复用的能力封装”。它的底层可能包含 Prompt 模板、工具调用规则、输出格式约束甚至一小段脚本逻辑。但对外暴露时它是一个带名字、带描述、带入参定义的完整模块。普通提示词解决的问题是“某一次对话中怎么生成”Agent Skill 解决的问题是“在多种场景下Agent 如何稳定地完成一类任务”。举个例子对比项普通 PromptAgent Skill定位单次指令可复用能力结构自然语言描述有元信息、参数、输出约束复用性低每次要重写高可声明后反复调用维护方式散落在代码中独立文件、目录、版本管理触发方式用户手动描述斜杠命令、自动路由或函数调用/show-me的“/”前缀不是随意设计的它代表了命令式触发。用户不需要说“请你把当前上下文画成一个结构图”只需要输入/show-meAgent 就能自动匹配到对应技能。2.2 Skill、Tool、Plugin 的关系不少初学者会把 Skill、Tool、Plugin 混在一起这里做一个简单梳理Tool工具Agent 可以调用的外部函数例如搜索、发请求、读文件。它是原子的、无状态的。Skill技能围绕某个目标组织起来的指令 工具调用组合。它可以调用多个 Tool也可以只基于 Prompt 完成输出。Plugin插件通常是一个更大的生态概念可能包含多个 Tool 和 Skill 的打包分发。/show-me属于 Skill 层它可以把“读取上下文”“读取配置”“格式化输出”这些工具组合起来然后对外提供一个统一入口。2.3 Skill 文件的基本结构在实现层面一个 Skill 通常由元信息和执行逻辑组成。下面是一个典型的声明结构name: show-me description: 生成紧凑的可视化表示帮助快速展示上下文结构、数据流、配置依赖或 Schema。 version: 1.0.0 author: your-team trigger: type: command command: /show-me parameters: - name: target type: string required: true description: 想要可视化的对象如 context、flow、config、schema - name: format type: string required: false enum: [ascii, tree, mermaid, json] default: ascii description: 输出格式偏好这里的关键并不是具体字段而是它的设计思想把“让 Agent 干什么”和“Agent 怎么干”分离。外层调用方只需要告诉它“可视化什么”至于用哪种布局、怎么压缩信息密度由 Skill 内部逻辑决定。3. Agent Skill 与 MCP 的区别3.1 MCP 是什么MCPModel Context Protocol是一个开放协议它解决的是“模型如何标准化地连接外部工具和数据源”的问题。你可以把它理解成 Agent 世界的“USB-C 接口”——只要工具实现了 MCP 协议模型就能通过统一方式发现工具、调用工具、接收结果。MCP 的核心要素包括工具发现机制。标准化的请求/响应格式。资源访问规则。基于 JSON-RPC 的交互流程。它偏底层是“管道”层面的标准。3.2 Skill 与 MCP 的分工差异很多人把这两个概念搞混是因为它们都和“让 Agent 更强大”有关但作用层级完全不同。维度Agent SkillMCP本质能力封装技能配方通信协议连接标准层级应用层协议层解决什么问题Agent 如何稳定完成某类任务Agent 如何标准化调用外部能力是否包含 Prompt通常包含不包含是否规定传输格式不规定规定典型形态目录 描述文件 模板Server 实现 客户端 SDK一个更直观的类比MCP 像是“插座标准”规定了电流规格和插孔形状。Skill 像是“电器使用方法”告诉你按哪个按钮能让微波炉热饭。插座可以给微波炉供电但微波炉能不能热饭取决于内置的加热逻辑而不是插座本身。3.3 它们如何配合使用实际项目中Skill 和 MCP 并不是二选一的关系而是经常组合出现。一个 Agent 可以通过 MCP Server 暴露“读取数据库 Schema”的工具然后show-me这个 Skill 在内部调用该工具把 Schema 数据转换成紧凑的可视化表示。Skill 负责“如何组织输出”MCP 负责“如何稳定地获取数据”。所以正确理解是当你想让 Agent 获得某种能力可以选择实现一个 Skill。当你想让多个 Agent、多个客户端共享同一套工具和数据接口可以选择基于 MCP 实现标准化连接。当两者结合时MCP 为 Skill 提供稳定的数据通路Skill 为 MCP 工具提供场景化的调用方式。4. 环境准备与项目结构下面进入实操部分。这一节的目标是搭建一个可以运行的/show-me风格 skill 项目。4.1 前置条件由于不同 Agent 框架的 Skill 加载机制不完全一样本文以一个通用的目录化 Skill 为例重点演示思路。你可以将它适配到自己的框架中。建议环境Python 3.10用于编写渲染逻辑。任意支持斜杠命令或技能路由的 Agent 框架例如自研 Agent、LangChain 或类似工具。一个能加载 YAML 配置的依赖库如pyyaml。版本需要根据你的项目实际情况调整。本文示例不绑定某个具体框架的私有 API重点是把“Skill 的目录结构”和“渲染逻辑”讲清楚。4.2 Skill 目录结构一个独立 Skill 推荐采用以下结构show-me/ ├── SKILL.md ├── assets/ │ └── templates/ │ ├── ascii_tree.txt │ └── mermaid_template.txt └── scripts/ ├── collect.py └── render.pySKILL.md描述文件包含技能元信息、触发方式和输出规则。assets/templates/输出模板。scripts/收集数据和渲染可视化的脚本。4.3 创建 SKILL.md 文件创建show-me/SKILL.md--- name: show-me description: 生成紧凑的可视化表示用于快速展示上下文、数据流、配置和 schema。 version: 1.0.0 trigger: type: command command: /show-me parameters: - name: target type: string required: false default: context - name: format type: string required: false default: ascii --- # show-me 当用户输入 /show-me 时你需要 1. 根据 target 参数确定可视化对象。 2. 收集相关数据优先使用已有的工具返回值。 3. 使用紧凑的可视化格式输出行数尽量控制在 40 行以内。 4. 如果信息不足以绘制先输出缺失部分并给出获取建议。这个SKILL.md的价值在于把 Agent 的“行为约定”写清楚。Agent 加载后会在对话上下文中看到这些规则从而在触发时按规则执行。5. 从零实现一个/show-me风格 Skill5.1 设计目标在代码实现前先明确我们想让/show-me做什么输入目标对象类型。输出紧凑可视化文本。特性无第三方前端依赖、输出稳定、对中文友好。5.2 编写数据收集脚本创建show-me/scripts/collect.py模拟从上下文或配置中收集数据。# 文件路径show-me/scripts/collect.py 数据收集脚本根据 target 返回结构化数据。 实际项目中这一步可能会调用 MCP 工具或读取内部状态。 def collect_context(): 模拟上下文状态 return { messages: [ {role: user, content: 查询用户订单}, {role: assistant, content: 调用订单服务}, ], memory: {user_id: u_1024, cart: [item_1, item_2]}, } def collect_config(): 模拟配置结构 return { app: { name: agent-demo, port: 8080, debug: False, }, llm: { provider: openai-compatible, temperature: 0.2, }, tools: { enabled: [search, calculator], timeout: 30, }, } def collect_flow(): 模拟工具调用链路 return [ {step: 1, tool: search, status: success, cost_ms: 120}, {step: 2, tool: calculator, status: success, cost_ms: 15}, {step: 3, tool: order_api, status: failed, cost_ms: 300}, ] def collect_schema(): 模拟数据库表关系 return { users: {fields: [id, name, email], relations: [orders.user_id]}, orders: {fields: [id, user_id, amount, status], relations: [items.order_id]}, items: {fields: [id, order_id, sku, price], relations: []}, } COLLECTORS { context: collect_context, config: collect_config, flow: collect_flow, schema: collect_schema, }这里每个函数对应一种可视化对象。实际使用中collect_context可以接入 Agent 的上下文管理器collect_schema可以通过 MCP 工具查询真实的数据库结构。5.3 编写渲染脚本创建show-me/scripts/render.py这部分是/show-me输出能力的关键。# 文件路径show-me/scripts/render.py 渲染脚本把结构化数据转换成紧凑的可视化文本。 支持 ascii 和 tree 两种格式mermaid 可作为扩展。 from typing import Any, Dict, List def render_tree(data: Dict[str, Any], prefix: str , depth: int 0) - str: 把嵌套字典渲染成缩进树 lines [] for key, value in data.items(): if isinstance(value, dict): lines.append(f{prefix}{key}:) lines.append(render_tree(value, prefix , depth 1)) elif isinstance(value, list): lines.append(f{prefix}{key}: [{, .join(str(v) for v in value)}]) else: lines.append(f{prefix}{key}: {value}) return \n.join(lines) def render_flow(flow: List[Dict[str, Any]]) - str: 把工具调用链路渲染成箭头流 lines [] for item in flow: marker ✅ if item[status] success else ❌ lines.append( f[{item[step]}] {item[tool]} {marker} f({item[cost_ms]}ms) ) lines.append(└── 结束) return \n.join(lines) def render_schema(schema: Dict[str, Any]) - str: 把表关系渲染成紧凑结构 lines [数据库 Schema ] for table, info in schema.items(): fields , .join(info[fields]) rels , .join(info[relations]) if info[relations] else - lines.append(f■ {table}) lines.append(f 字段: {fields}) lines.append(f 关联: {rels}) return \n.join(lines) def render(data: Dict[str, Any], target: str, format: str ascii) - str: 统一渲染入口 if format tree: return render_tree(data) if target flow: return render_flow(data) if target schema: return render_schema(data) # 默认 ascii 风格 return render_tree(data)5.4 组合入口脚本创建show-me/scripts/main.py把收集和渲染串联起来# 文件路径show-me/scripts/main.py import sys from collect import COLLECTORS from render import render def main(): target sys.argv[1] if len(sys.argv) 1 else context output_format sys.argv[2] if len(sys.argv) 2 else ascii collector COLLECTORS.get(target) if not collector: print(f不支持的目标类型{target}) print(可选类型context, config, flow, schema) return 1 data collector() result render(data, target, output_format) print(result) return 0 if __name__ __main__: sys.exit(main())5.5 运行与验证在终端中运行cd show-me/scripts python main.py context预期输出类似messages: [{role: user, content: 查询用户订单}, {role: assistant, content: 调用订单服务}] memory: user_id: u_1024 cart: [item_1, item_2]再运行python main.py flow预期输出类似[1] search ✅ (120ms) [2] calculator ✅ (15ms) [3] order_api ❌ (300ms) └── 结束再运行python main.py schema预期输出类似数据库 Schema ■ users 字段: id, name, email 关联: orders.user_id ■ orders 字段: id, user_id, amount, status 关联: items.order_id ■ items 字段: id, order_id, sku, price 关联: -到这里一个最小的/show-me风格 skill 已经跑通。它把“数据收集”和“紧凑渲染”拆分成了独立模块后续要扩展新的可视化对象只需要在COLLECTORS里加一个函数再在render.py里加对应渲染逻辑即可。6. 进阶配置把 Skill 接入 Agent6.1 声明触发命令在真实的 Agent 框架中/show-me斜杠命令通常由前端或 Agent Runner 解析。触发流程如下用户输入/show-me flow。框架解析出 skill 名show-me和参数flow。框架读取SKILL.md。框架执行技能同时把当前上下文注入到脚本环境中。脚本输出文本框架回传给用户。如果你是在自研 Agent 中接入可以参考以下 Python 示例# 文件路径agent_router.py 简化版 Skill 路由示例 import subprocess import shlex SKILL_COMMANDS { /show-me: show-me/scripts/main.py, } def handle_command(user_input: str) - str: if user_input.startswith(/show-me): parts shlex.split(user_input) target parts[1] if len(parts) 1 else context fmt parts[2] if len(parts) 2 else ascii script SKILL_COMMANDS[/show-me] result subprocess.run( [python, script, target, fmt], capture_outputTrue, textTrue, timeout30, ) return result.stdout return 未知命令这个例子展示的是路由层逻辑。注意这里用了subprocess去调用脚本只是一种便于理解的接入方式。实际生产环境中更推荐直接通过函数调用或事件机制加载 Skill避免频繁启停 Python 进程。6.2 将 Mermaid 作为可选输出虽然默认输出是 ASCII 风但/show-me这类 skill 完全可以把 Mermaid 作为高密度输出格式。比如渲染流程时可以输出flow LR A[用户请求] -- B[调用搜索工具] B -- C{是否成功} C --|是| D[返回结果] C --|否| E[记录错误]这样既保持了文本特性又能在支持 Mermaid 的编辑器中直接渲染成图。在你的SKILL.md中可以增加一条规则- 当 format 为 mermaid 时输出 Mermaid 代码块并确保语法完整。6.3 对输出做长度兜底Agent 场景里最怕的是输出过长。可以在渲染函数里加一个最大行数限制# 在 render.py 中增加截断逻辑 MAX_LINES 40 def safe_render(data, target, fmtascii): text render(data, target, fmt) lines text.splitlines() if len(lines) MAX_LINES: lines lines[:MAX_LINES] lines.append(... (已截断)) return \n.join(lines)这个兜底机制可以在 Agent 输出阶段降低可用性风险。7. 常见问题与排查思路在动手实现或改造/show-me这类 Skill 时经常遇到下面几个问题。问题现象常见原因解决思路输入/show-me无响应斜杠命令未注册检查命令路由表确认 skill 名称匹配输出格式混乱SKILL.md 中的格式约束不够明确在描述文件中增加“必须输出 code block”等强约束脚本运行报 ModuleNotFoundError脚本间引用路径错误用python -m方式运行或在入口脚本中修正sys.path中文对齐错乱等宽字体下字符宽度不一致避免用空格对齐中英文改用缩进或列表数据收集超时工具调用链路过长给 collect 阶段设置超时超过则返回部分数据可视化内容过深嵌套字典递归无深度限制在 render 函数中增加最大递归深度7.1 Skill 无响应排查顺序如果你接入框架后发现/show-me不生效按下面顺序排查看路由表是否把/show-me映射到了正确脚本。看描述文件SKILL.md 是否被正确加载。看脚本权限是否有执行权限Python 环境是否可用。看输出日志Agent 框架通常会记录工具调用结果。7.2 输出过长问题如果输出超过对话窗口限制优先检查是否按 target 正确过滤字段。是否设置最大行数。是否误把原始 JSON 直接输出。记住/show-me的目标是“紧凑”。如果输出比原始数据还长说明渲染逻辑失败了。8. 最佳实践与工程建议8.1 输出格式要稳定可解析Agent Skill 的输出不只是给人看的它还可能被后续工具继续消费。建议优先使用 Markdown 代码块包裹输出。节点符号固定不要随意换。关键字段加前缀如工具: search、状态: success。保留机器可读取的行结构。8.2 紧凑不等于晦涩有些开发者为了压缩行数把变量名全部简写成单个字母结果别人根本看不懂。紧凑可视化应该遵循保留语义化名字。删除次要字段而不是压缩字段名。用符号增强层次感而不是替代文字。8.3 Skill 参数要少而清晰Agent 对参数的理解来自描述文件。如果参数过多、边界模糊Agent 很容易猜错意图。建议参数 2~3 个为佳。每个参数给出枚举值。提供默认值让用户可以不传参直接触发。8.4 把 Skill 纳入版本管理Skill 本质上是代码 文档的组合。建议把 SKILL.md、脚本、模板都放进 Git 仓库并遵守团队约定每次修改 Skill 行为同步更新描述文件。记录变更日志方便回滚。为关键 Skill 写单元测试尤其是渲染函数。8.5 注意安全与权限边界当/show-me被用于读取配置、数据库 Schema 或上下文状态时要注意只读取当前用户有权限访问的数据。不把敏感字段密码、Token写入可视化输出。对工具调用设置超时和失败兜底。涉及生产环境数据时优先使用脱敏样本。8.6 先做能跑通的最小闭环如果要在团队里推广 Agent Skill不建议一开始就做通用平台。可以先围绕一个高频场景比如“调试工具调用流程”做一个最小闭环——一个命令、一个输出模板、一条数据链路。跑通后再扩展其他可视化对象。这样做的好处是可以快速验证输出格式是否被团队接受。可以积累真实数据优化渲染模板。可以避免过早过度设计。我自己在调试 Agent 时已经习惯先用类似/show-me的指令把上下文结构和工具链路“照”出来再决定下一步是补 Prompt 还是调工具参数。这个动作看起来简单但确实能省下不少来回翻日志的时间。如果你也对 Agent Skill 感兴趣下一步可以继续研究三件事一是把收集到的结构化数据做成可持久化缓存减少重复计算二是增加 Mermaid 输出并接入文档生成流程三是给 Skill 加上简单的测试用例保证模板改动不会破坏输出格式。动手跑一遍你会对 Agent Skill 的边界和潜力有更具体的感知。