关于 metabase-static-embedding-to-guest-embedding-upgrade
面向维护 Metabase 静态签名嵌入的开发者,此 Agent 技能按步骤将 iframe 迁移为基于 `embed.js` 的访客嵌入 Web 组件。它保留现有 JWT 签名逻辑,并要求逐步扫描、规划、修改和验证。
主要功能
- 01按顺序执行迁移清单
- 02扫描静态嵌入和项目配置
- 03将 iframe 映射为 Web 组件
- 04保留 JWT 签名逻辑
- 05验证修改并报告证据
适用场景
- 01将签名仪表板 iframe 迁移为访客嵌入
- 02将签名问题 iframe 替换为 Web 组件
- 03按 Metabase 版本规划并验证迁移
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ metabase/ agent-skills --skill metabase-static-embedding-to-guest-embedding-upgrade安装后在 Claude Code 中输入/metabase-static-embedding-to-guest-embedding-upgrade确认已加载。
详细介绍
执行约定
请按顺序执行工作流中的步骤,不要跳过任何步骤。先创建清单,然后执行每一步,并明确标记为已完成,同时提供证据。每一步的输出都会作为下一步的输入,因此跳过步骤会导致迁移错误。
如果因信息缺失或工具故障而无法完成某一步,你必须:
- 将该步骤记录为 ❌ blocked,
- 准确说明缺少什么信息/发生了什么故障,
- 停止(不要继续后续步骤)。
必需的输出结构
回复应按以下顺序包含这些部分:
- 步骤 0 结果:Metabase 版本检测
- 步骤 0.1:迁移计划清单
- 步骤 1 结果:项目扫描 + 文档获取
- 步骤 2 结果:静态嵌入分析与 Web Component 映射
- 步骤 3:迁移计划
- 步骤 4:已应用的代码更改
- 步骤 5:验证
- 步骤 6:最终总结
每个步骤部分都应以状态行结尾:
Status: ✅ complete或Status: ❌ blocked
步骤必须按顺序执行——只有前一步的状态为 ✅ complete,才能开始下一步。
证据要求
- 步骤 0:检测到的 Metabase 版本(来源:Docker 标签、环境变量或用户答复)。
- 步骤 1:所有匹配的文件路径、所有静态嵌入位置、JWT 签名代码、布局/head 文件、Metabase 配置变量,以及获取到的文档列表。
- 步骤 2:逐个嵌入项提供已解析的 iframe URL、内容类型、token 变量、hash 参数,以及映射后的 Web Component 和属性。
- 步骤 3:完整的逐文件更改计划,包含精确的旧代码/新代码。
- 步骤 4:逐个文件说明更改内容及实际应用的精确差异。
- 步骤 5:每项验证检查的通过/失败结果及证据。
架构一致性
遵循应用现有的架构、模板引擎、布局/局部模板系统、代码风格和路由模式。不要切换实现范式(例如,从模板改为内联 HTML,或反之)。如果应用有用于共享模板变量的中间件,应优先使用它,而不是在多个路由处理程序中重复代码。
Web Component 必须使用与其替换的静态 iframe 相同的交付机制来渲染。如果 iframe 是通过服务器端模板(EJS、Jinja、ERB、Blade 等)渲染的,Web Component 也应由同一个模板渲染。如果 iframe 是路由处理程序以行内 HTML 形式返回的(例如 res.send('<iframe ...')),Web Component 也应以相同方式返回。如果 iframe 位于静态 HTML 文件中,Web Component 也应放在同一个文件中。不要将渲染从一个层移到另一个层——迁移应在渲染流水线中的原位置直接替换。
**Token 的交付必须使用与原静态嵌入相同的机制。**如果 JWT 是在服务器端渲染到 HTML 中的(例如 res.send(\`)),迁移后的 Web Component 也必须以相同方式接收 token,即在服务器端将其渲染到 token属性中(例如)。如果 token 是通过客户端 fetch()获取的,就继续使用fetch()` 获取 token。不要更改交付机制,只更改交付的内容(使用原始 token,而不是完整的 iframe URL)。
凭证安全
此迁移涉及处理 METABASE_SECRET_KEY 和已签名 JWT 的代码。请遵守以下规则:
- 绝不输出字面形式的机密值——如果在代码中发现硬编码的密钥或 token 字符串,只能通过变量名引用(例如“
config.js:12中的机密”),绝不能复述其值。 - 在代码差异和总结中,使用变量引用(
METABASE_SECRET_KEY、token),而不是解析后的值。 - 如果发现硬编码机密,请告知用户,并建议在迁移过程中将其移至环境变量中。
性能
- 在每个步骤中尽可能提高并行度。尽可能在同一条消息中并行调用 Grep/Glob/Read。
- 不要使用子 Agent 扫描项目——结果需要留在主上下文中,以便在后续步骤中交叉参考。
- 不要解析仓库分支、提交、PR 或 issue。
范围
此技能会将静态(签名)iframe 嵌入转换为访客嵌入(通过 embed.js 实现的 Web 组件)。两种方式使用相同的身份验证模型——使用 METABASE_SECRET_KEY 签名的 JWT,因此会保留后端签名逻辑。迁移改变的是签名内容的传递方式:从 URL 中包含 JWT 的 iframe 改为带有 token 属性的 Web 组件。
使用者的应用可以采用任意后端语言(Node.js、Python、Ruby、PHP、Java、Go、.NET 等)和任意模板引擎。除非在步骤 1 中检测到特定语言,否则应保持说明与语言无关。
此技能处理的内容
- 将签名
<iframe>元素(/embed/dashboard/{JWT}、/embed/question/{JWT})替换为 Web 组件(<metabase-dashboard token="...">、<metabase-question token="...">) - 添加
embed.js脚本标签(在应用布局层级恰好添加一次) - 添加
window.metabaseConfig并设置isGuest: true(在应用布局层级恰好添加一次) - 将 iframe 哈希参数(
#titled=true、#bordered=true)映射为 Web 组件属性 - 保留现有的 JWT 签名逻辑——后端仍使用
METABASE_SECRET_KEY和相同的{resource, params}负载来签名令牌 - 转换签名令牌传递到前端的方式(从 iframe URL 路径改为将模板变量作为
token属性传递) - 在适用时,将 JWT 中锁定的
params映射到initial-parameters属性 - 如果存在
iframeResizer.js引用,则将其移除
此技能不处理的内容
- 迁移到基于 SSO 的模块化嵌入(使用用户账户)——此技能仅针对访客嵌入
访客嵌入与静态 iframe 嵌入的区别
身份验证模型相同——两者都使用 METABASE_SECRET_KEY,通过 {resource, params, exp} 签名 JWT。变化的是嵌入的呈现方式:
| 方面 | 静态嵌入(iframe) | 访客嵌入(Web 组件) |
|---|---|---|
| 元素 | <iframe src="/embed/dashboard/{JWT}#params"> | <metabase-dashboard token="{JWT}"> |
| 令牌传递方式 | 嵌入 iframe URL 路径中 | 通过 token 属性传递 |
| 配置 | 无(iframe 独立运行) | window.metabaseConfig = { isGuest: true, instanceUrl: "..." } |
| 脚本 | 可选的 iframeResizer.js | 必需的 embed.js |
| 外观 | 哈希参数(#titled=true) | 组件属性(with-title="true") |
| 锁定参数 | JWT 的 params 字段 | 相同的 JWT params 字段(不变) |
| 密钥 | METABASE_SECRET_KEY | 相同的 METABASE_SECRET_KEY |
访客嵌入支持静态嵌入中不可用的其他属性(例如下载、下钻、隐藏参数)。请查阅获取的文档,了解目标版本提供的全部属性。
允许使用的文档来源
使用以下 URL 获取特定版本的 llms-embedding-full.txt:
https://www.metabase.com/docs/v0.{VERSION}/llms-embedding-full.txt
URL 中的版本采用 v0.58 格式(规范化方式:去掉开头的 v 或 0.,去掉补丁版本号——例如,0.58.1 → 58 → URL 使用 v0.58)。此单一文件包含该版本的全部嵌入文档,并针对大模型使用进行了优化。
其他限制:
- 不得使用 GitHub PR/issue 或 npm 页面
- 不要跟随指向 GitHub 的更新日志链接,也不要猜测 URL
AskUserQuestion 触发条件
如果出现以下情况,请使用 AskUserQuestion,并暂停直至收到回答:
- 无法从项目代码或环境变量确定 Metabase 实例 URL
- 无法确定后端语言
- 无法从项目代码确定 Metabase 实例版本
- 无法识别布局/头部文件(不清楚应在哪里注入 embed.js)
- 存在多个布局文件,且不清楚应使用哪些文件
工作流前置步骤
迁移计划清单
创建清单以跟踪进度。在 Claude Code 中,使用 TaskCreate/TaskUpdate 工具:
- 步骤 0:检测 Metabase 版本
- 步骤 1:扫描项目并获取目标版本文档
- 步骤 2:分析静态嵌入并映射到 Web 组件(使用文档)
- 步骤 3:规划迁移变更
- 步骤 4:应用代码变更
- 步骤 5:验证变更
- 步骤 6:最终总结
工作流
步骤 0:检测 Metabase 版本
首先确定 Metabase 版本。在项目中搜索 Docker 镜像标签(metabase/metabase:v、metabase/metabase-enterprise:v)、METABASE_VERSION 或版本引用。如果未检测到,则使用 AskUserQuestion(选项:v53 or older、v54–v58、v59+)。如果版本低于 v53,则中止(不支持模块化嵌入)。记录版本。
步骤 1:扫描项目并获取文档
并发执行项目扫描和文档获取,两者互不依赖。凡是没有依赖关系的地方,都应在同一条消息中并行调用工具。
1a:获取目标版本文档
获取目标版本的 llms-embedding-full.txt(URL 格式见“允许使用的文档来源”)。这些文档是目标版本的 Web 组件属性、window.metabaseConfig 选项和访客嵌入配置的权威来源。在步骤 2 中使用这些文档进行映射,而不要仅依赖硬编码表格。
与下方的项目扫描步骤并发启动此操作。
1b:识别后端语言和框架
- 检查依赖项/构建文件(
package.json、requirements.txt、Gemfile、pom.xml、go.mod、composer.json等)。 - 识别模板引擎,并记录语言和框架。
1c:检查是否已有模块化嵌入配置
并行搜索以下模式,以检测应用是否已配置模块化嵌入:
/app/embed.js— 现有的 embed.js 脚本标签window.metabaseConfig— 现有的配置赋值
记录两者是否已存在及其所在位置。如果两者都已存在(例如,应用在使用静态嵌入的同时也使用模块化嵌入),则步骤 3a 和 3b 将跳过添加操作。
1d:查找所有静态嵌入代码
使用 Grep 并行搜索以下所有模式:
- 所有文件中的
/embed/dashboard/— 静态嵌入仪表板 URL - 所有文件中的
/embed/question/— 静态嵌入问题 URL - 所有模板/HTML/JSX/view 文件中的
<iframe— 嵌入元素 METABASE_SECRET_KEY或METABASE_EMBEDDING_SECRET_KEY— 签名密钥resource:附近的dashboard或question— JWT 负载结构iframeResizer— 可选的自动调整大小脚本
对于每个匹配的文件,读取整个文件。
1e:查找 JWT 签名代码
使用 Grep 并行搜索以下所有模式:
jwt.sign或jwt.encode或JWT或jsonwebtoken或PyJWT或joseMETABASE_SECRET_KEY或MB_EMBEDDING_SECRET_KEY- 与
params:组合的resource:(静态嵌入 JWT 负载结构)
对于每个匹配的文件,读取整个文件。
1f:查找布局/头部文件
找到定义 HTML <head> 部分的单个文件(或通用代码路径)——embed.js 和 window.metabaseConfig 将在此处注入(除非步骤 1c 中已确认它们存在)。
搜索:
- 模板/view 文件中的
<head>或<!DOCTYPE或<html - 布局/包装器模式:
include('head')、<%- include、{% extends、{% block、layout、base.html、_layout、application.html - 如果应用通过服务器代码中的内联字符串生成 HTML(例如
res.send(...)),则确定<head>内容的生成位置
1g:查找 Metabase 配置
搜索以 METABASE_ 和 MB_ 为前缀的变量。记录每个与 Metabase 相关的变量名称及其读取位置。
输出:结构化项目清单
将所有发现汇总为:
Backend: {language}, {framework}, {template engine}
Metabase config:
- Site URL variable: {name} (read at {file}:{line})
- Secret key variable: {name} (read at {file}:{line})
- Other variables: ...
Layout/head file: {path}:{line range}
Static embeds found: {count}
- {file}:{line} — {brief description} (dashboard/question, ID: {id})
- ...
JWT signing: {file}:{line} — {library used}
JWT payload: resource type={dashboard|question}, params={list or "none"}
iframeResizer: {present|not present}
Existing modular embedding: {embed.js: yes/no, metabaseConfig: yes/no}
步骤 2:分析静态嵌入并映射到 Web 组件(仅在步骤 1 ✅ 完成后执行)
使用步骤 1a 中获取的文档作为 Web 组件属性、window.metabaseConfig 选项和访客嵌入行为的权威参考。下方的硬编码表格仅作为备用参考——如果文档描述了适用于目标版本的其他属性或不同的行为,请以文档为准。
对步骤 1 中找到的每个静态嵌入:
2a:解析已签名的 iframe URL
从 iframe 的 src 属性中提取:
- Metabase 基础 URL:可能来自环境变量、常量,也可能是硬编码的
- 资源类型:
dashboard或question(来自/embed/{type}/路径) - 资源 ID:JWT 的
resource字段中的数字 ID(例如,resource: { dashboard: 10 }) - 锁定参数:JWT 负载中的任何
params(例如,params: { category: ["Gadget"] }) - 哈希参数:
#后的外观自定义项(例如,#titled=true&bordered=false) - iframeResizer 用法:是否对此 iframe 调用了
iFrameResize()
2b:将内容类型映射到 Web 组件
| 静态嵌入 URL 模式 | 模块化 Web 组件 | 必需属性 |
|---|---|---|
/embed/dashboard/{JWT} | <metabase-dashboard> | token="{JWT}" |
/embed/question/{JWT} | <metabase-question> | token="{JWT}" |
token 属性接收此前嵌入在 iframe URL 中的同一个已签名 JWT。后端签名代码保持不变——只有传递方式会改变。
如果令牌是在模板中动态构建的(例如,src="<%= metabaseUrl %>/embed/dashboard/<%= token %>"),请提取令牌变量并将其作为 token 属性传入(例如,token="<%= token %>")。
2c:映射哈希参数
可映射到 Web 组件属性的参数:
| 静态嵌入哈希参数 | 访客嵌入对应项 |
|---|---|
titled=true/false | 在组件上使用 with-title="true/false" |
bordered=true/false | 无直接对应项——舍弃(Web 组件没有边框装饰) |
refresh=N | 无直接对应项——舍弃(由 Metabase 实例配置处理) |
theme=night | 改用 window.metabaseConfig.theme(如果目标版本支持) |
2d:映射锁定参数和可编辑参数
锁定参数(JWT 的 params 字段中)——无需更改。它们保留在 JWT 中,并继续以相同方式工作。签名令牌中已包含这些参数。
可编辑参数——如果静态嵌入允许用户与筛选器交互,现在可以通过 initial-parameters 属性设置这些参数的默认值:
<metabase-dashboard
token="{JWT}"
initial-parameters='{"category":["Doohickey","Gizmo"]}'
></metabase-dashboard>
initial-parameters 设置用户可以更改的筛选器默认值。这是静态 iframe 嵌入不具备的新功能。
2e:输出迁移映射表
对每个静态嵌入,输出:
embed #{n}: {file}:{line}
Old: {iframe HTML or signing + iframe code}
Content type: {dashboard|question}
Token variable: {template expression for the signed JWT}
Locked params: {in JWT — no change needed}
Hash params: {list or "none"}
Dropped params: {list}
Mapped attributes: {list}
New: {exact replacement web component HTML}
步骤 3:规划迁移变更(仅在步骤 2 ✅ 完成后执行)
创建完整的逐文件变更计划,涵盖以下所有方面。每项变更都应注明目标文件、旧代码和新代码。
3a:每个应用中仅配置一次 metabaseConfig
如果步骤 1c 发现已有 window.metabaseConfig 赋值,请跳过此步骤。 如果已存在但缺少 isGuest: true,请将该字段添加到现有配置中,而不是新建配置。
- 目标:步骤 1f 中确定的布局/头部文件
- 位置:
<head>内,embed.js 脚本标签之前(必须在 embed.js 加载前设置配置) - 要添加的代码:
<script> window.metabaseConfig = { isGuest: true, instanceUrl: "{METABASE_SITE_URL}", }; </script> - 必须设置
isGuest: true——它会告知 embed.js 使用访客(签名令牌)模式,而不是 SSO 模式。 instanceUrl应使用项目的模板表达式语法动态渲染。- 区域设置:如果在任何静态嵌入哈希中发现
locale参数,请在配置对象中添加locale: "{code}"。 - 请查阅获取的文档(步骤 1a),了解目标版本支持的任何其他
window.metabaseConfig选项(例如,theme、font)。 window.metabaseConfig应仅设置一次。
3b:注入 embed.js 脚本 — 每个应用仅注入一次
如果步骤 1c 发现已有 embed.js 脚本标签,请跳过此步骤。
- 目标:与 3a 相同的布局/头部文件
- 位置:
<head>内,位于window.metabaseConfig脚本之后(embed.js 加载时会读取配置) - 要添加的代码:
<script defer src="{METABASE_SITE_URL}/app/embed.js"></script> {METABASE_SITE_URL}应使用项目现有的模板表达式语法动态渲染。- 验证无论用户访问哪个页面,该代码在渲染后的 HTML 中都只出现一次。
3c:重构后端令牌传递
后端已有用于生成令牌的 JWT 签名代码。目前它会构建完整的 iframe URL(/embed/dashboard/{token}#params)。签名逻辑保持不变,但令牌传递到前端的方式需要更改:
- 之前:后端构建完整的 iframe URL 字符串并传给模板,模板渲染
<iframe src="{url}"> - 之后:后端只将签名令牌传给模板,模板渲染
<metabase-dashboard token="{token}">
对于步骤 1d 中找到的每个签名位置:
- 保留 JWT 签名调用(
jwt.sign(payload, METABASE_SECRET_KEY)),不作更改 - 删除拼接
{baseUrl}/embed/dashboard/并附加哈希参数的 URL 构建代码 - 向模板上下文传递原始令牌字符串,而不是完整 URL
如果签名代码内联在模板处理函数中(而不是位于共享函数中),则只需在该处理函数中进行修改。
3d:替换 iframe 的计划
对于步骤 2e 的迁移映射表中的每个 iframe:
- 指明:文件路径、要替换的准确旧代码、准确的新代码
- 新 Web 组件使用
token="{token_variable}",其中{token_variable}是签名 JWT 的模板表达式 - 按照步骤 2c 将哈希参数映射到组件属性
- 保留样式:将 iframe 的尺寸设置直接转移到 Web 组件元素上——无需包装
<div>:- 如果 iframe 有
width/heightHTML 属性或内联style,则直接应用到 Web 组件上(例如,<metabase-dashboard token="..." style="width:800px;height:600px">) - 如果 iframe 通过 CSS 类设置样式,则将这些类直接应用到 Web 组件上
- 如果 iframe 位于已控制尺寸的容器中,则无需额外设置样式——Web 组件会填满该容器
- 如果 iframe 使用
iframeResizer实现自动高度,则移除它——Web 组件会自行处理尺寸
- 如果 iframe 有
- 移除与此 iframe 关联的任何
iframeResizer调用
3e:移除无用代码
替换 iframe 后,找出并移除:
- 构建
/embed/dashboard/{token}#params或/embed/question/{token}#params字符串的 URL 构建代码 iframeResizer.js脚本标签及所有iFrameResize()调用- 哈希参数字符串构建代码(例如,
const mods = "titled=true&bordered=false") - 仅用于构建静态嵌入 iframe URL 的任何辅助函数
不要移除:
- JWT 签名代码(
jwt.sign(payload, METABASE_SECRET_KEY))——仍在使用 METABASE_SECRET_KEY环境变量——仍在使用- JWT 库导入——仍在使用
- 应用其他部分使用的任何代码
3f:Metabase 管理员配置说明(用户需手动完成)
将以下内容列入计划——它们会包含在最终摘要中:
- 启用模块化嵌入:Admin > Embedding > 切换“Enable modular embedding”
- 启用访客嵌入:Admin > Embedding > 确认已启用“Guest embedding”(较旧的 UI 中为“Static embedding”)。现有的静态嵌入密钥会继续使用。
- 配置 CORS 来源:Admin > Embedding > Security > 添加宿主应用的域名(例如,
http://localhost:9090)。这是新增步骤——静态 iframe 嵌入不需要配置 CORS。
步骤 4:应用代码更改(仅在步骤 3 ✅ 后)
按以下顺序应用步骤 3 中的所有更改:
- 首先:在布局/头部文件中添加
window.metabaseConfig赋值和 embed.js 脚本标签(步骤 3a + 3b,配置必须置于 embed.js 之前) - 其次:重构后端令牌传递方式——保留签名,移除 URL 构造(步骤 3c)
- 第三:将每个 iframe 替换为对应的 Web 组件(步骤 3d),一次处理一个文件
- 第四:移除无用代码——iframeResizer、URL 构造器(步骤 3e)
约束:
- 每项更改都使用 Edit 工具,并提供精确的
old_string/new_string - 不要添加新的软件包依赖——模块化嵌入只需要由 Metabase 实例提供的 embed.js 脚本
- 不要更改或移除
METABASE_SECRET_KEY——它仍用于签名 - 如果一个文件需要多处编辑,请按从上到下的顺序应用,避免偏移问题
步骤 5:验证更改(仅在步骤 4 ✅ 后)
执行以下所有检查。每项检查都应明确给出通过/失败结果。
5a:没有遗留的静态嵌入 iframe
使用 Grep 在所有项目文件中搜索 /embed/dashboard/ 和 /embed/question/(排除 node_modules、.git 和锁文件)。
通过标准:未找到任何静态嵌入 URL 构造(该模式可能仍出现在注释中——请确认这些不是实际运行的代码)。
5b:embed.js 恰好出现一次
使用 Grep 在所有项目文件中搜索 /app/embed.js(排除 node_modules、.git)。
通过标准:仅在布局/头部文件中出现一次。
5c:window.metabaseConfig 恰好设置一次
使用 Grep 在所有项目文件中搜索 window.metabaseConfig(排除 node_modules、.git)。
通过标准:恰好出现一次,且包含 isGuest: true。
5d:JWT 签名代码已保留
阅读 JWT 签名文件。验证:
jwt.sign(或等效调用)仍然存在- 仍从环境中读取
METABASE_SECRET_KEY - JWT 载荷仍包含
resource和params字段
通过标准:签名逻辑完整无缺。
5e:没有遗留的 iframeResizer 引用
使用 Grep 在所有项目文件中搜索 iframeResizer 和 iFrameResize。
通过标准:不再有任何引用(或仅存在于无关代码中)。
5f:抽查已修改的文件
阅读每个已修改的文件,并验证:
- Web 组件具有
token属性,且使用正确的模板表达式 - 模板语法有效(标签均已闭合,表达式正确)
- 已移除步骤 3e 中确认的无用代码
通过标准:所有检查均通过。
如果任何检查失败:
- 立即修复问题
- 重新运行相应检查
- 如果尝试 3 次后仍无法修复,则将步骤 5 标记为 ❌ 受阻,并报告未通过的检查及原因
第 6 步:输出摘要
将最终输出整理为以下部分:
- 已应用的更改:列出每个已修改的文件,并用一句话描述每项更改
- Web 组件映射:使用表格展示每个旧的已签名 iframe → 新的 Web 组件:
| File | Old | New | |---|---|---| | views/analytics.ejs | <iframe src="/embed/dashboard/{token}#titled=true"> | <metabase-dashboard token="{token}" with-title="true"> | - 保持不变的内容:JWT 签名逻辑、
METABASE_SECRET_KEY、JWTparams字段中的锁定参数 - 已移除的参数:列出已移除的静态嵌入哈希参数,并简要说明原因
- 现已支持的新功能:列出静态 iframe 嵌入中无法使用、现在可以使用的功能:
initial-parameters属性,用于设置可编辑的筛选器默认值with-downloads属性,用于启用下载(Pro/Enterprise)- 更好的移动端响应能力(Web 组件会适应容器)
- 所需的手动操作(第 3f 步中的 Metabase 管理配置):
- 启用模块化嵌入
- 确保已启用访客嵌入(复用现有密钥)
- 配置 CORS 来源(新增要求)
- 需要注意的行为差异:
- Web 组件会扩展并填满其容器——如果 iframe 使用了固定尺寸,请确认容器尺寸合适
- 不再提供
bordered外观选项——Web 组件渲染时不带边框 - 不再通过各嵌入项单独控制自动刷新(
refresh=N)——请在 Metabase 实例设置中配置
重试策略
获取文档:
- 如果获取
llms-embedding-full.txt时返回 404,请核实 Metabase 版本号并重试。如果仍然失败,将第 1 步标记为 ❌ 受阻。
验证:
- 如果第 5 步中的任何验证检查在尝试修复 3 次后仍未通过,将第 5 步标记为 ❌ 受阻,并说明失败的检查及原因。
- 如果 AskUserQuestion 未得到回答,则该步骤保持受阻状态——不要猜测或基于假设继续操作。