AI 代理技能模块实战:用自然语言生成可交互架构图 昨天在 GitHub 上刷到一个很有意思的仓库名字叫 archify。项目定位很直白给 AI 代理用的技能模块skill module让你用自然语言描述系统AI 自动生成一张可以点击、缩放、带信息面板的可交互架构图。这个方向听着像“又一个画图工具”实际用下来发现核心其实在另一层它把架构图从一次性的静态交付物变成了一条可以由 AI 代理持续驱动的生成链路。如果你写过系统设计文档、画过微服务拓扑图肯定懂维护架构图的痛PPT 改了又改、draw.io 文件越存越乱、图一旦没人维护就彻底失真。archify 的思路是用“AI 代理 文本化 DSL 前端渲染”把这摊事自动化。这篇文章我会从设计思路、目录结构、实操步骤到坑位排查讲清楚适合正在折腾 AI 代理工作流、或者对“让 AI 输出可视化交付物”感兴趣的开发者参考。1. 先想清楚AI 生成架构图和“可交互”到底是怎么结合的1.1 静态架构图的维护困局传统架构图的问题说实话不是“画不出来”而是“画完就过时”。很多团队的做法是新系统上线前架构师对着 PPT 或者 draw.io 拖两个小时出图发到文档库里然后这张图就进入“历史文物”状态。等半年后再有人问“订单服务到底连了几个数据库”打开那张图一看和线上完全对不上最后还是得看代码。我在几个项目里都吃过这个亏。有一次做系统迁移需要先盘清现有服务依赖团队里每个人对架构的理解都不一样A 说订单服务直接调支付B 说中间还有个消息队列C 说其实支付回调走的是独立网关。最后只能开会对齐、手工画图一整天就这么没了。这种场景下真正需要的不是“更好用的画图软件”而是一条能随时根据最新描述重新生成图的流水线。这也是 archify 这类项目抓住的点把“架构描述”和“图形呈现”解耦。你不需要关心节点怎么摆放、连线怎么画只需要把系统的组成和依赖关系说清楚剩下的交给脚本和模板。架构图变成了一种“随叫随到的产物”而不是某个文件里的存量资产。1.2 为什么是“技能模块”而不是一个画图工具看到这里你可能会想那直接用 AI 生成 Mermaid 不就行了确实可以但那是零散的玩法。真正让这件事可落地的是“技能模块”这个工程化外壳。技能模块在 AI 代理生态里可以理解成“给代理封装好的一套工作流”。代理本身是对话入口技能模块则是它在某个具体任务里会调用的工具箱和 SOP。archify 没有做成一个让你手动上传文件再点击“生成”的网站而是做成一个代理随时可以调用的模块代理读一遍 SKILL.md 就知道自己能干什么、调用哪个脚本、传什么参数、输出到哪里。这个设计非常适合和自然语言协作。你直接说“帮我画一下这个系统的架构订单服务依赖用户服务消息走 Kafka”代理不会去随机发挥而是先按技能模块的约定把描述转成结构化数据再调用脚本渲染成 HTML 交互图。如果说 AI 是“实习生”技能模块就是“实习生手里的标准作业手册”——没有手册的实习生能力再强也容易跑偏有了手册稳定性和可复现性一下就上来了。所以 archify 的价值不只是“AI 画图”而是“让 AI 代理学会一套稳定的出图流程”。这一点决定了后续所有配置和排坑都要围绕“流程可复用”来展开。2. 拿到仓库后先看结构archify 的骨架设计2.1 核心目录其实只有三块把仓库克隆下来之后第一件事不是跑脚本而是先看目录。我数了一下archify 的文件结构很克制主要有三个部分archify/ ├── SKILL.md # 给 AI 代理看的工作流说明 ├── scripts/ │ ├── extract_system.py # 从描述中抽取节点、边、元数据 │ ├── render_arch.py # 将结构化数据渲染成可交互 HTML │ └── validate_diagram.sh # Mermaid DSL 语法校验 ├── templates/ │ ├── diagram_template.html # 前端渲染模板 │ └── assets/ │ ├── styles.css │ └── interact.js # 点击高亮、详情面板、缩放控制 ├── config/ │ └── agents.yaml # 代理接入配置 └── examples/ ├── demo-system.json └── demo-output.htmlSKILL.md 是给代理看的“说明书”不是给人看的 README。它里边定义的是触发条件、参数规范、调用顺序、输出约定。代理读到这个文件就会知道“用户提到架构图、拓扑、依赖关系这些词时我应该调用 archify 流程。”这也是技能模块模式的通用框架先让代理知道什么场景该出手再让它知道怎么出手。scripts 目录是真正干活的。extract_system.py负责把自然语言转成结构化描述render_arch.py负责把结构化描述渲染成 HTML。这个拆分很关键抽取和渲染是两件完全不同的事前者依赖大模型的语义理解后者是确定性逻辑。一旦把“不确定性”和“确定性”拆开后面出问题就很好定位——报错在抽取阶段那是模型理解问题报错在渲染阶段那是模板或语法问题。templates/assets/interact.js是交互能力的核心后面单独展开。config/agents.yaml则是挂载到 Claude、OpenClaw 这类代理框架时用的配置声明。2.2 交互能力藏在两层里Mermaid DSL 和渲染前端很多人以为“可交互架构图”很玄其实拆开看就两层底层是 Mermaid DSL顶层是前端渲染层。Mermaid 本身支持click语法可以在节点上绑定点击跳转或回调函数。archify 的核心思路就是让 AI 生成的 Mermaid DSL 尽可能标准然后由前端模板统一接管交互逻辑。一段由 archify 生成的 Mermaid DSL 长这样截取它输出的一部分flowchart LR subgraph FRONT[前端层] A[React 前端] end subgraph BACK[服务层] B[auth-service] C[order-service] D[payment-service] end A -- HTTPS -- B A -- HTTPS -- C C -- 消息 -- G[Kafka] click B https://wiki.xxx/auth-service 认证服务详情 class B BACK_SERVICE;注意看click这一行它给节点 B 绑定了跳转链接和悬浮提示。Mermaid 渲染引擎读到这行之后生成的 HTML 里就会给对应的节点元素挂上事件。这就完成了“静态图”到“可交互图”的第一步。但很多场景下光有跳转还不够。你希望点击一个服务节点右侧面板能显示它的端口、负责人、依赖列表、最近变更记录。这部分 archify 不是靠 Mermaid 语法硬撑而是在渲染时额外生成一个data.json把每个节点的元数据单独存下来然后模板里的interact.js在渲染完成后再动态绑定事件mermaid.run({ query: .arch-diagram }).then(() { for (const node of metaData.nodes) { const el document.getElementById(escapeId(node.id)); el?.addEventListener(click, () showDetailPanel(node)); } });第一层 Mermaid DSL 保证“图能画出来”第二层前端脚本保证“图能交互起来”。这两层合在一起正是 archify 这类技能模块和“直接用 AI 生成 Mermaid 代码”之间的本质区别AI 负责内容前端模板负责体验分工清楚可维护性也就上来了。2.3 为什么不是 draw.io也不是纯静态图片用 archify 一段时间后我越发觉得它不是在替代 draw.io而是在替代“画图这个动作本身”。draw.io 适合人肉精修、临时涂改静态图片适合放到文档里展示最终结果。但这两者都有个问题它们和 AI 代理的协作成本太高。一个 AI 代理不可能打开 draw.io 帮你拖拽连线也不可能替你改一张已经导出的 PNG。但代理可以非常舒服地“写文本”写 Mermaid DSL、写 JSON、写 HTML 模板。archify 选择了 Mermaid 和前端渲染这套链路本质上是为了让 AI 的强项文本生成能顺畅地驱动最终产物。我后来在团队里推广时的感受是以前让同事更新架构图他要打开软件、找文件、改布局现在只要把自己的系统变更描述清楚发给代理一份新的交互图就出来了所有人看到的信息还是一样的。下面这张表可以直观感受一下差异方式更新成本可交互性与 AI 代理协作适合场景draw.io / PPT 手绘高每次改动重排布局弱基本是静态图几乎为 0一次性方案评审纯 Mermaid 文件中改文本但无交互弱较好但容易失控代码仓内的快速示意图archify 生成 HTML低描述变更即可强点击/缩放/详情面板强标准化流程持续维护的系统拓扑图3. 实操把 archify 挂到 AI 代理上3.1 环境准备和安装实操是从安装开始的。先说前置条件核心脚本依赖 Python 3.10 和 Node.js 16前端渲染没有额外框架依赖纯 HTML 原生 JavaScript。按常见实践我会把仓库克隆到本地然后把整个目录软链到当前使用的 AI 代理的 skills 目录里git clone https://github.com/archify-project/archify.git ln -s $(pwd)/archify ~/.openclaw/skills/archify如果你用的是 Claude Code、OpenClaw 或者其他支持自定义 skill 的代理框架思路都一样让代理能在对话过程中根据 SKILL.md 的指引发现并调用这个技能。官方仓库的 README 里一般会写明它优先适配的框架我第一次挂载 OpenClaw 时只花了五分钟。要注意一点软链整目录比复制文件更省心因为后续拉取更新时代理读到的永远是同一份最新代码。装完之后先跑一遍自检脚本确认环境没问题bash scripts/validate_diagram.sh examples/demo-system.json如果输出类似DSL syntax OK说明基础链路通了。3.2 第一张图用一句话触发完整链路环境就绪后直接在代理对话框里触发 archify。我建议用一句完整的描述开场用 archify 技能为这个微服务系统生成一张可交互架构图前端是 React后端有 auth-service、order-service、payment-service消息总线用 Kafka数据库用 PostgreSQL缓存用 Redis。点击服务节点时显示它的端口和依赖信息。正常情况下代理会先调用extract_system.py把你的描述解析成节点和边再调用render_arch.py渲染出 HTML。终端里能看到类似这样的调用痕迹python scripts/extract_system.py --input 微服务系统... --output /tmp/archify-node/output.json python scripts/render_arch.py --data output.json --out output/arch-diagram.html最终产出的arch-diagram.html是一个独立的 HTML 文件CSS 和 JS 都已经内联进去了直接浏览器打开就能用。我实测下来的效果页面顶部是缩放控制中间是渲染好的拓扑图右侧有一个可折叠的详情面板。点任何服务节点节点会高亮它相关的依赖边也会一起高亮同时右侧面板显示端口、负责人、依赖列表这些元数据。这里有个细节值得说即使代理第一次给出的描述不够完整比如漏了 Redis你也可以在对话里追一句“补上 Redisweb 层的接口走 HTTPS 到 order-service”代理会基于已有的 output.json 做增量修改重新跑渲染流程而不是从头再来。这个体验非常接近“和一个懂架构的同事对话”而不是操作一个画图工具。3.3 进阶玩法结构化输入和自定义交互面板如果只是让代理从对话里抽取信息能力边界还是比较模糊。archify 更稳的用法是直接提供结构化 JSON让脚本做确定性渲染。比如你在做系统规划时已经有了服务清单{ title: 订单中台, nodes: [ {id: web, label: Web 前端, group: front, port: 3000, owner: 前端组, description: React 18 Vite}, {id: order, label: order-service, group: backend, port: 8081, owner: 交易组, description: 订单核心逻辑}, {id: pay, label: payment-service, group: backend, port: 8082, owner: 交易组, description: 支付对接}, {id: db, label: PostgreSQL, group: storage, description: 订单库15 个表} ], edges: [ {from: web, to: order, label: HTTPS}, {from: order, to: pay, label: gRPC}, {from: order, to: db, label: SQL} ] }把这个文件喂给代理让它调用 render 脚本出来的图会严格按照你定义的结构渲染不会出现 AI 自由发挥导致的字段漂移。这也是我强烈建议的用法对话抽取出图适合快速原型正式维护阶段还是要把数据源管起来。config/agents.yaml 里还可以调整默认行为。比如默认布局方向写default_layout: LR从左往右或者TD从上往下strict_validation: true表示渲染前强制跑语法校验一旦 Mermaid DSL 有问题就返回错误报告而不是硬生成 HTML。我建议在生产环境把 strict 开起来宁肯告诉代理“你生成的 DSL 有问题”也不要让它默默产出一张渲染失败的半成品。4. 常见问题与排查实录实际踩过的六个坑4.1 节点能渲染但是点不动这是最容易遇到的问题图渲染出来了但点击节点没有反应。原因大多是事件绑定时机不对。Mermaid 的渲染是异步的如果你在页面加载完成时就去绑事件此时 DOM 里还没有对应的节点元素绑定自然落空。排查路径很固定先看 browsers 控制台有没有报错再看mermaid.run()的 Promise 是否真的 resolve 了。我自己遇到的另一个坑是 ID 转义Mermaid 渲染生成的元素 ID 会把特殊字符转成下划线比如节点 id 里带括号或空格getElementById就找不到。后来在模板里统一用escapeId映射表做一次转换问题一次性解决。4.2 代理生成的 Mermaid 语法总是报错让 AI 直接生成 Mermaid DSL最大的不稳定因素就是语法。它可能编造不存在的flowchart修饰符或者把subgraph嵌套写错。archify 的做法是在渲染前强校验render_arch.py会调用validate_diagram.sh通过 Mermaid CLI 把 DSL 先转成 SVG失败就直接返回错误信息给代理重试。手动调试时可以这样校验npx -y mermaid-js/mermaid-cli -i test.mmd -o check.svg如果 check.svg 成功生成说明语法至少过了引擎这一关。我在实际使用中给 SKILL.md 加了几条约束来降低出错率节点 id 只用大小写字母和数字、不要生成 emoji、禁止嵌套超过两层 subgraph。加了这些限制之后报错率肉眼可见地下降。4.3 大架构图一打开就糊成一团系统一大节点一多图就会变成“毛线球”。这不是 archify 的问题是图可视化本身的规律。我个人的经验值是单张图控制 30 到 50 个节点以内超过这个量就按域拆分前端一张、核心服务一张、数据层一张。如果确实需要展示全貌可以依靠子图和分组。archify 渲染出的 HTML 支持缩放和平移但缩得太小一样看不清。更实用的做法是主图只放关键节点和链路细节交给点击后的详情面板。换句话说架构图应该“按需展开”而不是把所有信息堆在同一个画布上。4.4 多轮会话产出的文件彼此覆盖这个坑我踩得比较深。早期没有指定输出目录连续让代理生成四五张图之后所有结果都写到同一个默认路径文件互相覆盖最后只留下最后一张。后来我把 output 约定为“会话 ID 时间戳”的目录结构比如outputs/ ├── session_8f31/ │ └── arch-diagram.html └── session_c204/ └── arch-diagram.html在 config/agents.yaml 里把 output_dir 设置成动态路径并在每次生成结束后把完整路径返回给用户这样就不会出现“图生成成功了但不知道去哪找”的尴尬。4.5 点击跳转被浏览器拦截Mermaid 的click语法支持链接跳转但很多浏览器会把非用户主动触发的弹出窗口拦截。如果架构图里每个节点点了都期望在新标签页打开文档用户可能在点击时发现没反应。这个问题的处理方案有两步一是在 HTML 模板里把链接的target属性改成_blank同时加上relnoopener noreferrer二是在右键或中间键点击时手动打开新窗口避免浏览器的弹窗拦截策略。如果架构图是部署在内网 wiki 的场景我更建议用详情面板展示文档摘要而不是直接跳转交互体验更顺滑。4.6 本地打开 HTML 一切正常部署到服务器后样式丢失最后再提一个和部署相关的坑。archify 生成的是单文件 HTML本地打开没问题但如果你的 docs 平台会重写资源链接或者文件被放到 CDN 后 MIME 类型不对样式和 JS 可能加载失败。排查时要先看浏览器网络面板确认styles.css和interact.js是否真的加载了。为了避免这个问题我一般会在 render 脚本里把 CSS 和 JS 内联编译进 HTML尽量做到单个文件自包含这样在任意静态托管平台都能正常展示。5. 我把 archify 用进日常后的工作流折腾完这一圈archify 在我这里已经不只是个新鲜玩具了它直接改变了我处理架构信息的方式。以前每次系统有变更要么改文档文字要么补一张新图图永远滞后于现实。现在我维护一个简单的system.json里面是服务清单和依赖关系谁上线新接口、谁改了数据库连接方式就顺手更新这个 JSON。每次需要最新架构图就让代理重新跑一次渲染一分钟内拿到最新的可交互 HTML。代码评审的时候打开这张图点一下某个服务就能看到依赖和元数据比对着文档猜高效得多。如果你也想试我的建议是从小处开始先找一个你熟悉的系统把它的服务和依赖整理成 JSON用 archify 渲染出第一张图。跑通之后再加“点击查看详情”的元数据字段最后再把生成流程接进你的 AI 代理工作流。这个项目最值得借鉴的地方其实不是某个神秘的算法而是“把 AI 的文本能力和前端交互能力用一条标准流程串起来”的工程思路——顺着这个思路你不光能画架构图还能让 AI 代理批量生成各种可视化交付物。