mcpField
F
fabriciq-ontology-authoring-cli

fabriciq-ontology-authoring-cli

github.com/microsoft数据与数据库1.3k47 次安装3 周前更新
代码仓库

关于 fabriciq-ontology-authoring-cli

fabriciq-ontology-authoring-cli 是通过 Microsoft Fabric 控制平面 API 编写 Ontology 项目定义的 CLI 技能,支持实体类型、数据绑定和关系,并在写入前预览确认。

主要功能

  1. 01创建和更新 Ontology 定义
  2. 02编写实体类型及属性
  3. 03绑定 Lakehouse 和 Eventhouse 表
  4. 04定义关系及上下文映射
  5. 05写入前预览拟议变更

适用场景

  1. 01根据 Fabric 表数据建模实体
  2. 02配置来自 Eventhouse 的时序绑定
  3. 03通过关系连接实体类型
  4. 04创建或修改 Ontology 项目

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/microsoft/skills-for-fabric --skill fabriciq-ontology-authoring-cli

安装后在 Claude Code 中输入/fabriciq-ontology-authoring-cli确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
authoring-mechanics.md
definition-script-templates.md
examples.md
ONTOLOGY-AUTHORING-CORE.md
preview-and-confirm.md

详细介绍

更新检查——每个会话仅执行一次(必须) 本技能在一个会话中首次使用时,继续操作前请先运行 check-updates 技能。

  • GitHub Copilot CLI / VS Code:调用 check-updates 技能(例如 /fabric-skills:check-updates)。
  • Claude Code / Cowork / Cursor / Windsurf / Codex:读取本地 package.json 版本,然后通过 git fetch origin main --quiet && git show origin/main:package.json(或 GitHub API)与远程版本比较。如果远程版本较新,请显示更新日志和更新说明。
  • 如果本会话中已执行过检查,则跳过。

重要说明

  1. Ontology 处于 预览版。项类型值为 Ontology。功能和线格式可能会发生变化;用于生产环境前,请对照当前文档进行验证。
  2. 要根据工作区名称查找工作区详细信息(包括其 ID),请列出所有工作区并使用 JMESPath 进行筛选。
  3. 要根据工作区 ID、项类型(Ontology)和项名称查找项的详细信息(包括其 ID),请列出该工作区中此类型的所有项并使用 JMESPath 进行筛选。
  4. 创建关系类型需要使用本体中已存在的 两种不同实体类型。source.entityTypeId 和 target.entityTypeId 的值是你分配的实体类型 ID,而非项 ID。
  5. 数据绑定通过 workspaceId、itemId、sourceTableName 以及湖仓源的 sourceSchema 引用源表。湖仓(LakehouseTable)源携带湖仓项 ID;Eventhouse(KustoTable)源携带 Eventhouse 项 ID,以及 clusterUri 和 databaseName。源端的键列必须与实体类型的键属性匹配。Eventhouse 源仅适用于 TimeSeries;静态(NonTimeSeries)绑定必须来自湖仓。

fabriciq-ontology-authoring-cli — 通过 CLI 创建 Fabric Ontology

目录

任务参考备注
在 Fabric 中查找工作区和项COMMON-CLI.md § Finding Workspaces and Items in Fabric必须 — 编写内容前先解析工作区/项 ID
Fabric 拓扑与关键概念COMMON-CORE.md § Fabric Topology & Key Concepts工作区 → 项层级
身份验证与令牌获取COMMON-CORE.md § Authentication & Token Acquisition控制平面使用 https://api.fabric.microsoft.com 作为受众
核心控制平面 REST APICOMMON-CORE.md § Core Control-Plane REST APIs创建项、获取/更新项定义
长时间运行的操作(LRO)COMMON-CORE.md § Long-Running Operations (LRO)创建/更新项会返回 LRO
速率限制与节流COMMON-CORE.md § Rate Limiting & Throttling
身份验证方法COMMON-CLI.md § Authentication Recipesaz login;获取令牌
通过 az rest 调用 Fabric 控制平面 APICOMMON-CLI.md § Fabric Control-Plane API via az rest始终传入 --resource https://api.fabric.microsoft.com
长时间运行的操作(LRO)模式COMMON-CLI.md § Long-Running Operations (LRO) Pattern对于 Ontology 的创建/更新,在 Fabric 主机上轮询 /v1/operations/{x-ms-operation-id} — 请参阅 LRO Header Capture
注意事项与故障排除(CLI 专属)COMMON-CLI.md § Gotchas & Troubleshooting (CLI-Specific)令牌受众、Shell 转义
az rest 模板COMMON-CLI.md § az rest Template
定义封装(parts、payloadType)ITEM-DEFINITIONS-CORE.md § Definition EnvelopeOntology 使用的 InlineBase64 parts 模式
Ontology 定义参考ONTOLOGY-AUTHORING-CORE.md § Definition TreeOntology 项权威文件/文件夹布局
EntityType 与 EntityTypeProperty 架构ONTOLOGY-AUTHORING-CORE.md § EntityType file允许的 valueType 值、键约束、名称正则表达式
DataBinding 架构与源类型映射ONTOLOGY-AUTHORING-CORE.md § DataBinding fileLakehouse 与 Eventhouse 结构;值类型映射;绑定规则
RelationshipType 与 Contextualization 架构ONTOLOGY-AUTHORING-CORE.md § RelationshipType file源/目标约束、链接表要求
Ontology 概念SKILL.md § Ontology Item Concepts实体类型、属性、绑定、关系类型
工具栈SKILL.md § Tool Stack
连接SKILL.md § Connection发现工作区、Lakehouse、Ontology ID
编写范围SKILL.md § Authoring Scope支持的操作一览
编写机制(完整参考)authoring-mechanics.md封装、ID、创建、实体类型、绑定、关系、更新、验证
示例examples.md端到端 bash 方法(创建 → 绑定 → 关系 → 时间序列)
预览与确认(LRO 写入前必须执行)preview-and-confirm.mdASCII 提案(全新构建)/变更集差异(现有项目)
脚本模板definition-script-templates.mdBash / PowerShell 获取-修改-发送脚手架
必须 / 优先 / 避免 / 故障排除SKILL.md § Must / Prefer / Avoid / TroubleshootingLLM 决策规则
Agent 工作流SKILL.md § Agentic Workflows先探索再编写、脚本生成
Agent 集成说明SKILL.md § Agent Integration Notes此技能如何与 Agent / 其他技能组合

本体项概念

Fabric 本体项以定义中的 JSON 文件树形式编写。每个文件都作为一个部分,包含在创建/更新定义信封的 parts[] 数组中(payloadType InlineBase64)。

概念定义文件路径用途
本体信封definition.json空 {};必需
平台元数据.platform{ "metadata": { "type": "Ontology", "displayName": "<name>" } }
实体类型EntityTypes/{entityTypeId}/definition.json名称、命名空间、键、显示名称属性、properties[]、timeseriesProperties[]
实体类型数据绑定EntityTypes/{entityTypeId}/DataBindings/{guid}.json将 lakehouse 或 eventhouse 表映射到属性;dataBindingType = NonTimeSeries 或 TimeSeries。仅 TimeSeries 允许使用 Eventhouse(KustoTable)源
实体类型文档EntityTypes/{entityTypeId}/Documents/{name}.json可选文档链接
实体类型概览EntityTypes/{entityTypeId}/Overviews/definition.json可选小组件布局
实体类型资源链接EntityTypes/{entityTypeId}/ResourceLinks/definition.json可选 Power BI / 项目链接
关系类型RelationshipTypes/{relTypeId}/definition.json源实体类型 ID、目标实体类型 ID、名称
关系上下文化RelationshipTypes/{relTypeId}/Contextualizations/{guid}.json将源/目标键绑定到 lakehouse 表

属性 valueType 允许的值(必须完全一致):String、Boolean、DateTime、Object、BigInt、Double。整数请使用 BigInt,不要使用 Int64;没有 Guid 值类型(请将模型 GUID 设为 String)。时间序列绑定需要时间戳列(源类型为 datetime / date / timestamp),并且绑定类型须为 TimeSeries,且包含 timestampColumnName。完整的源列 → valueType 映射请参阅 ONTOLOGY-AUTHORING-CORE.md § EntityTypeProperty。

⚠️ 单个实体类型中,properties[] 和 timeseriesProperties[] 里的属性名称必须唯一。如果 lakehouse 表和 Eventhouse 表中都包含同名列(例如 tenant_id),则必须重命名其中一个本体属性名称,以避免冲突。绑定中的 sourceColumnName 仍可指向原始列——只有本体属性的 name 必须唯一。例如,静态属性保留为 TenantId,时间序列属性命名为 TsTenantId。

⚠️ 不同实体类型中具有相同 name 的属性必须使用相同的 valueType——本体会在整个定义中强制执行名称级别的类型一致性。如果某个实体类型中的 SerialNum 为 String,则另一个实体类型中不能将其设为 BigInt。请在所有位置使用相同的 valueType,或添加前缀以区分(例如 SerialNumStr 与 SerialNumInt)。

⚠️ 部分路径必须始终使用正斜杠(EntityTypes/{id}/definition.json),不能使用反斜杠。在 Windows 上,PowerShell 路径拼接运算符(Join-Path、\)会生成反斜杠,Fabric API 会因此返回 ALMOperationBadRequest。请始终使用字符串插值和 / 构建部分路径。


工具栈

本体创作使用与其他 CLI 技能相同的 Fabric 控制平面工具栈 — 规范列表(安装命令、先决条件检查、base64 助手、JSON 工具)请参阅 COMMON-CLI.md § 工具选择理由,az login 和令牌获取请参阅 COMMON-CLI.md § 身份验证方法。

以下本体专属工具指南仅涵盖 createItem / updateDefinition 有效负载中遇到的问题。

⚠️ PowerShell ConvertTo-Json 警告:PowerShell 的 ConvertTo-Json 可能会静默地重新排列键,并以不同于 JSON null 的方式序列化 $null,从而导致 updateDefinition 出现 ALMOperationImportFailed 错误。为避免此问题:

  1. 始终使用 [System.IO.File]::WriteAllText,并搭配 [System.Text.UTF8Encoding]::new($false) 写入 JSON 文件 — Out-File 和 Set-Content 会添加 BOM,导致有效负载损坏。
  2. 尽可能使用 jq 构建 JSON,而不是 ConvertTo-Json — jq -nc 可生成确定且紧凑的 JSON,不受 PowerShell 序列化问题影响:
    $json = '{}' | jq -nc --arg id "$ET_ID" --arg name "Site" '{id:$id,name:$name}'
    
  3. 发送前验证 JSON:Get-Content envelope.json | jq . — 如果 jq 失败,则说明有效负载格式错误。
  4. 对 ConvertTo-Json 使用 -Depth 10 — 默认深度为 2,会静默截断嵌套对象。

⚠️ 避免对 InlineBase64 部分使用 certutil -encode。 它的输出会按行换行,并带有页眉和页脚,使用前必须进行后处理。在 Windows 上,请改用 PowerShell 的 [Convert]::ToBase64String([IO.File]::ReadAllBytes($path))。


连接

本体创作的目标是 Fabric 控制平面。在编写定义之前,你需要:WS_ID(工作区)、LH_ID(用于静态绑定和湖仓时序绑定的湖仓项 ID),以及 — 对于由 Eventhouse 提供支持的时序 — Eventhouse 项 ID、KQL 群集 URI 和 KQL 数据库名称。

以下是本体专属的查找注意事项(文件夹 GUID 与门户数字 ID、Eventhouse ID 字段映射、绑定的架构发现,以及在预览版重定向主机上捕获 LRO 标头)。

文件夹(本体专属注意事项)

本体创建有效负载中的 folderId 字段需要文件夹 GUID — 而不是门户 URL 中显示的数字 subfolderId。传入门户中的数字会导致 400 InvalidParameter … cannot convert "<numeric>" to Guid … Path 'folderId'。请按照 COMMON-CLI.md § 在 Fabric 中查找工作区和项 中所述,列出 GET /v1/workspaces/{WS_ID}/folders 并按 displayName 筛选,以查找 GUID。

Eventhouse / KQL 数据库(用于 TimeSeries 绑定)

由 Eventhouse 提供支持的 TimeSeries 本体绑定,需要在 KustoTable 数据绑定负载中包含三个字段——这些字段取自 GET /v1/workspaces/{WS_ID}/kqlDatabases 返回的 KQL 数据库记录:

KustoTable 绑定字段KQL 数据库记录中的源字段
itemIdproperties.parentEventhouseItemId — Eventhouse 项目 ID,而不是 KQL 数据库自身的 id
clusterUriproperties.queryServiceUri
databaseNamedisplayName(使用 API 返回的规范大小写)

Eventhouse 表只能用于 TimeSeries 绑定。 实体类型的静态(NonTimeSeries)绑定仍必须来自托管 lakehouse 表。

常见错误:将 KQL 数据库自身的 id 作为 KustoTable.itemId 传入。请使用同一记录中的 parentEventhouseItemId。

有关通用的 kqlDatabases 列表调用(分页 + 按 displayName 使用 JMESPath 筛选),请参阅 COMMON-CLI.md § 在 Fabric 中查找工作区和项目。

架构发现

编写绑定前,请先发现源表架构,以便映射正确的列名。请使用配套技能发现架构——它们比原始 REST 调用更快捷、更可靠。

  • Lakehouse 表 → 使用 sqldw-consumption-cli 技能,并针对 lakehouse SQL 终结点查询 INFORMATION_SCHEMA.COLUMNS(一次查询即可返回所有表和列)。如果无法使用,请改用 Fabric Tables REST API 和 OneLake Table API 获取 Iceberg 元数据。
  • Eventhouse / KQL 表 → 使用 eventhouse-consumption-cli 技能并运行 .show database schema as json(单次响应即可返回所有表和列)。如需查询单个表,请使用 .show table <name> schema as json。

使用此处返回的列类型为每个 EntityTypeProperty 填写 valueType——请参阅 ONTOLOGY-AUTHORING-CORE.md § EntityTypeProperty 中的源列 → valueType 映射。

使用 az rest 捕获 LRO 标头

默认情况下,az rest 不会公开响应标头。createItem 和 updateDefinition 都会返回 202 Accepted,并带有 x-ms-operation-id 标头(以及 Location 标头)。请使用 --verbose 并解析 stderr,以捕获操作 ID:

本体创建/更新时,优先使用 x-ms-operation-id 轮询,而不是直接使用 Location 标头。 公共 Fabric LRO 合约支持通过 Location 标头或 https://api.fabric.microsoft.com/v1/operations/{operationId}(使用 x-ms-operation-id)轮询。在当前本体预览版行为中,观测到的 Location 值指向 analysis.windows.net 重定向主机(例如 https://df-…-redirect.analysis.windows.net/v1/operations/{id}),而非 api.fabric.microsoft.com;使用 az rest --resource https://api.fabric.microsoft.com 轮询该 URL 时,会针对错误的受众重新进行身份验证,并因 401/403 而失败——这会隐藏 LRO 状态/错误,并导致盲目重试。因此,请捕获 x-ms-operation-id 并轮询 https://api.fabric.microsoft.com/v1/operations/{operationId}(Fabric 主机,Fabric 令牌)。如果确实要使用 Location,请使用该 URL 所需的受众。

# Bash — capture x-ms-operation-id from az rest --verbose stderr
OP_ID=$(az rest --method POST \
  --url "https://api.fabric.microsoft.com/v1/workspaces/${WS_ID}/items" \
  --resource "https://api.fabric.microsoft.com" \
  --headers "Content-Type=application/json" \
  --body @envelope.json --verbose 2>&1 \
  | grep -oiP "(?<=x-ms-operation-id': ')[^']+")

# Poll the Fabric operations endpoint (stays on api.fabric.microsoft.com)
while :; do
  OP=$(az rest --method GET \
    --url "https://api.fabric.microsoft.com/v1/operations/${OP_ID}" \
    --resource "https://api.fabric.microsoft.com")
  STATUS=$(printf '%s' "$OP" | jq -r .status)
  case "$STATUS" in
    Succeeded) break ;;
    Failed|Cancelled)
      # Read the error and FIX the payload — never blind-retry the same body.
      printf '%s' "$OP" | jq -r '.error | "\(.errorCode // .code): \(.message)"' >&2
      exit 1 ;;
    *) sleep 5 ;;
  esac
done
# PowerShell — capture x-ms-operation-id from az rest --verbose stderr
$result = az rest --method POST `
  --resource "https://api.fabric.microsoft.com" `
  --url "https://api.fabric.microsoft.com/v1/workspaces/$WS_ID/items" `
  --headers "Content-Type=application/json" `
  --body "@envelope.json" --verbose 2>&1
$opId = ($result | Select-String -Pattern "x-ms-operation-id': '([^']+)'" |
  ForEach-Object { $_.Matches[0].Groups[1].Value })

# Poll the Fabric operations endpoint (stays on api.fabric.microsoft.com)
do {
  Start-Sleep -Seconds 5
  $op = az rest --method GET `
    --url "https://api.fabric.microsoft.com/v1/operations/$opId" `
    --resource "https://api.fabric.microsoft.com" | ConvertFrom-Json
} while ($op.status -notin 'Succeeded','Failed','Cancelled')
if ($op.status -ne 'Succeeded') {
  # Read .error and FIX the payload — never blind-retry the same body.
  throw "createItem LRO $($op.status): $($op.error.errorCode) $($op.error.message)"
}

重要:createItem 返回 202,且没有响应正文——az rest 以代码 0 退出,不会打印任何内容。这是正常现象。操作达到 Succeeded 后,请列出项目以获取新项目 ID。如果 status 为 Failed,error 字段会指出原因(例如实体类型部分格式错误)——请修正负载并提交更正后的请求,而不要重新发送相同的正文。


编写范围

操作Fabric REST 调用涉及的定义部分
创建空本体POST /v1/workspaces/{ws}/items,其中 type=Ontology.platform、definition.json
添加 / 修改实体类型POST /v1/workspaces/{ws}/items/{id}/updateDefinitionEntityTypes/{id}/definition.json
将实体类型绑定到表(非时序)updateDefinitionEntityTypes/{id}/DataBindings/{guid}.json,包含 NonTimeSeries
将实体类型绑定到表(时序)updateDefinitionEntityTypes/{id}/DataBindings/{guid}.json,包含 TimeSeries + timestampColumnName
添加关系类型updateDefinitionRelationshipTypes/{id}/definition.json
绑定关系(上下文化)updateDefinitionRelationshipTypes/{id}/Contextualizations/{guid}.json
删除实体 / 关系使用省略该路径部分的 updateDefinition—
重命名本体使用 updateMetadata=true 和新的 .platform 的 updateDefinition.platform

**更新项目定义会替换所包含部分的完整树结构。**务必先通过 Get Item Definition 获取当前定义,在本地修改各部分,然后重新发送完整的目标部分集合。


编写参考

每项操作的完整 JSON 结构、字段约定和验证方法见 authoring-mechanics.md。端到端 Bash 操作示例见 examples.md。以下各节可用作快速索引:

主题参考
定义封装(parts[]、InlineBase64、base64 辅助函数)authoring-mechanics.md § Definition Envelope
ID 生成(64 位整数、GUID、name → id 映射)authoring-mechanics.md § ID Generation Pattern
创建空本体authoring-mechanics.md § Create the Ontology Item
添加实体类型authoring-mechanics.md § Add an Entity Type
绑定到 lakehouse / eventhouseauthoring-mechanics.md § Bind an Entity Type
关系类型 + 上下文化authoring-mechanics.md § Add a Relationship Type
应用定义更新(获取 → 修改 → 发送)authoring-mechanics.md § Apply a Definition Update
验证和检查authoring-mechanics.md § Verify and Inspect
完整的 Bash / PowerShell 脚手架definition-script-templates.md

编写时需牢记的核心不变量(完整细节见参考文件):

  • 封装结构:{ "displayName", "type": "Ontology", "definition": { "parts": [ { "path", "payload", "payloadType": "InlineBase64" } ] } };definition.json 的内容就是 {};.platform 包含 metadata.type: "Ontology" + displayName。
  • ID:实体 / 关系 / 属性 ID 是正 64 位整数,数据绑定 / 上下文化 ID 是 GUID。在源代码管理中保存 name → id 映射;切勿将同一 ID 用于不同概念。

ID 映射模板——将其与部署脚本一同保存(JSON 或 YAML):

{
  "ontologyName": "SkillTest_Fleet",
  "entityTypes": {
    "Site":      { "id": "1048860412765431174", "properties": { "SiteId": "1428056703884423742", "SiteName": "4251708967918658190" } },
    "Equipment": { "id": "3332700945676096991", "properties": { "EquipmentId": "4585483423451989345" } }
  },
  "relationshipTypes": {
    "EquipmentAtSite": { "id": "4242053467032157032" }
  },
  "bindings": {
    "Site_static":      "25e3a44a-b62a-40e3-a64a-a43caaa92d19",
    "Equipment_static": "5dc4cadd-3700-4c96-bb1e-41e4c909ae4d"
  }
}
  • 绑定:NonTimeSeries 仅适用于 lakehouse,且每种实体类型最多只能有一个;同一实体类型上的任何 TimeSeries 绑定之前,都必须先有 NonTimeSeries 绑定;TimeSeries 可绑定到 lakehouse 或 Eventhouse;对于 KustoTable,itemId 是 Eventhouse 项目 ID(而非 KQL 数据库 ID)。
  • 关系:source.entityTypeId 和 target.entityTypeId 必须不同,并且必须引用 parts 树中存在的实体类型。
  • 更新会整体替换其中包含的 parts——务必先获取当前定义,在本地修改,然后发送。

必须 / 优先 / 避免 / 故障排除

必须遵守
  • 路由到此处前,必须明确要求提供本体上下文——提示词必须要求创建或更改“本体”(或引用某个本体项)。没有本体上下文的通用“Fabric IQ”提示词不属于本体创作任务;应转交给匹配的技能。这可以避免共享的“Fabric IQ”品牌导致此技能被过度触发。
  • 对含糊的提示词,先澄清再操作——绝不推断架构或绑定。如果用户说“为航空公司数据创建一个本体”,却没有说明实体类型、实体键或湖仓表,应询问具体有哪些实体、实体键是什么,以及使用哪些湖仓表。替换本体定义等不可逆副作用操作,必须得到用户明确授权。
  • 编写任何绑定前,先解析 WS_ID 和源项 ID——硬编码 GUID 是最常见的三大故障原因之一。湖仓绑定需要湖仓的 itemId;事件中心绑定需要事件中心的 itemId、群集 URI 和数据库名称。
  • 更新前先获取当前定义——updateDefinition 会整体替换所包含的部分。与过时的本地状态合并会悄无声息地丢弃近期更改。处理 getDefinition 返回的 LRO 202 状态(轮询并通过该操作的 result 端点获取结果)。
  • 在源代码管理中,和技能使用者的代码库放在一起,持久化实体类型、关系类型和属性的 name → id 映射。每次运行都重新生成 ID 会产生重复项并破坏引用。
  • 在实体类型上添加任何时间序列绑定之前,先添加静态(NonTimeSeries)绑定——每个实体类型最多支持一个静态绑定,而且时间序列绑定要求静态键属性已填充。
  • 只绑定到托管湖仓表——不支持外部表、启用了 OneLake 安全性的湖仓,以及启用了列映射的 delta 表。
  • 确保每个实体类型内 properties[] 和 timeseriesProperties[] 中的属性名称唯一。当湖仓表和 Eventhouse 表包含同名列(例如 tenant_id、device_id)时,应重命名本体时间序列属性(例如 TsTenantId),同时让 sourceColumnName 指向原始列。属性名称重复会导致 ALMOperationImportFailed。
  • 观察到的行为(预览版):将实体键(entityIdParts)限制为 valueType 为 String 或 BigInt 的属性——根据当前预览版行为,其他值类型尚未被接受为键。Microsoft Learn 公共文档未说明此限制;依赖此限制前,请在你的租户中验证。
  • 所有部分路径都使用正斜杠——使用 EntityTypes/{id}/definition.json,绝不要使用 EntityTypes\{id}\definition.json。在 Windows 上,Join-Path 和 \ 会生成 Fabric API 不接受的反斜杠。请使用字符串插值构建路径:"EntityTypes/$ET_ID/definition.json"。
  • 验证权限——创作至少需要工作区上的 Contributor 权限。
  • 在信封的 type 和 .platform 元数据中,均将项类型设为 Ontology(而不是 OntologyPreview 或类似类型)。
  • 每次 LRO 写入前都显示预览并确认环节——显示 ASCII 提案(全新创建)或与 getDefinition 对比的变更集差异(已有内容),并在调用 createItem 或 updateDefinition 前取得用户明确的 yes。请参阅 preview-and-confirm.md。除 yes 以外的任何回应都意味着停止并修改;绝不部分应用。
建议做法
  • 在磁盘上构建定义树(每个逻辑部分一个 JSON 文件,并遵循 EntityTypes/{id}/... 布局),发送前再对每个文件进行 Base64 编码。这样可以方便地审查差异。
  • 入门时,先从现有且已验证可用的本体的 getDefinition 转储开始,再进行修改。
  • 静态绑定优先使用 Lakehouse;时间序列使用 Eventhouse——对于 NonTimeSeries 绑定,唯一支持的数据源是 OneLake(lakehouse)。对于 TimeSeries 绑定中的高吞吐遥测数据,使用 Eventhouse(KustoTable);如果团队更倾向于使用单一数据源类型,也可以将数据镜像或快捷方式接入 lakehouse 表。
  • 确保部署脚本具备幂等性——输入不变时,重复运行脚本应生成不变的本体。
  • 涉及多个实体类型或环境时,优先使用脚本化工作流,而非 UI。
  • 上游数据写入后,手动触发图模型刷新——在刷新本体之前,绑定源中的新行不会显示在预览体验中。
避免
  • 生成单体 .ps1 或 .sh 脚本文件——直接在 Shell 中执行命令。大型生成脚本容易引入转义错误和 PowerShell 解析错误,而且单行失败时很难调试。使用 jq -nc 构建 JSON,将其写入临时文件,然后传递给 az rest --body @file。
  • 手动编辑 Base64 载荷——始终先解码、编辑 JSON,再重新编码。
  • 将某个属性、实体或关系 ID 复用于不同概念。
  • 依赖本体范围以外的关系名称唯一性——目前观察到,关系名称似乎在本体内唯一;请预先收集所有所需的关系名称,以便在需要时使用前缀消除歧义。遇到命名冲突时,应向使用方确认,而非自行猜测。
  • 在 .platform 或任何部分中嵌入机密、SAS 令牌或用户令牌。
  • 在源实体类型和目标实体类型尚未出现在部分列表中时创建关系类型。
  • 将 Object / JSON 属性视为可完全查询——目前观察到,绑定到 Object 属性的嵌套 JSON 会以不透明载荷的形式呈现,无法像标量一样寻址。对于嵌套载荷,请将原始数据保留在 Eventhouse 中,只绑定可寻址的标量字段。在向下游使用方承诺特定查询形式之前,请通过 getDefinition 往返验证。
  • 依赖“省略即删除”——观察到,未包含在 updateDefinition 正文中的部分会被移除,但技能应告知用户此操作具有破坏性,并在生成会丢弃部分的封套前征得确认。
故障排除
症状可能原因修复方法
创建时出现 400 Bad Request — “Invalid item type”项目类型字符串错误在 .platform 中使用 "type": "Ontology" 和 metadata.type: Ontology
使用 type: Ontology 调用 createItem 时出现 400 InvalidItemType租户 / 工作区未启用 Fabric IQ Ontology(预览版)向用户说明此情况——不要重试。必须在租户级别加入 Ontology 预览版计划。
创建时出现 400 InvalidParameter — Error converting value "<number>" to … Guid … Path 'folderId'传入了门户 URL 中的数字 subfolderId,而不是文件夹 GUID通过 GET /v1/workspaces/{WS_ID}/folders 获取文件夹 GUID(参见连接 § 文件夹),并传入该 GUID
出现 400 — 属性上的 “Invalid value type”将 Int64 / Guid / Float 用作 valueType允许的值仅为 String、Boolean、DateTime、Object、BigInt、Double
实体类型 / 属性上出现 400 — “Invalid identifier”名称不符合正则表达式符合 ^[a-zA-Z][a-zA-Z0-9_-]{0,127}$;为确保兼容性,建议采用更严格的 1–26 个字符门户规则
出现 400 — “Source and target must differ”关系两端指向了同一实体类型选择不同的源实体类型和目标实体类型
出现 400 — “Referenced property not found”targetPropertyId 与实体类型中的任何属性都不匹配检查 ID;确保属性已在同一次更新中添加
出现 400 — “Time series binding requires existing static binding”在实体类型上添加时序绑定之前,尚未添加静态绑定先添加带有键属性的 NonTimeSeries 绑定,然后再添加 TimeSeries 绑定
出现 400 — 键列问题键属性的 valueType 不是 String 或 BigInt将属性改为 String / BigInt,或选择其他键
绑定时出现 404workspaceId / itemId 错误,或源项目已删除通过 list items / list lakehouses / list eventhouses 重新解析 ID
绑定已接受,但没有实例出现源是外部表、列映射的 delta 表,或受 OneLake 安全保护将表重建为不带列映射的托管 delta 表;移除 lakehouse 上的 OneLake 安全设置
绑定后实例为空propertyBindings 列名与源列不匹配检查源架构并修正 sourceColumnName / sourceSchema
上游新增行未显示尚未执行刷新在 ontology 项目上触发手动图模型刷新
时序小组件没有数据显示未设置 timestampColumnName,或时间戳列不是受支持的日期 / 时间类型在 TimeSeries 绑定中设置 timestampColumnName;确保列类型为 datetime / date / timestamp
getDefinition 返回 200 或 202支持 LRO 的响应(可能是内联信封或操作 ID)如果是 202,轮询操作直到状态为 Succeeded,然后执行 GET https://api.fabric.microsoft.com/v1/operations/{operationId}/result;如果是 200,直接解析返回的信封——参见 LRO Header Capture
LRO 轮询返回 401 / 403,或 Location 标头的主机为 *.analysis.windows.net创建 / 更新时的 Location 重定向到了 Analysis Services 主机;使用 az rest --resource https://api.fabric.microsoft.com 轮询会针对错误的受众重新进行身份验证在 Fabric 主机上轮询 https://api.fabric.microsoft.com/v1/operations/{x-ms-operation-id},不要跟随 Location URL——参见 LRO Header Capture。轮询失败期间不要盲目重试创建操作
updateDefinition 出现 Conflict门户中有并发编辑重新获取定义、重新应用修改并重新发送
updateDefinition 出现 ALMOperationImportFailedJSON 负载格式错误——通常由 PowerShell ConvertTo-Json 序列化问题导致($null 与 null 的差异、键重排、文件中的 BOM)使用 jq -nc 构建 JSON,而不是使用 ConvertTo-Json;使用 [System.IO.File]::WriteAllText + UTF8Encoding($false) 写入文件以避免 BOM;发送前用 jq . 验证——参见 工具栈 § PowerShell 警告
createItem 或 updateDefinition 出现 ALMOperationImportFailed — 属性名称重复同一实体类型的 properties[] 和 timeseriesProperties[] 中出现了相同的属性名称两个数组中的属性名称必须唯一。如果 lakehouse 表和 Eventhouse 表共享列名,请重命名时序 ontology 属性(例如,TenantId → TsTenantId)——绑定的 sourceColumnName 仍可引用原始列
ALMOperationImportFailed — “Property 'X' has conflicting value types”相同的属性 name 出现在两个不同的实体类型中,且 valueType 值不同(例如,一个为 String,另一个为 BigInt)属性名称在整个 ontology 中必须唯一——如果两个实体类型共享属性名称,两者必须使用相同的 valueType。可通过添加前缀来区分(例如,SerialNumStr 与 SerialNumInt),或统一类型
ALMOperationBadRequest — “directory name … is not valid for EntityType”Part path 使用了反斜杠(EntityTypes\\{id}\\definition.json),而不是正斜杠Part 路径始终使用正斜杠:EntityTypes/{id}/definition.json。在 Windows 上,避免使用 Join-Path 或 \ 构造 part 路径——改用带 / 的字符串插值
createItem 返回退出代码 0,但没有输出正常情况——createItem 返回不带正文的 202 Accepted;az rest 会将其视为成功LRO 完成后列出项目以获取新项目 ID;使用 --verbose 捕获 x-ms-operation-id 标头以轮询 LRO
createItem 出现 409 ItemDisplayNameAlreadyInUse工作区中已存在具有相同 displayName 的 ontology先列出现有 ontology;删除或重命名现有项,或选择不同的名称
definition.json 负载导致导入错误base64 负载中有多余空格、BOM 或换行符definition.json 必须严格为 {}——其 base64 为 e30=。在 Windows 上,使用带有 UTF8Encoding($false) 的 [System.IO.File]::WriteAllText 确保没有 BOM

Agentic 工作流

⚠️ 请勿生成单体 .ps1 / .sh 脚本文件。 请直接在 shell 中逐条执行每个步骤。生成大型脚本文件容易引入转义错误、解析错误和属性访问问题,而且很难调试。请改为:

  • 在终端中直接运行 az rest、jq 和 PowerShell 命令
  • 使用通过变量传递的 jq -nc,逐步构建 JSON 载荷
  • 将最终封装写入临时文件,然后通过 az rest --body @file 传入
  • 如果某个步骤失败,请修复并重新运行——不要重新生成整个脚本
编写前先探索

Greenfield 与 brownfield 执行策略:

  • Greenfield(新本体):构建完整定义——实体类型、绑定、关系、上下文化和时间序列——并在一个封装中通过单次 createItem 调用完成。createItem 载荷接受完整的 definition.parts[] 数组,而不只是 .platform + definition.json。
  • Brownfield(更新现有内容):逐步执行——获取当前定义、修改、发送。每次 updateDefinition 后都用 getDefinition 验证,以便尽早发现错误。即使中途失败,也会保留之前的进度。
并行发现架构

当本体绑定到多个数据源(Lakehouse 表 + Eventhouse 表)时,应并行发现架构,而不是顺序执行。启动单独的发现任务并发运行:

┌─────────────────────────────────────────────────────────────────┐
│  ORCHESTRATOR (this skill)                                       │
│                                                                   │
│  Step 0 → Resolve workspace, folder, lakehouse ID, eventhouse ID │
│                                                                   │
│  Step 1 → Fan out schema discovery (parallel):                   │
│     ┌──────────────────────────┐  ┌────────────────────────────┐ │
│     │ TASK A: Lakehouse schemas │  │ TASK B: Eventhouse schemas │ │
│     │ sqldw-consumption-cli     │  │ eventhouse-consumption-cli │ │
│     │ or INFORMATION_SCHEMA     │  │ or .show database schema   │ │
│     │ → all tables + columns    │  │ → all tables + columns     │ │
│     └──────────┬───────────────┘  └──────────┬─────────────────┘ │
│                │                              │                   │
│  Step 2 → Merge schemas ◄────────────────────┘                   │
│     - Match entity tables (lakehouse) to telemetry (eventhouse)  │
│     - Detect property name collisions across sources             │
│     - Detect property type conflicts across entity types         │
│     - Rename collisions (e.g., TenantId → TsTenantId)           │
│                                                                   │
│  Step 3 → Propose model → PREVIEW & CONFIRM                     │
│                                                                   │
│  Step 4 → Build full envelope → createItem (single call)         │
└─────────────────────────────────────────────────────────────────┘

如何分发任务(因 Agent 而异):

  • GitHub Copilot CLI / Claude Code:启动两个后台 task Agent——一个负责 Lakehouse(sqldw-consumption-cli 或 INFORMATION_SCHEMA.COLUMNS 查询),另一个负责 Eventhouse(.show database schema as json)。两者完成后读取结果。
  • 单线程环境:依次运行两个发现查询——每个查询只需调用一次,因此开销很小。

大多数编写错误会在合并步骤(步骤 2)中被发现——请对属性名称去重、统一各实体间的 valueType,并为与静态属性冲突的时间序列属性添加前缀。

详细步骤流程
Step 0 → Is the request specific? Are the entity types, keys, and lakehouse tables named?
         → NO  → Ask: "Which entity types? What is the key of each? Which lakehouse table binds to each?
                  Any timeseries properties? Any relationships and their link tables?"
                  STOP — do not proceed until the user answers.
         → YES → Continue.
Step 1 → Resolve IDs: workspace, folder, lakehouse, eventhouse     [COMMON-CLI.md]
Step 2 → Discover source schemas (parallel where possible):
           a. Lakehouse: invoke `sqldw-consumption-cli` or query INFORMATION_SCHEMA.COLUMNS
           b. Eventhouse: invoke `eventhouse-consumption-cli` or run `.show database schema as json`
Step 3 → Merge schemas: detect property name collisions + type conflicts; rename as needed
Step 4 → If ontology exists: getDefinition → decode parts              (capture current IDs)
         Else: plan `createItem` with the FULL definition (all parts in one call).
Step 5 → For each entity type:
           a. Generate/reuse 64-bit IDs for entity + properties
           b. Build EntityTypes/{id}/definition.json
           c. Build one or two DataBindings/{guid}.json files
Step 6 → For each relationship:
           a. Confirm both entity types exist in Step 5 output
           b. Generate/reuse relationship type ID
           c. Build RelationshipTypes/{id}/definition.json
           d. Build RelationshipTypes/{id}/Contextualizations/{guid}.json
Step 7 → Base64-encode all parts; assemble envelope
Step 8 → **PREVIEW & CONFIRM** — render proposal (greenfield) or change-set diff (brownfield)
         and obtain explicit `yes` from the user. See [preview-and-confirm.md](references/preview-and-confirm.md).
         Do not proceed on anything other than `yes`.
Step 9 → createItem OR updateDefinition (LRO)
Step 10 → Poll LRO until Succeeded; getDefinition; verify IDs and bindings; persist post-write snapshot for next-run diff
脚本生成工作流
Step 1 → Capture user intent (entity types, keys, properties, relationships, source tables)
Step 2 → Save intent as a YAML/JSON spec in the consumer's repo — single source of truth
Step 3 → Generate: (a) the ID map, (b) per-file JSON parts, (c) the composite envelope
Step 4 → **PREVIEW & CONFIRM** — render proposal/diff and require explicit `yes`
         (see [preview-and-confirm.md](references/preview-and-confirm.md)). The textual
         diff against the last-applied envelope snapshot feeds the brownfield change-set.
Step 5 → Apply via az rest --body @envelope.json (createItem or updateDefinition)
Step 6 → Poll LRO; on success, commit the envelope snapshot + ID map

示例

端到端的完整示例(创建空本体 → 添加实体类型 + 非时间序列绑定 → 添加关系类型 + 上下文化 → 添加时间序列属性 + Eventhouse 绑定)位于 examples.md。完整的 fetch-mutate-send bash 和 PowerShell 脚本位于 definition-script-templates.md。


Agent 集成说明

  • 此技能专注于编写。请搭配使用消费技能(例如 Fabric Graph 查询技能),以端到端验证本体。
  • 当本体绑定到多种源类型时,并行执行架构发现:
    • 启动后台 sqldw-consumption-cli 任务来发现 Lakehouse 架构(INFORMATION_SCHEMA.COLUMNS)——一次查询即可返回所有表和列。
    • 启动后台 eventhouse-consumption-cli 任务来发现 Eventhouse 架构(.show database schema as json)——一次调用即可返回所有表和列。
    • 两项任务并发运行。两者完成后合并结果,再构建本体模型。
  • 合并步骤至关重要——发现完成后,在 properties[] 和 timeseriesProperties[] 中对属性名称去重,统一不同实体类型中同名属性的 valueType,并在构建封装前为冲突项添加前缀。
  • 编排跨越 Ontology + Eventhouse + Lakehouse 的多步骤客户工作流时,应通过 Agent(例如 FabricDataEngineer)进行路由,而不是直接串联技能。
  • 可合理假设上游依赖已就绪:Lakehouse 表已存在,且包含用户描述的关键列。若未满足此条件,调用方应先调用 Lakehouse 编写技能。

评论

支持 Markdown