AI Agent画图Skill:用Mermaid自动替代Visio和draw.io

AI Agent画图Skill:用Mermaid自动替代Visio和draw.io 我用Visio画图差不多画了十年从最早Office 2003里那个新版界面到后来被微软从Office全家桶里拆出来单独卖再到现在每次重装系统都得折腾一遍安装和激活说实话真是画够了。期间也换过draw.io免费确实免费但真到画架构图、时序图这种稍微复杂点的东西拖拽对齐能把人磨到没脾气。所以今年我给自己定了个小目标把所有画图的事全部交给AI Agent去干。前后折腾了两周做出了一个“画图Skill”。这个Skill不是某个画图软件而是给Claude Code这类Agent加持的一项技能。装好之后你只需要说“帮我画一个用户登录的流程图”它会自动把流程拆清楚、写Mermaid代码、渲染出图片全程不用开Visio、不用拖拽draw.io。这篇文章我会把这个Skill的完整设计思路、代码实现、安装方法和踩坑记录全部摊开来讲适合正在折腾Agent能力、想提高画图效率的朋友直接照抄。1. 为什么非得折腾一个画图Skill1.1 先聊聊我受够Visio和draw.io的那些时刻先说Visio。这个东西其实功能没得挑画流程图、网络拓扑、平面布局都能干但它的毛病实在太典型了。安装包本身很大就不说了激活机制对普通单机用户极其不友好。我自己的visio professional 2013当年激活就折腾了好久换了新电脑以后密钥能不能用还得看绑定情况后来win10升级又遇到过打开软件直接卡死的问题。网上搜“visio卡死”你能看到一多半是微软自己的兼容性bug不是咱机器的问题。再说draw.io。它确实让我过渡了三年开源、免费、支持各种格式导出连VS Code都有插件云盘私有化部署也可以。但draw.io的核心操作还是“人肉拖拽”所有形状、连线、对齐、分组都要手动做。画一张二十个节点的架构图少说也得半小时。更致命的是当Agent时代来了以后流程本身的描述才是真正的价值点画图的体力活完全应该被自动化掉而我发现手动工具在这个方向上没有任何进展。1.2 AI Agent时代画图方式真的变了2024年到2025年这一年多Agent的开发范式变动非常大。现在的主流做法已经不是写一堆硬编码的流程而是给大模型Agent配上各种各样的“Skill”。你可能在热搜词里已经反复看到“skill开发”、“agent skill”、“skill和agent的区别”这些词了。简单说Skill就是一组指令和脚本的封装让Agent在主对话之外具备一项特定领域的专业技能。比如你有codex skill那Agent在写代码时就会调用它来辅助你有数学建模skill那在搭数模问题时Agent会使用更专业的工具链。而画图这件事天然特别适合做成Skill因为大模型非常擅长把自然语言需求整理成结构化文本而Mermaid这种基于文本的图表标记语言正好就是结构化的极致。Agent不需要“理解”像素坐标它只需要把一个流程正确地组织成Mermaid语法即可剩下的排版交给渲染引擎。我做的这个画图Skill本质上是把“需求理解”和“图表渲染”两件事缝合了起来。Agent负责从自然语言中提取实体、关系、时序、层级这些信息然后生成Mermaid代码Skill里带的脚本负责把Mermaid代码变成人类能看的HTML、SVG或PNG。整个过程不再需要任何手动拖拽这才是面向Agent时代应有的画图方式。1.3 这个Skill到底能画什么图我把需求收敛到了日常最高频的五类图流程图、时序图、架构图或系统组件图、甘特图、以及统计图。流程图画业务流转、审批路径、算法逻辑时序图画接口调用、消息交互架构图画系统模块和依赖关系甘特图做项目排期统计图用matplotlib画柱状图、折线图和饼图。这五类覆盖了我个人工作里九成以上的画图需求。至于Visio那种超专业的平面布局图、网络拓扑图Skill也支持画Mermaid版的拓扑示意但真正带比例和尺寸的工程图纸我还是会老实回CAD或专业工具。不是说Skill万能而是把最高频、最耗时的那部分替代掉已经非常值了。2. 画图Skill的整体设计与技术选型2.1 图表描述语言Mermaid还是Graphviz还是PlantUML第一步要定的是让Agent输出什么格式。我对比了三个主流方案这里直接说结论Mermaid是最合适的没有之一。先看PlantUML。它在UML领域的表达力非常强类图、用例图、序列图都做得很好规则也比Mermaid严格。但问题是PlantUML的语法相对复杂AI生成时容易在边角语法上出错而且渲染需要安装Java环境对一个Agent Skill来说太重了。再看Graphviz。Graphviz的DOT语言极其强大但它的强项是算图和布局而不是让人对着源码能直接读懂结构。DOT的语法习惯比较程序员类似a - b - c;这种描述可读性不如Mermaid的A--B直观对Agent来说也比较容易在小细节上翻车。Mermaid的优势是显而易见的语法非常轻一个块级结构搭起来几行就能搞定渲染生态完善CLI、CDN、在线API都有而且它本身的设计目标就是“让图表可以被写进文档里”。主流技术博客、GitHub仓库里大量使用Mermaid这意味着大模型训练语料里Mermaid的占比远高于PlantUML和DOTAI生成它的质量天然更稳定。这就是一个很朴素的逻辑我选择的不是功能最全的语言而是Agent最容易一次写对的。2.2 渲染引擎CLI、在线API还是本地HTML模板Mermaid代码本身只是文本要把文本变成图片需要渲染引擎。我研究了三条路。第一条路是Mermaid CLI。官方提供了mermaid-js/mermaid-cli装在Node环境里之后用mmdc命令就能把.mmd文件渲染成PNG/SVG。但问题来了它底层依赖Puppeteer也就是要额外下载一个Chromium内核装完轻轻松松几百兆。Agent Skill的部署场景通常不止一台机器尤其在云环境或无头Linux上光下载Chromium就能劝退一半人。第二条路是mermaid.ink在线API。把Mermaid代码做一次base64编码然后拼URL浏览器就能直接渲染出图片。这个方案确实最省事几行代码就搞定。但它的致命缺陷是依赖公网服务只要网络受限、服务超时、或者有数据隐私要求马上就抓瞎。企业内部项目根本不敢把内容经过这种在线服务。第三条路是本地HTML模板渲染。做法很简单脚本把Mermaid代码嵌入到一个固定HTML模板里模板通过CDN引入Mermaid的JS库然后用浏览器打开HTML文件即可看到渲染结果。也可以再用无头工具转出PNG。这条路没有任何本地重型依赖一个Python脚本就能干完完全离线可选生成的是可交互的HTML文件还能手动微调所以我最终选了它。2.3 Skill目录结构和脚本分工按照Anthropic的Agent Skills规范一个Skill就是一个文件夹文件夹里必须有SKILL.md其余脚本和资源按需放置。我最终的结构设计如下draw-skill/ ├── SKILL.md ├── scripts/ │ ├── render_mermaid.py │ └── render_chart.py └── templates/ ├── mermaid_template.html └── chart_template.pySKILL.md是整个Skill的口令和说明告诉Agent这个技能在什么场景下使用、怎么调用脚本、输出放哪里。render_mermaid.py负责接收Agent传来的Mermaid源码校验、拼接HTML模板并落盘render_chart.py负责处理数据统计图接收JSON格式的数据借助matplotlib画出图表。templates目录里放的是两套固定的渲染模板真正把代码和模板分离脚本不去拼字符串拼到天荒地老。这个设计的好处是职责分离画流程类图表走一套渲染链路画数据统计图走另一套。原因是Mermaid对统计图的表达能力很弱而matplotlib本身的画质和可控性都更好没必要硬让Mermaid越俎代庖。3. 核心代码实现与关键细节3.1 SKILL.md让Agent“看懂”怎么用SKILL.md是整个Skill的灵魂。如果这一份文件的描述写得不够好Agent根本不会主动调用你辛苦写的脚本。这里直接给一份可以照抄的精简版本--- name: smart_diagram description: 根据用户需求绘制流程图、时序图、架构图、甘特图和统计图。当用户要求画图、生成流程图、画架构图、画时序图、画甘特图、把数据画成图表时必须优先使用本技能输出可打开查看的可视化文件。 --- # Smart Diagram Skill 你是一个专业的图表生成助手。收到用户需求后: 1. 先确认图表类型: 流程图(flowchart)、时序图(sequenceDiagram)、架构图(flowchart子图)、甘特图(gantt)、统计图(bar/line/pie)。 2. 流程图/时序图/架构图/甘特图: 先生成完整的Mermaid语法, 不要省略任何节点, 然后运行: python3 scripts/render_mermaid.py 这里传Mermaid源码 脚本会生成HTML文件, 打开即可看到渲染结果。 3. 统计图: 把数据整理成JSON格式, 运行: python3 scripts/render_chart.py {type:bar,title:销售统计,x:[1月,2月,3月],y:[12,15,9]} 4. 生成完成后, 把文件路径清晰告诉用户。 注意事项: - Mermaid节点文字不要使用特殊字符如冒号、括号, 必要时改用中文描述。 - 流程图中表示判断用 {文本} 格式。 - 时序图参与者命名用英文或拼音, 显示文本用 as 别名。 - 甘特图必须给每个任务指定 dateFormat 和 axisFormat。写SKILL.md时我踩过的最大的坑是description写得太泛。一开始我写的是“帮助用户画图工具”结果Agent在用户提唱歌、写代码时也会试着调这个Skill非常浪费上下文。后来我把触发词精确到“流程图、时序图、架构图、甘特图、统计图”这五类具体名词触发准确率一下子提升到了九成以上。3.2 render_mermaid.pyMermaid代码的接收与渲染接着是核心脚本render_mermaid.py。脚本做的事情不复杂但有几个细节非常关键。我直接贴核心代码#!/usr/bin/env python3 # -*- coding: utf-8 -*- import sys import re import html from pathlib import Path BASE_DIR Path(__file__).resolve().parent.parent TEMPLATE_PATH BASE_DIR / templates / mermaid_template.html OUTPUT_DIR BASE_DIR / output def sanitize_mermaid(code: str) - str: # 去掉可能的 Markdown 代码块围栏 code re.sub(r^[a-zA-Z]*\s*, , code.strip()) code re.sub(r\s*$, , code.strip()) return code def build_html(mermaid_code: str) - str: template TEMPLATE_PATH.read_text(encodingutf-8) # 这里不能用 str.replace 直接替换, 因为Mermaid代码里可能包含 $ 或特殊转义序列 # 所以用占位符 split 再 join, 避免各种转义灾难 parts template.split(/*MERMAID_CODE*/) return parts[0] mermaid_code parts[1] def main(): if len(sys.argv) 2: # 支持从stdin读, Agent传超长代码时更稳 mermaid_code sys.stdin.read() else: mermaid_code sys.argv[1] mermaid_code sanitize_mermaid(mermaid_code) # 简单校验: 不允许空内容, 不允许传入HTML注入 if not mermaid_code.strip(): print(ERROR: Mermaid代码为空) sys.exit(1) mermaid_code html.escape(mermaid_code, quoteFalse) html_content build_html(mermaid_code) OUTPUT_DIR.mkdir(exist_okTrue) out_path OUTPUT_DIR / diagram_output.html out_path.write_text(html_content, encodingutf-8) print(f渲染文件已生成: {out_path.resolve()}) if __name__ __main__: main()这段代码里有三个关键设计。第一用html.escape转义Mermaid内容防止用户需求里夹带HTML标签最终在浏览器里被当成脚本执行这是安全底线。第二脚本同时支持命令行传参和stdin读取因为Agent在长上下文中生成Mermaid代码时代码往往非常长超过命令行参数的长度限制用stdin更稳定。第三把Mermaid代码只当作填充物注入模板指定的注释位避免用一次性replace导致的转义问题。HTML模板文件mermaid_template.html长这样!DOCTYPE html html langzh-CN head meta charsetUTF-8 titleDiagram Output/title script srchttps://cdn.jsdelivr.net/npm/mermaid10/dist/mermaid.min.js/script style body { background: #fff; font-family: -apple-system, Microsoft YaHei, sans-serif; padding: 32px; } .mermaid { display: flex; justify-content: center; margin-top: 24px; } /style /head body h2图表预览/h2 div classmermaid /*MERMAID_CODE*/ /div script mermaid.initialize({ startOnLoad: true, theme: default }); /script /body /html这里我特意把CDN的Mermaid版本锁定为v10。因为Mermaid的版本迭代很快个别API和语法在新旧版本之间有变化。如果模板写mermaidlatest可能今天能渲染过两个月语法就变了图全挂掉。锁版本号以后环境稳定排查问题也方便。3.3 render_chart.py顺手解决统计图的三个坑统计图我单独用matplotlib实现因为这部分的诉求和流程图完全不同。用户说“把数据画成柱状图”如果还走Mermaid那套不仅效果难看而且基本没法做坐标轴、标签这些精细控制。所以我把统计图拆出来用Python画。代码核心逻辑不复杂但我在实际开发中连续踩了三个坑中文字体、横坐标密度、以及负号显示。这三个坑几乎每个Python画图的人都遇到过包括热搜词里的“plt画图显示中文问题”、“python画图横坐标太密集”就明晃晃挂着。#!/usr/bin/env python3 # -*- coding: utf-8 -*- import json import sys import matplotlib matplotlib.use(Agg) import matplotlib.pyplot as plt # 解决中文显示问题 plt.rcParams[font.sans-serif] [Microsoft YaHei, SimHei, WenQuanYi Zen Hei] # 解决负号显示为方块的问题 plt.rcParams[axes.unicode_minus] False def plot_chart(data: dict): chart_type data.get(type, bar) title data.get(title, 统计图) x data.get(x, []) y data.get(y, []) fig, ax plt.subplots(figsize(10, 6)) if chart_type bar: ax.bar(x, y, color#4C72B0) elif chart_type line: ax.plot(x, y, markero, color#C44E52) elif chart_type pie: ax.pie(y, labelsx, autopct%1.1f%%) else: ax.bar(x, y, color#4C72B0) # 横坐标太密集时, 自动抽稀 if len(x) 12: step len(x) // 12 new_ticks list(range(0, len(x), step)) ax.set_xticks(new_ticks) ax.set_xticklabels([x[i] for i in new_ticks], rotation45, haright) ax.set_title(title) fig.tight_layout() out_path output/chart_output.png fig.savefig(out_path, dpi150) print(f图表已生成: {out_path}) if __name__ __main__: data json.loads(sys.argv[1]) plot_chart(data)中文显示问题为什么存在因为matplotlib默认字体是DejaVu Sans根本不包含中文字形所以中文输出全是方块。解决方式也很粗暴指定系统里的中文字体。Windows上微软雅黑和黑体基本都有Linux的服务器上要确认有没有WenQuanYi没有就得apt装。横坐标太密集的问题我用了自适应抽稀逻辑如果横坐标超过12个就每隔N个取一个标签再加45度旋转这样即使50个数据点也能看清。4. 实操实录从安装到完成第一张图4.1 把Skill装进Claude Code这套Skill我主要在Claude Code里用安装方式不难三步就能跑通。第一步把draw-skill文件夹放到Claude Code的Skill目录。不同环境位置不一样如果是Claude Code的默认配置一般是~/.claude/skills/下面。放好之后目录结构就是这样~/.claude/skills/ └── draw-skill/ ├── SKILL.md ├── scripts/ │ ├── render_mermaid.py │ └── render_chart.py └── templates/ ├── mermaid_template.html └── chart_template.py第二步手动验证脚本本身能跑。先直接命令行跑一下例如cd ~/.claude/skills/draw-skill python3 scripts/render_mermaid.py flowchart TD; A[开始] -- B{判断}; B --|是| C[结束];这条命令会生成output/diagram_output.html用浏览器打开如果能正常看到流程图说明脚本链路是通的。第三步确认依赖齐全。脚本依赖Python3不需要第三方库HTML模板走浏览器渲染所以只要机器上能打开浏览器就行。如果部署在纯服务器上也可以把HTML拷到本地再打开。安装完之后在Claude Code里重新加载会话让Agent感知到新Skill。验证方式很简单我直接问一句“你会画流程图吗”如果Agent正确识别并提到了smart_diagram说明Skill已经注册成功。4.2 四个典型场景实测记录我实际测了几天最有代表性的四个场景是这样的。第一个是流程图。我让它画“用户登录的流程图”Agent内部的处理链路是先拆出用户输入账号密码、系统校验、生成token、进入主页面这些节点然后自动生成Mermaid代码。它的输出里Mermaid片段大致长这样这里用文字展示不经过mermaid渲染flowchart TD A[用户输入账号密码] -- B[提交登录请求] B -- C{校验账号密码} C --|通过| D[生成token] C --|不通过| E[提示错误] D -- F[跳转到主页面] E -- B整个生成加渲染流程大概十五秒比我手动拖Visio快了十倍不止而且结构非常清晰。第二个是时序图让它画“订单支付接口的调用时序”Agent把前端、后端、支付网关三个参与者的交互按时间顺序排列Mermaid的sequenceDiagram语法生成得相当标准渲染出来很漂亮。第三个是架构图。这个我一开始比较担心因为架构图涉及多个模块的层级关系。实测下来Agent用flowchart加子图的方式组织把网关层、服务层、数据层分别用subgraph包起来层次感非常清楚。关键的经验是prompt里要稍微交代清楚系统包含哪些部分否则Agent会在模块命名上自由发挥不够贴合实际。第四个是甘特图。让Agent根据一个月的项目排期生成甘特图它会主动询问关键里程碑和时间点。给它日期范围后生成的甘特图带日期轴、任务依赖、进度条用于周报和向上汇报已经很够用了。4.3 和Visio、draw.io的直观对比我把同一张“用户登录流程”分别用三种方式画了一遍对比结果是这样的对比项Visiodraw.io画图Skill耗时约15分钟含排样式约10分钟约15秒安装成本需要安装激活还会卡死免费但需下载桌面端无安装脚本即用修改成本手动拖线手动拖线重新描述即可可版本管理二进制文件XML但流程繁琐纯文本Mermaid可进Git可读性好好取决于路径分类和命名一次生成准确率不涉及不涉及需要2-3轮微调较稳耗时这个差异是最颠覆的。过去画图最大的成本是“把脑子里的结构落到画布上”而Skill把这个过程压缩到了“把结构说清楚”。说实在的现在让我再回到Visio去手动拖那些连线我已经觉得非常不适应了。5. 踩坑记录与高频问题排查5.1 SKILL.md描述不当导致Skill不触发一开始我把description写成“帮助用户绘图”结果它被触发得极其频繁连用户问个“画一条曲线轨迹”都去调用而且因为描述太宽泛Agent会在不该用的时候耗费大量上下文。后来改成特别具体的五类图名称加“必须优先使用”的指令触发逻辑才精准起来。这个经验我觉得对任何Skill开发都适用描述里列清楚触发场景和禁止场景Agent才懂得边界。5.2 Mermaid语法错误但Agent自己没发现这是我最头疼的问题。很多时候Agent生成Mermaid代码后直接退出没有先自我检查。比如在flowchart里节点标签里带了冒号A[操作: 提交]Mermaid新语法会报错或显示不正确。我后来在SKILL.md里强制加了一条节点文案不要出现冒号、括号、引号表达不清就换中文词汇。同时脚本里还做了基础校验生成前先把Mermaid代码里明显的Markdown围栏剥离掉省得Agent把代码块一起塞进来。虽然不能做到100%的语法校验但简单错误能被拦截八成。5.3 中文乱码和特殊字符转义问题中文乱码的坑在统计图脚本里更明显因为matplotlib默认字体不含中文。解决方式前面代码里已经写了指定Microsoft YaHei或SimHeiLinux上装文泉驿字体。另外有一个细节是make sure负号也能正常显示plt.rcParams[axes.unicode_minus] False这一行不加图上坐标轴的负号会显示成方块非常丑。另外Mermaid这边也有转义坑。节点文字里的引号和括号会导致语法错误解决办法是尽量用简洁中文描述别放特殊符号。我目前的做法是让Agent在生成后主动检查一遍特殊字符养成这个习惯后渲染失败率大幅下降。5.4 布局方向混乱左右和上下的玄学Mermaid默认的flowchart是自上而下也就是TD。但有些场景比如画一个横向的用户流程LR从左到右更合适。如果方向不对图会很矮很宽或者很高很窄看起来非常别扭。解决方式是写死偏好在SKILL.md里强调除非用户特别要求普通流程图默认用flowchart TD涉及时间线、操作步骤这种建议用flowchart LR。实测下来方向对了图的好看程度提升一个档次。5.5 本地打开HTML时Mermaid渲染空白我第一次用浏览器打开生成的HTML页面上一片空白控制台报错说Mermaid没加载出来。排查了一下是CDN的脚本被本地代理或者网络环境拦了。解决办法有两个方向一个是把Mermaid的JS库下载到本地模板里用相对路径引用另一个是改用内网可达的CDN地址。目前我的模板仍保留jsdelivr如果要在完全离线的环境用把链接换成./mermaid.min.js即可。5.6 常见问题排查速查表问题现象可能原因解决办法Skill不触发description太宽泛把触发词精确到五类图名Mermaid报语法错误节点文字含特殊字符清理冒号、引号、括号HTML渲染空白CDN被墙或离线换本地mermaid.min.js中文字体显示方块matplotlib没配字体指定系统中文tff输出图太宽/太高方向没控制按场景指定TD或LRAgent生成的图过于复杂没有边界约束在SKILL.md限定节点数这张表我打印出来贴在了工位上后来调试其他Skill遇到类似问题也能复用一部分排查思路。6. 这版Skill还能怎么扩展6.1 和draw.io做格式互转现在画完的图是HTML里的Mermaid想再拉回draw.io继续编辑需要把Mermaid转成draw.io的XML。其实draw.io支持导入Mermaid文本你只需要在draw.io里“Extras - Edit Diagram”把Mermaid源码粘进去它就能自动转成图形对象。这个方案我试过对普通流程图转换效果还不错复杂子图会有少量布局错位稍微调整一下就行。6.2 一键导出PNG和SVG现在脚本生成的是HTML文件用浏览器打开后手动导出PNG也不是不行但终究多个步骤。更顺滑的方案是写一个无头浏览器调用或者用Mermaid CLI跑一次把HTML转成PNG。考虑到CLI依赖太重我打算后续用Selenium或Playwright写一个轻量导出模块只在用户明确要求输出PNG时临时拉起无头Chrome。这样既能保住轻量安装又能满足发布场景。6.3 数据图表和流程图的联动现在流程图和统计图是完全独立的链路。但实际工作里经常有这种需求一个总流程图里某个节点对应一个数据统计图。比如“订单流程图”里有个“每日订单量趋势”的节点用户希望点开这个节点能看到对应的折线图。这个我后续想在模板里做一层交互Mermaid渲染出来的HTML里可以塞入iframe把统计图嵌进节点弹层里。技术上可行就是需要模板做更多定制属于进阶玩法。6.4 结合多Agent协作画大型架构图还有一个方向是让多个Agent共同产出图。比如一个Agent负责描绘模块A的时序细节另一个Agent负责模块B最后统一合成一张总览架构图。这个方案在Agent开发中叫multi-agent协作稍微有点重但思路是通的把大图拆成多个子图每个子图用独立的Skill渲染最后在总图里用flowchart的子图模块把它们组装起来。当前我的Skill已经天然支持subgraph语法所以后面扩展起来技术成本并不高。最后分享一个小技巧。实际使用中我发现想让Agent画出的图不失控最好的办法是别一上来就让它画整张大图而是先让它用文字列出“节点清单和关系清单”你确认后再让它生成图。这样相当于在人和Agent之间加了一层审视。多花半分钟能省掉后面大量来回改图的时间。这也是我用这套Skill两周下来最值钱的一条经验。