快速复现:整段复制给 Codex
不想看完整过程的话,把下面整个代码块复制到 Codex、Claude Code 或其他能操作本机文件与 GUI 的 Agent。它会在当前目录搭建 Bridge,并带你完成真实 Figma 画布验证。
1 | 请在当前工作目录实现一套安全、可复用的 Figma Agent Canvas Bridge,并完成端到端验证。不要只写教程,要实际创建文件、运行检查,并在 Figma 中生成原生可编辑节点。 |
起因:Agent 能不能直接设计 Figma?
最开始的问题很直接:既然 Figma 提供 API,能不能让 Agent 自动创建页面、写文字、画图标、调整布局,并且留下可继续编辑的图层?
答案是:可以,但不能只靠 REST API。
这个区别非常重要。Figma REST API 很适合读取文件树、节点信息和导出图片,也能管理评论、Variables 与 Dev Resources;但它没有通用的 Frame、Text、Shape 节点增删改接口。真正能够操作当前画布的是运行在 Figma 客户端内部的 Plugin API。
| API | 适合做什么 | 能否普通图层 CRUD |
|---|---|---|
| REST API | 读取文件、跨文件同步、导出、评论、Variables、Dev Resources | 否 |
| Plugin API | 在当前打开的文件中创建和修改原生节点 | 是 |
| Widget API | 持久化、多人可见的画布交互对象 | 不适合作为批量设计生成器 |
所以真正的问题变成了:怎样把外部 Agent 的命令,安全、稳定地送进 Figma Plugin?
第一版尝试:固定生成器并不等于 Agent
最早的原型是一个写死的 Figma 插件。点击运行后,它会创建一组固定的 Frame、Text 和 Shape。
这一步证明了两件事:
- Plugin API 的确可以写入真实画布。
- 生成结果是原生节点,不是贴进 Figma 的截图。
但它仍然不是通用的 Agent 自动化。设计内容被硬编码在插件里,每换一个需求就要改插件代码、重新运行。它更像一个模板生成器,而不是外部智能体可以持续调用的设计执行器。
于是我们把它改造成了一个本地 Bridge。
Bridge 架构
最终采用的是一个很小的 loopback command queue:
1 | Agent |
外部 Agent 只提交结构化 JSON,不向 Figma 注入任意 JavaScript。Bridge 只接受白名单 action,例如:
inspect:读取当前文件、Page 与选择节点apply:创建或更新图层move-root-to-page:移动到独立 Pageaudit-root:统计节点类型、图片层与参考覆盖层export-node:调用 FigmaexportAsync()导出真实渲染
Plugin manifest 只允许访问本机地址:
1 | { |
这套结构刻意保留了一点“人工在环”:Figma 必须打开,用户必须拥有编辑权限,并且要启动本地开发插件。它不是绕过 Figma 权限体系的无头写入服务。
用稳定 key 保证可重复修改
如果每次生成都创建新节点,画布很快就会堆满副本。解决方式是给每个受管理节点保存稳定 key:
1 | node.setPluginData("agentCanvasKey", spec.key) |
命令中的节点也带相同 key:
1 | { |
Plugin 先按 key 查找节点:找不到就创建,找到就更新。这样同一份设计描述可以反复执行,也可以只提交两三个节点做局部修正。
这也是“选中一块再重新设计”可行的基础。Plugin API 能读取当前 selection,Agent 可以先 inspect,识别用户选中的 Frame,再把变更限制在这个父节点下面。
最容易踩的几个坑
1. 命令顺序反了
Plugin 的工作模式是一轮只取一条命令,然后立即关闭。正确顺序是:
1 | 启动 Bridge → 提交命令 → 在 Figma 中运行 Plugin |
如果先运行 Plugin,再提交命令,队列是空的,Plugin 会正常退出。这个现象很像“插件什么都没做”,其实只是握手顺序错了。
2. 一直显示 Loading
Bridge 最初只监听 IPv4 loopback,但 Plugin 请求的是 localhost。在某些环境中,localhost 会优先解析到 IPv6,结果是终端访问正常,Figma 内部却一直拿不到命令。
我们先尝试把 manifest 改为 http://127.0.0.1:3847,但 Figma 对 allowedDomains 的校验并不接受这个写法。最终做法是:
- manifest 继续声明
http://localhost:3847 - Bridge 使用 dual-stack socket,同时接受 IPv4 和 IPv6 loopback
1 | class DualStackServer(ThreadingHTTPServer): |
修复后,localhost 和 127.0.0.1 都能访问同一个队列。
3. “看起来一样”不代表真的完成
一次完整验证至少需要三层证据:
- Plugin 返回创建/更新结果。
audit-root确认节点结构,尤其检查是否存在整页图片层。export-node从 Figma 导出实际渲染图,再做视觉检查。
仅看到成功 toast 不够,代码运行成功也不等于文字没有溢出、图标没有错位。
4. 字体会改变布局
我们用 Georgia 做编辑感较强的衬线标题。Reader 页面第一次导出时,标题自动折成三行,压到了副标题。结构审计完全正常,但视觉结果不合格。
最后没有整页重做,只提交了一个两节点 patch:缩小标题字号、调整断行与副标题位置,然后重新导出。这个过程证明局部、幂等更新比每次重建整页可靠得多。
从“贴图”升级到真正的原生设计
为了验证 Bridge 不是把大截图塞进画布,我们做了一个英文美文阅读 App,视觉方向接近 Medium:暖白背景、衬线大标题、宽松留白,只保留少量绿色强调。
页面包括:
- Today:今日文章和推荐阅读
- Discover:主题筛选与编辑精选
- Reader:正文、阅读进度、划句学习工具和音频控制
- Notebook:生词、音标、释义、来源与复习入口

最终审计结果:
| 类型 | 数量 |
|---|---|
| Frame | 52 |
| Text | 93 |
| Vector | 72 |
| Rectangle | 20 |
| Ellipse | 3 |
| Image layer | 0 |
一共 240 个原生可编辑节点。状态栏、搜索、书签、导航等图标使用 SVG 创建,文字和布局仍然可以在 Figma 中逐层修改。
当前边界
这个 Bridge 已经适合做页面生成、局部改版和视觉验证,但它不是完整复制 Figma 所有能力的协议。目前刻意保持了较小的白名单:
- 单次最多 500 个 operations
- 请求体限制在 2 MB
- 客户端等待时间有限
- SVG 内部路径变化时需要 remove 后重建
- Effects、完整组件变体与 Prototype interaction 还没有纳入协议
这些限制并不完全是缺点。设计自动化最危险的部分,是一个功能过宽的执行器在画布中产生难以审查的副作用。小协议、稳定 key、逐区域执行、每轮导出检查,反而更适合 Agent 工作流。
脱敏与安全处理
本文示例已移除或替换以下信息:
- Figma 文件 URL、file key、node ID 与账户信息
- 本机用户名和绝对目录
- Access Token、Cookie、OAuth 信息
- 私有项目名、内部评论和真实业务数据
展示图仅包含虚构品牌与示例文章内容。Bridge 只监听本机 loopback,并且不执行远程下发的任意代码。
结论
Agent 当然可以“设计 Figma”,但准确说法应该是:
REST API 负责读取、校验和跨系统集成;Plugin API 负责在已打开、可编辑的 Figma 文件中写入原生画布节点。
真正有价值的不是一次性生成一张看起来像 UI 的图,而是建立一条可重复的工程链路:结构化命令、稳定节点身份、局部更新、原生图层审计,以及最终的真实渲染检查。
当这些环节都存在时,Agent 才从“帮你画一张图”变成了可以参与设计迭代的工程协作者。