mcpField
D
dataflows-authoring-cli

dataflows-authoring-cli

github.com/microsoftデータ・データベース1.3k107 回インストール3 週間前に更新
リポジトリ

dataflows-authoring-cli について

Microsoft Fabric Dataflows Gen2をコマンドラインで作成・編集するスキルです。要件を確認したうえで、プレビューや検証、任意の更新までを支援します。

主な機能

  1. 01データフローの一貫した作成
  2. 02既存データフローの編集
  3. 03候補 M クエリのプレビュー
  4. 04出力先の管理
  5. 05定義とバインドの検証
  6. 06任意でデータフローを更新

活用シーン

  1. 01指定したソースと変換で Dataflow を作成
  2. 02既存データフローの定義を更新
  3. 03変更を保存する前にクエリ結果を確認
  4. 04クエリ結果を対応する出力先に書き込む

インストール

コマンドをコピーしてターミナルで実行します。

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

インストール後、Claude Code で/dataflows-authoring-cliを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
authoring-cli-quickref.md
authoring-script-templates.md
connection-management.md
connectors.md
m-language.md
mashup-preview.md
output-destinations.md
references/charts/
bar_chart.py
line_chart.py

詳細

更新チェック — セッションごとに1回(必須) このスキルをセッションで初めて使用するときは、作業を進める前に check-updates スキルを実行してください。

  • GitHub Copilot CLI / VS Code:check-updates スキルを呼び出します。
  • Claude Code / Cowork / Cursor / Windsurf / Codex:ローカルとリモートの package.json のバージョンを比較します。
  • このセッション中にすでにチェックを実行している場合はスキップしてください。

重要な注意事項

  1. ワークスペース名からワークスペースの詳細(IDを含む)を取得するには、すべてのワークスペースを一覧表示してから、JMESPath でフィルタリングします。
  2. ワークスペース ID、項目の種類、項目名から項目の詳細(IDを含む)を取得するには、そのワークスペース内の該当する種類の項目をすべて一覧表示してから、JMESPath でフィルタリングします。

変更前の要件確認ゲート(必須) 変更を行う前に、依頼された操作に対するユーザーの意図が十分に確認できていることを確かめてください。 作成または更新の依頼では、ソース、クエリ/スキーマと変換、出力先の動作、更新動作を確認します(出力先なし、または更新なしを明示的に選択する場合も含みます)。「レポート作成に必要な Dataflow を設定して」のような一般的な依頼の場合は、必要事項を確認する質問を構造化して行い、変更を行う前に停止してください。無関係なワークスペース項目から要件を推測したり、推測に基づいてソース、接続、Dataflow を作成したりしないでください。

dataflows-authoring-cli — CLI による Dataflows Gen2 の作成

目次

このスキル(SKILL.md)

セクション内容
ツールスタックaz + jq + base64 + curl
接続ワークスペース/データフロー ID の特定
エージェント型ワークフローまずここから。 A:エンドツーエンドで作成、B:既存のものを変更、C:プレビューのループ
必須事項/回避事項/推奨事項作成ルール
トラブルシューティング症状 → 対処方法の表
例実行可能な bash + PowerShell のレシピ
出力に関する期待事項応答の規約

リファレンス(references/ 内)

ファイル参照するタイミング
authoring-cli-quickref.md1 行のレシピ、ステータス列挙型、base64 ヘルパー、接続バインドの簡易パターン
authoring-script-templates.mdbash + PowerShell の完全なテンプレート、エンドツーエンドのスモークテスト、LRO ポーリングパターン
connection-management.md接続の一覧表示/作成/調査、supportedConnectionTypes、ClusterId の解決、ID 形式のチートシート
connectors.mdM 側のソースコネクタ:ライブ検証済み関数の一覧、Lakehouse の詳細なナビゲーション、Web.Page / Web.BrowserContents のゲートウェイ範囲、Html.Table / Csv.Document / Json.Document のパターン
m-language.mdDataflow Gen2 の M 言語セマンティクス:try のレコード形式、列変換におけるセル単位のエラーラップ、行とサブテーブルのコンテキストにおける each のスコープ、オプションのフィールドアクセス [?] / Record.FieldOrDefault、引用符付き識別子、サンドボックスで無効化されているシンボル(File.Contents)
mashup-preview.mdexecuteQuery の契約:ブートストラップ分岐、自動ラップルール、範囲のないプレビューを絶対に避けること
output-destinations.md出力先のパターン:Lakehouse Table、Lakehouse Files、Warehouse、ADX、Azure SQL。DataDestinations 注釈、非表示のクエリ、loadEnabled のルール、接続の制限

共通リファレンス(../../common/ 内)

ファイル参照するタイミング
COMMON-CLI.mdaz login、トークンの取得、az rest、ページネーション、LRO ポーリング、CLI の注意点。§ Fabric のワークスペースとアイテムの検索は必須です。
COMMON-CORE.mdFabric のトポロジ、環境 URL、認証、コア REST API の範囲
ITEM-DEFINITIONS-CORE.md定義エンベロープ、アイテム種別ごとのペイロード契約
DATAFLOWS-AUTHORING-CORE.md作成機能のマトリックス、3 部構成の定義、M の構造、接続モデル、ALM/Git の統合

関連スキル

スキル用途
dataflows-consumption-cli永続化されたクエリの実行、永続化を意図しないアドホックな読み取り専用の customMashupDocument、Arrow → CSV/pandas 変換、更新の状態/履歴。

ツールスタック

ツール役割インストール
az CLI主要ツール:認証(az login)、REST API 呼び出し(az rest)、トークンの取得。ほとんどの開発環境にプリインストールされています
jqJSON レスポンスと定義ペイロードの解析および操作。プリインストール済み、または簡単にインストールできます
base64REST API 用の定義パーツのエンコード/デコード。bash に組み込み済み/PowerShell の [Convert]::ToBase64String()
curl生の HTTP を制御する必要がある場合の az rest の代替手段。プリインストール済み
uuidgen新しいデータフロー定義の作成時(ワークフロー A)に、queryId と logicalId 用のクエリごと/プラットフォームごとの GUID を生成します。Linux/macOS ではプリインストール済み。Windows では PowerShell の [guid]::NewGuid().Guid を使用するか、WSL 経由で実行してください

エージェントの確認事項 — 初回操作の前に、az、jq、curl が使用可能であることを確認してください。uuidgen が必要なのはワークフロー A(作成)のみです。 インストールと認証の設定については、COMMON-CLI.md を参照してください。


接続

ワークスペース ID とデータフロー ID の確認

COMMON-CLI.md の Fabric のワークスペースとアイテムの検索に従ってください。

# List workspaces — find workspace ID by name
az rest --method get \
  --resource "https://api.fabric.microsoft.com" \
  --url "https://api.fabric.microsoft.com/v1/workspaces" \
  --query "value[?displayName=='MyWorkspace'].id" --output tsv

# List dataflows in workspace — find dataflow ID by name
WS_ID="<workspaceId>"
az rest --method get \
  --resource "https://api.fabric.microsoft.com" \
  --url "https://api.fabric.microsoft.com/v1/workspaces/$WS_ID/dataflows" \
  --query "value[?displayName=='MyDataflow'].id" --output tsv
再利用可能な接続変数
WS_ID="<workspaceId>"
DF_ID="<dataflowId>"
API="https://api.fabric.microsoft.com/v1"
RESOURCE="https://api.fabric.microsoft.com"

エージェントワークフロー

一般的な作成タスクを対象とする、3 つのワークフローがあります。

A. 新しいデータフローを最初から最後まで作成する

データフローがまだ存在しない場合に使用します。接続の検索または作成、データフローのシェルの作成、1 回の updateDefinition での M とバインディングの保存、検証、必要に応じた更新まで、成功までの一連の手順を扱います。

手順:

  1. 既存の接続を一覧表示し、connectionDetails.type と対象の URL/ホストで絞り込みます。一致するものがあれば再利用します(GET /v1/connections + JMESPath)。
  2. 一致するものがなければ、接続を作成します。 まず GET /v1/connections/supportedConnectionTypes を実行して、必須パラメーターとサポートされている資格情報の種類を確認し、次に POST /v1/connections を実行します(同期 201)。リクエスト本文の形式と資格情報スキーマについては、connection-management.md を参照してください。
  3. 複合バインディング用の ClusterId を解決します。 GET https://api.powerbi.com/v2.0/myorg/me/gatewayClusterDatasources を --query "value[?id=='$CONN_ID'] | [0].clusterId" とともに実行します。audience は --resource "https://analysis.windows.net/powerbi/api" です(末尾のスラッシュは付けません)。ID ごとのルートは、クラウド接続に対して PowerBIEntityNotFound を返します。新しく作成した接続が反映されるまで数秒かかることがあるため、空の場合は再試行してください。詳細は、connection-management.md § ClusterId の解決 を参照してください。
  4. データフローのシェルを作成します。 POST /v1/workspaces/{ws}/dataflows に {"displayName":"<displayName>"} を指定すると、同期 201 が返ります。作成時に definition フィールドを指定する必要はなく、次の手順で設定できます。代わりに、この作成 POST で完全な definition(3 つの部分すべて)を指定する場合は、この呼び出しが永続化の手段になります。概要では、永続化のパスとして updateDefinition ではなく POST /v1/workspaces/{ws}/dataflows と記載してください。
  5. M と接続バインディングを 1 回の呼び出しで保存します。 3 つの部分を指定して POST /v1/workspaces/{ws}/dataflows/{df}/updateDefinition?updateMetadata=true を実行します。mashup.pq(実際の Web.Contents/Sql.Database/…)、queryMetadata.json(connections[] を設定し、各 connectionId に {"ClusterId":"…","DatasourceId":"…"} を文字列化した値を指定)、および .platform です。通常は同期 200 が返ります。大きな本文では 202 と LRO の Location が返る場合があるため、どちらにも対応してください。
  6. バインディングが永続化されたことを確認します。 getDefinition を再度呼び出し、queryMetadata.json をデコードして、connections[] がそのまま保持されていることを確認します。確認には GET /items/{id}/connections を使用しないでください。このエンドポイントが反映するのは永続化された定義ではなく、更新によって具体化された状態であり、バインドが成功していても 0 を返します。AVOID を参照してください。 条件付きのプレビュー専用フォールバック: Power BI v2 の gatewayClusterDatasources が 401/403/Unauthorized を返す、または再試行しても ClusterId が確認できないために接続バインディングを進められない場合でも、データフローの作成前に処理を止めないでください。シェルを作成し、有効なソースバインディングが設定済みだと主張せずに、保存済みのクエリ定義を永続化します。保存済みの各クエリについて QueryName のみを指定して executeQuery を呼び出し、Arrow ストリームから正確な資格情報エラーまたはバインディングエラーを提示してください。グラフのデータを捏造せず、更新もしないでください。
  7. (推奨)出力を ASCII グラフでプレビューするか、ユーザーに確認します。 ユーザーに 「最初の更新の前に、データをグラフでプレビューしますか?」 と尋ねてください。この作成フローでは手順 5 ですでに定義が保存されているため、ここでのグラフプレビューは 更新によって具体化する前に行う、保存後の検証ゲート であり、保存前の手順ではありません。(最初の updateDefinition の前に候補の M を検証する場合(たとえば M を調整する場合や、資格情報が設定されたソースをブートストラップバインドして executeQuery から参照できるようにする場合)は、保存前の プレビュー主導の作成ループ を使用してください。グラフの描画方法は同じで、保存との順序だけが異なります。)承諾された場合は各エンティティに対して executeQuery を呼び出し、Arrow IPC ストリームを解析して、references/charts/line_chart.py/references/charts/bar_chart.py を使って折れ線グラフ(時系列)または横棒グラフ(カテゴリ)を描画し、続行前にユーザーに確認してください。詳細は、mashup-preview.md § ASCII グラフプレビュー を参照してください。辞退された場合は、手順 8 に直接進んでください。
  8. (任意)更新を開始してデータを具体化します。本文に {"executionData":{"executeOption":"ApplyChangesIfNeeded"}} を指定して POST .../jobs/instances?jobType=Refresh を実行します。定義を変更した後の最初の更新では、ApplyChangesIfNeeded が必須です。 指定しないと、Fabric は以前に適用された定義を更新します。LRO をポーリングし、status が Completed(更新の列挙値)、または Failed/Cancelled になるまで待ちます。
# Concise skeleton — full runnable bash is Example 1 below.
# PowerShell + LRO-polled variants: references/authoring-script-templates.md

WS_ID="<workspaceId>"; URL="<source-url>"
RES="https://api.fabric.microsoft.com"; API="$RES/v1"
PBI="https://analysis.windows.net/powerbi/api"

# 1. List existing & try reuse
CONN_ID=$(az rest --method get --resource "$RES" --url "$API/connections" \
  --query "value[?connectionDetails.type=='Web' && connectionDetails.path=='$URL'] | [0].id" -o tsv)

# 2. Create connection if missing — see connection-management.md for full body
# 3. List+filter for ClusterId
CLUSTER_ID=$(az rest --method get --resource "$PBI" \
  --url "https://api.powerbi.com/v2.0/myorg/me/gatewayClusterDatasources" \
  --query "value[?id=='$CONN_ID'] | [0].clusterId" -o tsv)

# 4. Empty dataflow shell — sync 201
SHELL_BODY=$(mktemp --suffix=.json 2>/dev/null || mktemp)
printf '{"displayName":"my-df"}' > "$SHELL_BODY"
DF_ID=$(az rest --method post --resource "$RES" \
  --url "$API/workspaces/$WS_ID/dataflows" \
  --headers "Content-Type=application/json" \
  --body "@$SHELL_BODY" --query id -o tsv)
rm -f "$SHELL_BODY"

# 5. One-shot updateDefinition with real M + connections[] (sync 200 typical)
#    Body assembly (mashup.pq + queryMetadata.json + .platform, base64-encoded;
#    queryMetadata.json.connections[].connectionId = composite ClusterId/DatasourceId):
#    see Example 1 below.

# 6. Verify via getDefinition (NOT GET /items/{id}/connections — see AVOID)
# 7. (optional) executeQuery — Workflow C
# 8. (optional) Refresh with executeOption=ApplyChangesIfNeeded — Example 2

一括処理と、バインド+保存の2段階処理。 ステップ4〜5は、1回の呼び出しで実行することも(デフォルト。HTTPの往復を1回分節約できます)、ブートストラップ用のバインドを行うupdateDefinitionに続けて、完全なMを指定したupdateDefinitionを実行する2段階に分けることもできます。どちらも有効です。PREFERを参照してください。

B. 既存のデータフローを変更する

データフローがすでに存在する場合に使用します。Discover → Formulate → Execute → Verifyの標準的なループです。データフローがまだ存在しない場合は、代わりにワークフローAを参照してください。

  1. Discover — ワークスペースとデータフローを一覧表示し、getDefinitionを実行します(mashup.pqとqueryMetadata.jsonをデコード)。GET /v1/connections/{id}を使って、すべてのconnections[]エントリを検証します。
  2. Formulate — Mを変更し、各パーツを再エンコードして、参照されているすべてのconnectionIdが呼び出し元の接続ストアに存在することを確認します。
  3. Execute — 3つのパーツすべてを指定してPOST .../updateDefinition?updateMetadata=trueを実行します(完全置換)。必要に応じて更新をトリガーします。
  4. Verify — getDefinitionを再度呼び出して変更を確認し、更新のLROをポーリングします。更新に失敗した場合は、修正可能なM/ソースの問題を特定するためのexecuteQueryによる切り分けを最大1回試みます。終端的な失敗、または再試行不可能な失敗(isRetriable: false、ワークスペース全体に及ぶUnknownException)の場合は、生のエラーを提示し、再トリガーせずに停止します。
# Concise skeleton — full templates: references/authoring-script-templates.md
# Acquire $TOKEN per common/COMMON-CLI.md § Token-in-Variable Pattern (resource = $RESOURCE).
RESOURCE="https://api.fabric.microsoft.com"; API="$RESOURCE/v1"

# 1. Discover — getDefinition (handles 200 sync and 202 + LRO via curl)
HDR=$(mktemp); BODY=$(mktemp)
CODE=$(curl -sS -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Length: 0" \
  "$API/workspaces/$WS_ID/dataflows/$DF_ID/getDefinition" \
  -D "$HDR" -o "$BODY" -w "%{http_code}")
if [ "$CODE" = "202" ]; then
  LOC=$(tr -d '\r' < "$HDR" | grep -i "^location:" | awk '{print $2}')
  RETRY=$(tr -d '\r' < "$HDR" | grep -i "^retry-after:" | awk '{print $2}'); RETRY=${RETRY:-5}
  while :; do
    sleep "$RETRY"
    OP=$(az rest --method get --resource "$RESOURCE" --url "$LOC")
    case "$(echo "$OP" | jq -r '.status // empty')" in
      Succeeded) RESULT=$(az rest --method get --resource "$RESOURCE" --url "${LOC%/}/result"); break ;;
      Failed|Cancelled) echo "ERROR: getDefinition $(echo "$OP" | jq -r '.status')" >&2; exit 1 ;;
    esac
  done
else
  RESULT=$(cat "$BODY")
fi
rm -f "$HDR" "$BODY"

# Validate bound connections (connectionId is a composite JSON string — iterate safely)
QUERY_META=$(echo "$RESULT" | jq -r '.definition.parts[] | select(.path=="queryMetadata.json") | .payload' | base64 -d)
echo "$QUERY_META" | jq -c '.connections[]?' | while IFS= read -r conn; do
  RAW=$(echo "$conn" | jq -r '.connectionId')
  DATASOURCE_ID=$(echo "$RAW" | jq -r '.DatasourceId? // empty' 2>/dev/null)
  [ -z "$DATASOURCE_ID" ] && DATASOURCE_ID="$RAW"
  # GET /v1/connections/$DATASOURCE_ID to confirm access
done

# 2-3. Formulate & Execute — see Example 3
# 4. Verify — trigger refresh via curl (az rest cannot capture Location header).
#    Full LRO polling: references/authoring-script-templates.md.
C. プレビュー主導の作成ループ(保存前のexecuteQuery — mashup-preview.mdを参照)

変更がPower Query M(新しいクエリ、編集したマッシュアップ、新しいソース、変更したパラメーター)に関わる場合は、保存する前に、候補のcustomMashupDocumentをデータフローのバインド済み接続に対してプレビューします。作成時に構文、スキーマ、資格情報のエラーを検出できます。順序に沿った全ステップ、ブートストラップ分岐、自動ラップのルール、無制限のプレビューを避けるための強い注意、ASCIIチャートのプレビュー、Apache Arrowの処理については、mashup-preview.md § プレビュー主導の作成ループを参照してください。

意図の使い分け。 このワークフローは、保存前の操作を対象としています。保存済みのクエリ(QueryNameのみ)を実行する場合、または保存する意図のないアドホックな読み取り専用のcustomMashupDocumentを実行する場合は、dataflows-consumption-cliを使用してください。mashup-preview.mdは、どちらの操作にも共通するAPIリファレンスです。

メタデータのみの編集(表示名、スケジュール、loadEnabledの切り替え)の場合、またはエージェントが明確なスキップ理由(ブートストラップ、コストが過大、ソースに副作用がある)を記録する場合に限り、プレビューを省略してください。

D. 出力先

データフローでクエリ結果を外部ストア(Lakehouse テーブル、Lakehouse ファイル、Warehouse、ADX、Azure SQL)に書き込む場合に使用します。DataDestinations アノテーションと非表示の出力先クエリを追加して、ワークフロー A を拡張します。完全な例を含むリファレンスは、output-destinations.md を参照してください。

主な要件:

  1. ソースクエリには、出力先クエリを名前で参照する [DataDestinations = {[...]}] アノテーションを含めます。
  2. 非表示の出力先クエリ(末尾に _DataDestination を付けます)では、null 安全な ?[Data]?(テーブル)または ?[Content]?(ファイル)演算子を使って、対象のストレージに移動します。
  3. queryMetadata.json では、出力先クエリの "loadEnabled": false を設定する必要があります。設定しないと更新に失敗します。概要には、パーツ名をそのまま使って記載してください(例:「queryMetadata.json の出力先クエリで loadEnabled: false を設定」)。
  4. API で作成したデータフローでは、既存のテーブルであっても、常に IsNewTarget = true を使用してください。
  5. 適切な接続をバインドします(Lakehouse:kind "Lakehouse"、Warehouse:kind "Warehouse"、ADX:kind "AzureDataExplorer"、Azure SQL:kind "Sql")。ID には ClusterId と DatasourceId の複合値を使用します。
  6. 初回の更新では、必ず ApplyChangesIfNeeded を使用してドラフトを公開し、アノテーションを調整します。
  7. すべてのソース列に型を指定します。 Any 型の列は、すべての出力先タイプで拒否されます。
  8. 記述する概要には、定義パーツ名を含めてください。 CLI のトランスクリプトでは長いコマンド本体が省略されるため、最終的な概要(シェルコマンドだけでなく、文章で記述した概要)には、3 つの定義パーツをそのままのパスで記載する必要があります。これにより、回答内にパーツ名が残ります(例:「updateDefinition で mashup.pq + queryMetadata.json + .platform を保存」)。queryMetadata.json を「クエリメタデータ」と略したり、内部フィールドの queriesMetadata を使ったりしないでください。

対応している出力先:

出力先接続の種類出力先クエリ関数備考
Lakehouse テーブルLakehouseLakehouse.Contents(...)パス:「Lakehouse」
Lakehouse ファイルLakehouseLakehouse.Contents(...)TypeSettings = [Kind = "File"]、?[Content]?
WarehouseWarehouseFabric.Warehouse(...)パス:「Warehouse」、スキーマ/項目のナビゲーション
Azure Data ExplorerAzureDataExplorerAzureDataExplorer.Contents(...)パスは接続と完全に一致させる必要があります(末尾のスラッシュも含む!)
Azure SQLSqlSql.Database(...)パス:「server;database」

最小限の手順: データフローを作成 → 接続を検索/作成 → ClusterId を解決 → OD アノテーションを含む定義を保存 → 確認 → 更新。

# Skeleton — full PowerShell recipe: references/output-destinations.md § Complete Example
WS_ID="<workspaceId>"; LH_ID="<lakehouseId>"; RES="https://api.fabric.microsoft.com"

# M pattern (two queries):
# 1. Source with [DataDestinations] annotation
# 2. Hidden _DataDestination query with ?[Data]? null-safe navigation
# queryMetadata: source loadEnabled=true, destination loadEnabled=false + isHidden=true
# Refresh: {"executionData":{"executeOption":"ApplyChangesIfNeeded"}}

注意点、ルール、トラブルシューティング

作成時の注意点については、DATAFLOWS-AUTHORING-CORE.md の「注意点とトラブルシューティング」を参照してください。 CLI 固有の問題については、COMMON-CLI.md の「注意点とトラブルシューティング(CLI 固有)」を参照してください。 接続の検出については、authoring-cli-quickref.md § 接続の検出と検証 を参照してください。

必ず行うこと
  • 新しいデータフローの初回更新の前に、すべてのエンティティのプレビューを提案する — シェルを作成し、updateDefinition(定義を永続化します)で接続をバインドした後、更新によって具体化する前にプレビューチャートを表示したいかどうかをユーザーに尋ねます。プレビュー駆動ループでは、プレビューは代わりに、永続化する updateDefinition の前に実行します。承諾された場合は、mashup-preview.md § ASCII チャートプレビューに従います。メタデータのみの編集(表示名、スケジュール)の場合、またはエージェントが明示的なスキップ理由を記録した場合にのみスキップします。
  • まず az login — すべての az rest 呼び出しはアクティブなセッションを使用します。セッションがない場合は 401 になります。
  • Fabric API には --resource "https://api.fabric.microsoft.com" を使用します。 Power BI v2(gatewayClusterDatasources)には、--resource "https://analysis.windows.net/powerbi/api" を末尾のスラッシュなしで使用します — スラッシュ付きの形式は AADSTS500011 invalid_resource で失敗します。
  • 3 つの定義パーツをすべて Base64 エンコードします — mashup.pq + queryMetadata.json + .platform、それぞれ payloadType: "InlineBase64" です。updateDefinition は完全な置換であり、1 つまたは 2 つのパーツのみを送信するとクエリが黙って破棄されます。
  • 同期レスポンスと非同期レスポンスの両方を処理します。 POST /dataflows、updateDefinition、getDefinition は通常は同期(200/201)を返しますが、大きなボディでは 202 + LRO Location を返すことがあります — 両方を処理してください。authoring-script-templates.md § Fabric LRO ポーリングパターンを参照してください。
  • queryMetadata.json で formatVersion: "202502" を設定し、displayName と一致するトップレベルの name を含めます — どちらかを省略すると、保存時の失敗や表示名の状態が古くなる原因になります。
  • loadEnabled はオプトアウトであり、オプトインではありません。 Fabric はデフォルトで、すべてのクエリをステージング Lakehouse に自動的に読み込みます。書き込みたくないヘルパークエリにのみ loadEnabled: false を設定します。注: loadEnabled: true も(デフォルトであるため)getDefinition を経由したラウンドトリップで queryMetadata.json から取り除かれます — 読み戻し時にこれが存在しないことはバグではありません。詳細: DATAFLOWS-AUTHORING-CORE.md § loadEnabled のセマンティクス。
  • コンテキストごとに正しい ID 形式を使用します。 REST の /v1/connections 操作は connection.id のプレーンな GUID を受け取ります。queryMetadata.json の connections[].connectionId は文字列化された複合 {"ClusterId":"…","DatasourceId":"…"} を受け取ります。connection-management.md § 接続 ID 形式チートシートを参照してください。
  • ClusterId は list+filter で解決します。 GET .../gatewayClusterDatasources を value[?id=='$CONN_ID'] でフィルターします。ID ごとのルートは、クラウド接続では PowerBIEntityNotFound を返します。新しく作成された接続には 5〜15 秒のリトライが必要な場合があります。connection-management.md § ClusterId の解決を参照してください。
  • executeQuery のボディはトップレベルの QueryName フィールドを使用します(PascalCase が正式ですが、フィールド名自体はワイヤー上では大文字と小文字を区別しません — 小文字の queryName も評価されます)。値は、永続化された M または指定された customMashupDocument の shared メンバーを指定する必要があります。{"queries":[…]} 配列形式は常に DataflowExecuteQueryError: Invalid query name で失敗します。誤ったクエリ名は QueryNotFound を返します。完全なコントラクト: mashup-preview.md § リクエストボディ。
  • 正確で、大文字と小文字を区別する API 名を使用します。 エンドポイントは executeQuery(単数形、executeQueries は決して使いません)であり、リクエストボディのフィールドは customMashupDocument(mashupDocument は決して使わず、base64 エンコードも決してせず — プレーンな UTF-8 の M 文字列です)です。同じ M ボディが、customMashupDocument として参照される保存済みの mashup.pq パーツになります。用語表: mashup-preview.md § 用語。
  • updateDefinition 後の最初の更新では、必ず executeOption: "ApplyChangesIfNeeded" を使用する必要があります。 ボディ: {"executionData":{"executeOption":"ApplyChangesIfNeeded"}}。これがないと、Fabric は以前に適用された定義を更新します。
  • 終端の更新失敗は停止条件として扱います — デバッグループにしないでください。 更新/LRO ジョブが終端の Failed/Cancelled に達した場合、またはバックエンドエラーが isRetriable: false(あるいはワークスペース全体の UnknownException)を伴う場合、生のエラーをそのまま報告し、停止します。これらはエージェントがリトライしても修正できないバックエンド/インフラの結果です — 更新を再トリガーしたり、ポーリングを続けたり、拡張調査を開始したりしないでください。せいぜい、修正可能な M/ソースの原因を特定するために 1 回だけ executeQuery による切り分けを試みてください。それで定義側の問題が明らかにならなければ、終了してエラーを提示します。
  • POST /v1/connections の前に GET /v1/connections/supportedConnectionTypes を呼び出します -- パラメーター名や資格情報の種類を決して推測しないでください。これらはコネクタ、テナント、時期によって異なります。ユーザー向けにコネクタの必須パラメーターや credentialType のセットを要約する場合、正確で大文字と小文字を区別するエンドポイントパス GET /v1/connections/supportedConnectionTypes を使用します。これは純粋な参照(「コネクタ X はどのパラメーター/credentialType をサポートしていますか?」)の場合にも当てはまります。テナントに対して実際の GET /v1/connections/supportedConnectionTypes を実行してください。同梱の connection-management.md リファレンスはレスポンスの形状を示しますが、コネクタと時期によって異なる、テナント固有で大文字と小文字を区別する値の代わりにはなりません。
  • 更新の前に参照されている接続を検証します。 queryMetadata.json 内の各 connectionId について、GET /v1/connections/{id}(複合から抽出したプレーンな GUID)を実行します。更新時の不可解な EntityUserFailure は、多くの場合、接続の欠落またはアクセス不能です。connection-management.mdを参照してください。
  • 資格情報を使用する M をプレビューする前に、接続をブートストラップバインドします。 最初の作成ペイロード内の connections[] 配列は、まだ executeQuery からは見えません。まず少なくとも 1 回 updateDefinition を通じて永続化してください。詳細: mashup-preview.md § ブートストラップ分岐。
  • customMashupDocument には完全な section Section1; ... ドキュメントを送信します — executeQuery は生の式を自動的にラップしません。mashup-preview.md § customMashupDocument 形式を参照してください。
  • updateDefinition の前に executeQuery で候補の M をプレビューします — 変更がメタデータのみの場合、またはエージェントが明示的なスキップ理由を記録した場合を除きます。プレビューの成功は「M が評価される」ものとして扱い、次の更新を実際の可否判断として扱います。
  • JSON ボディはインラインではなく --body "@<file>" で渡します。 $env:TEMP\<name>.json(PowerShell、[IO.File]::WriteAllText による UTF-8 BOM なし)または /tmp/<name>.json(bash)に書き込みます。インラインの --body "<json>" は bash では脆弱で、Windows では cmd.exe の引数パーサーが埋め込まれた引用符を壊すため動作しません。authoring-script-templates.md § PowerShell — 定義付きデータフローの作成を参照してください。
  • 無人更新には WorkspaceIdentity / ServicePrincipal 資格情報を優先します。 OAuth2 + singleSignOnType: None は対話的な executeQuery では機能しますが、サービスコンテキストの更新ではテナントの条件付きアクセスの下で脆弱です。サポートされている種類は supportedConnectionTypes で確認してください。
避けるべきこと
  • ユーザーにプレビューを提示せず、新しいデータフローを具体化すること(初回の更新) — M コードを読むだけでは、ユーザーはその内容が意図と一致しているか検証できません。初回の更新前(およびプレビューを使った反復作業では、永続化する updateDefinition の前)に、各エンティティの出力を ASCII チャートでプレビューすることを必ず提案してください。ユーザーは断ってもかまいませんが、提案は必ず行ってください。
  • definition に format プロパティを追加すること — Items API では parts[] のみを使用します。"format": "json" を指定すると 400 InvalidDefinitionFormat が返されます。
  • ワークスペースやデータフローの GUID をハードコードすること — REST API で取得してください(Connection セクションを参照)。
  • 新たにバインドしたデータフローの検証に GET /v1/workspaces/{ws}/items/{itemId}/connections を使うこと。 この API が反映するのは永続化された定義ではなく、更新によって具体化された状態であり、バインドに成功した後は 0 件を返します。getDefinition を使い、queryMetadata.json.connections[] をデコードして検証してください。
  • updateDefinition / POST /dataflows は常に LRO だと決めつけること。 通常の応答は同期型(200/201)です。上記の必須事項を参照し、両方の形式に対応してください。
  • 末尾にスラッシュを付けて PBI v2 トークンをリクエストすること(--resource "https://analysis.windows.net/powerbi/api/")— AADSTS500011 invalid_resource エラーになります。スラッシュを付けない形式を使ってください。
  • クラウド接続に対して gatewayClusterDatasources/{id} を ID 指定で使うこと — PowerBIEntityNotFound が返されます。上記の必須事項に従い、一覧取得してからフィルタリングしてください。
  • executeQuery のリクエストボディに {"queries":[…]} 配列形式を使うこと — 内部の大文字・小文字に関係なく、常に 400 DataflowExecuteQueryError: Invalid query name が返されます。トップレベルに QueryName(または queryName。フィールド名の大文字・小文字は区別されません)を指定してください。1 回の呼び出しにつき、クエリは 1 つだけ指定してください。
  • getDefinition に GET を使うこと — POST エンドポイントです。GET では 405 が返されます。
  • 操作 URL を手動で組み立てること — 202 応答の Location ヘッダーに従ってください。
  • displayName の値を重複させること — 重複は拒否されませんが、混乱の原因になります。
  • 表示名で接続をバインドすること — 接続 ID が正しい情報源です。名前は変更される可能性があります。
  • すべての接続にすべてのユーザーがアクセスできると思い込むこと。 可視性は呼び出し元ごとです。アクセス権のない呼び出し元に対する GET /v1/connections/{id} は 403/404 を返すことがあります。GET /v1/connections の結果が空でも、接続が存在しない証拠にはなりません。
  • supportedConnectionTypes を含めずに接続リクエストボディを手作業で作ること — 推測で作成すると 400 InvalidConnectionDetails / 400 InvalidCredentialDetails が返されます。
  • 生成した例やコミットするスクリプトに認証情報を平文で記載すること — 認証情報の値を平文で表示したり、コミットしたりしないでください。生成する接続ボディには passwordReference / keyReference / tokenReference / servicePrincipalSecretReference だけを記載してください。
  • オンプレミスゲートウェイの接続ボディを平文でテンプレート化すること — OnPremisesGateway では、ゲートウェイメンバーごとに RSA で暗号化した認証情報が必要です。
  • 公開済みの単一ソースのデータフローを、その場で複数ソースに変換すること — バインドの状態に不整合が生じます。新しく作成してから、古いものを廃止してください。
  • プレビューしていない候補の M を updateDefinition で永続化すること — executeQuery は、updateDefinition の後に更新してデバッグする方法より大幅に高速です。mashup-preview.md を参照してください。
  • 本番規模のデータソースに対して上限のないプレビューを行うこと — executeQuery は評価済みデータセットの全件を返します。プレビュー専用ドキュメントに Table.FirstN / TOP N / 日付述語を追加し、保存前に削除してください。mashup-preview.md § Hard avoid を参照してください。
  • executeQuery と EvaluateQuery を混同すること。 EvaluateQuery には先行する正常な更新が必要ですが、customMashupDocument を使う executeQuery には必要ありません。作成時のプレビューループには executeQuery を使ってください。
  • Windows/PowerShell でインラインの --body を使うこと — cmd.exe が引用符を壊すため、必ず --body "@$env:TEMP\<name>.json" を使ってください。
推奨事項
  • ブートストラップ用のバインドと保存を個別に行うより、実際の M と connections[] を含むワンショットの updateDefinition を使用します。HTTP の往復を 1 回分省け、機能的にはどちらも同等です。説明を目的とする手順や、ブートストラップ時の M を本番用の M と異なるものにする場合は、2 段階の形式を使用します(例:mashup-preview.md のブートストラップブランチ)。
  • 生の curl より az rest を使用します。トークンの取得と更新が自動で処理されます。レスポンスヘッダー(例:202 LRO の Location)を取得する必要がある場合に限り、curl に切り替えます。az rest では取得できません。
  • updateDefinition の前に getDefinition を実行します。読み取り、変更、書き込みの手順により、意図しないデータ損失を防げます。updateDefinition は全体を置き換えます。
  • updateDefinition に ?updateMetadata=true を指定します。.platform の変更(表示名)が確実に適用されます。
  • JSON の操作には jq を使用します。定義ペイロードをプログラムで構築できます。
  • ジョブ実行時のパラメーターの種類には "Automatic" を指定します。エンジンが定義から種類を推測できるようになります。
  • スクリプトの再利用には環境変数(WS_ID、DF_ID、API、RESOURCE)を使用します。
  • 接続の検証はまとめて行います。更新前に queryMetadata.json connections[] をループ処理し、GET /v1/connections/{id} を実行します。任意で POST /v1/connections/{id}/testConnection を実行し、更新された資格情報を検出します。
  • 新しいデータフローを確定する前に、プレビューグラフを提示します。サンプルデータを ASCII グラフとして表示し、ユーザーが出力の形状と値を検証できるようにします。
トラブルシューティング
症状対処方法
401 Unauthorizedaz login が有効であることを確認し、--resource "https://api.fabric.microsoft.com"(または PBI v2 の場合は https://analysis.windows.net/powerbi/api 末尾にスラッシュを付けない)を確認してください。
getDefinition で 405 Method Not AllowedGET ではなく POST を使用してください。
updateDefinition でクエリが黙って削除される3 つすべてのパーツ(mashup.pq、queryMetadata.json、.platform)を送信してください。
executeQuery → 400 DataflowExecuteQueryError: Invalid query nameリクエストボディで {"queries":[…]} 配列形式を使用すると、必ず失敗します。トップレベルの {"QueryName":"<shared>"} に切り替えてください(PascalCase が正式な形式です。フィールド名の大文字と小文字は通信時に区別されません)。
executeQuery → 400 DataflowExecuteQueryError: ErrorCode: QueryNotFoundQueryName の値が、永続化された M または指定された customMashupDocument のどの shared メンバーとも一致していません。getDefinition → mashup.pq をデコードしてクエリを一覧表示してください。
GET /items/{id}/connections がバインド成功後に 0 を返すこのエンドポイントが返すのは定義ではなく、更新によって反映された状態です。getDefinition → queryMetadata.json.connections[] をデコードして確認してください。
gatewayClusterDatasources/{id} から ClusterId を取得すると 404 / PowerBIEntityNotFound が返るID 指定のルートではクラウド接続を解決できません。一覧取得とフィルタリングを使用してください:GET .../gatewayClusterDatasources --query "value[?id=='$CONN_ID'] | [0].clusterId"。audience は https://analysis.windows.net/powerbi/api(末尾にスラッシュなし)です。新規作成した接続が反映されるまで 5~15 秒かかることがあります。再試行してください。connection-management.md § Resolving ClusterId を参照してください。
updateDefinition 後の初回実行で更新が失敗する(古いデータ、変更の欠落)定義を変更した後の初回更新では、リクエストボディに {"executionData":{"executeOption":"ApplyChangesIfNeeded"}} を含める必要があります。
更新時に "Connection not found" が発生するqueryMetadata.json から複合形式の connectionId を抽出し、DatasourceId を解析して、GET /v1/connections/{id} で確認してください。
updateDefinition 後に connections[] がないバインドのないスナップショットから queryMetadata.json が読み取り・変更・書き込みによって再構築されました。更新前に再度バインドして updateDefinition を実行してください。
接続の作成とバインド後に、更新で "connection not found" が報告されるqueryMetadata.json の ID 形式が誤っています。REST の id は GUID のみですが、connectionId は {"ClusterId":"…","DatasourceId":"…"} を文字列化したものです。
formatVersion の不一致エラーqueryMetadata.json で formatVersion: "202502" を設定してください。
高速コピーが有効にならないmashup.pq の section の前に [StagingDefinition = [Kind = "FastCopy"]] を追加してください。
LRO のポーリングで 404 が返るLocation ヘッダーの URL を使用してください。操作 URL を手動で組み立てないでください。
429 Too Many RequestsRetry-After に従い、指数バックオフを行ってください。
Base64 のデコード結果が文字化けする末尾の改行を削除し、base64 -w0(Linux)を使用してください。
Windows でインラインの --body "<json>" が 400 または空のボディを返すaz.exe の起動時に cmd.exe の引数パーサーが引用符を壊します。$env:TEMP\body.json(UTF-8、BOM なし)に書き込み、--body "@$env:TEMP\body.json" を渡してください。authoring-script-templates.md § PowerShell — Create Dataflow with Definition を参照してください。
EntityUserFailure / "Something went wrong" が詳細なしで表示され、更新に失敗する(1) 作成後に updateDefinition が呼び出されたことを確認してください。(2) 資格情報の種類を確認してください。OAuth2 と singleSignOnType: None の組み合わせは、テナントの条件付きアクセスが有効な環境で、無人更新に失敗することがよくあります。WorkspaceIdentity または ServicePrincipal を推奨します。(3) データフローに対して executeQuery を実行し、M とソースを切り分けてください。(4) GET https://api.powerbi.com/v1.0/myorg/groups/{ws}/dataflows/{df}/transactions(PBI v1.0)で、エンティティごとの詳細なエラーが返ることがあります。

例

プラットフォームに関する注意 — 以下の例は bash 用です。Windows/PowerShell では、bash のパターン(MASHUP='...' のヒアドキュメント、echo -n | base64 -w0、tr -d '\r' | grep -i location | awk)を使うと、エスケープ処理で問題が発生しやすく、更新パターンも不安定になります。特に手間のかかる Create と Refresh の例には、PowerShell 用のバリエーションをリンクしています。PowerShell の完全なテンプレート(Create、Refresh、Validate Connections、Bind Connection、Create Cloud Connection)については、authoring-script-templates.md § PowerShell を参照してください。PowerShell では、--body "@$env:TEMP\body.json" を使い、Out-File(Windows PowerShell 5.1 では UTF-8 BOM が書き込まれ、az.exe の本文解析に失敗するため)やインラインの --body "{...}"(cmd.exe によって内容が改変されるため)を避けて、[IO.File]::WriteAllText($path, $body, [System.Text.UTF8Encoding]::new($false)) で本文を書き込むことをお勧めします。

例 1:Dataflow Gen2 をゼロから作成する

プロンプト:「Web コネクタを使って公開 CSV を読み込む新しい Dataflow Gen2 を作成し、検証してください。」

エージェントの応答 — ワークフロー A の実行可能な bash 実装です。PowerShell 用のバリエーション:authoring-script-templates.md § End-to-End Smoke Test。

# Prereqs: az login, jq, base64, uuidgen. Workspace must support Dataflow Gen2.
WS_ID="<workspaceId>"
DF_NAME="my-titanic-df"
CONN_NAME="my-titanic-web-conn"
URL="https://raw.githubusercontent.com/datasciencedojo/datasets/master/titanic.csv"
RES="https://api.fabric.microsoft.com"; API="$RES/v1"
PBI="https://analysis.windows.net/powerbi/api"   # NO trailing slash

# Step 1: List existing connections, try to reuse by name.
CONN_ID=$(az rest --method get --resource "$RES" --url "$API/connections" \
  --query "value[?displayName=='$CONN_NAME'] | [0].id" -o tsv)

# Step 2: Create if missing (Web + Anonymous; see connection-management.md for other shapes).
if [ -z "$CONN_ID" ] || [ "$CONN_ID" = "null" ]; then
  BODY_FILE=$(mktemp --suffix=.json 2>/dev/null || mktemp)  # GNU + BSD/macOS compatible
  cat > "$BODY_FILE" <<EOF
{
  "displayName": "$CONN_NAME",
  "connectivityType": "ShareableCloud",
  "connectionDetails": {
    "type": "Web", "creationMethod": "Web",
    "parameters": [{"name": "url", "dataType": "Text", "value": "$URL"}]
  },
  "privacyLevel": "Organizational",
  "credentialDetails": {
    "singleSignOnType": "None", "connectionEncryption": "NotEncrypted",
    "skipTestConnection": false,
    "credentials": {"credentialType": "Anonymous"}
  }
}
EOF
  CONN_ID=$(az rest --method post --resource "$RES" --url "$API/connections" \
    --headers "Content-Type=application/json" --body "@$BODY_FILE" --query id -o tsv)
  rm -f "$BODY_FILE"
fi

# Step 3: Resolve ClusterId via list+filter; retry — PBI v2 lags by 5-15s on new conns.
for i in 1 2 3 4 5 6 7 8; do
  CLUSTER_ID=$(az rest --method get --resource "$PBI" \
    --url "https://api.powerbi.com/v2.0/myorg/me/gatewayClusterDatasources" \
    --query "value[?id=='$CONN_ID'] | [0].clusterId" -o tsv 2>/dev/null)
  [ -n "$CLUSTER_ID" ] && [ "$CLUSTER_ID" != "null" ] && break
  sleep $((i*3))
done
# Fail-fast: an empty ClusterId silently corrupts the composite connectionId and the
# resulting updateDefinition / refresh failures are hard to debug. Stop here instead.
if [ -z "$CLUSTER_ID" ] || [ "$CLUSTER_ID" = "null" ]; then
  echo "FAIL: ClusterId not resolved for $CONN_ID after retries. Verify the connection is visible at PBI v2 (api.powerbi.com/v2.0/myorg/me/gatewayClusterDatasources)." >&2
  exit 1
fi

# Step 4: Create empty dataflow shell (sync 201).
SHELL_BODY=$(mktemp --suffix=.json 2>/dev/null || mktemp)
printf '{"displayName":"%s"}' "$DF_NAME" > "$SHELL_BODY"
DF_ID=$(az rest --method post --resource "$RES" \
  --url "$API/workspaces/$WS_ID/dataflows" \
  --headers "Content-Type=application/json" \
  --body "@$SHELL_BODY" --query id -o tsv)
rm -f "$SHELL_BODY"

# Step 5: One-shot updateDefinition — real M + composite-bound connections[] + .platform.
MASHUP='section Section1;
shared Titanic = let
    Source = Csv.Document(Web.Contents("'"$URL"'"), [Delimiter=",", Encoding=65001, QuoteStyle=QuoteStyle.Csv]),
    Headers = Table.PromoteHeaders(Source, [PromoteAllScalars=true])
in Headers;'

COMPOSITE_ID="{\"ClusterId\":\"$CLUSTER_ID\",\"DatasourceId\":\"$CONN_ID\"}"
QUERY_META=$(jq -n --arg name "$DF_NAME" --arg cid "$COMPOSITE_ID" --arg url "$URL" --arg qid "$(uuidgen)" '{
  formatVersion: "202502",
  name: $name,
  queriesMetadata: { Titanic: { queryId: $qid, queryName: "Titanic" } },
  connections: [ { connectionId: $cid, kind: "Web", path: $url } ]
}')
PLATFORM=$(jq -n --arg name "$DF_NAME" --arg lid "$(uuidgen)" '{
  "$schema": "https://developer.microsoft.com/json-schemas/fabric/gitIntegration/platformProperties/2.0.0/schema.json",
  metadata: { type: "Dataflow", displayName: $name },
  config: { version: "2.0", logicalId: $lid }
}')

MASHUP_B64=$(echo -n "$MASHUP" | base64 -w0)
META_B64=$(echo -n "$QUERY_META" | base64 -w0)
PLAT_B64=$(echo -n "$PLATFORM" | base64 -w0)

BODY_FILE=$(mktemp --suffix=.json 2>/dev/null || mktemp)  # GNU + BSD/macOS compatible
cat > "$BODY_FILE" <<EOF
{"definition":{"parts":[
  {"path":"mashup.pq",          "payload":"${MASHUP_B64}", "payloadType":"InlineBase64"},
  {"path":"queryMetadata.json", "payload":"${META_B64}",   "payloadType":"InlineBase64"},
  {"path":".platform",          "payload":"${PLAT_B64}",   "payloadType":"InlineBase64"}
]}}
EOF
az rest --method post --resource "$RES" \
  --url "$API/workspaces/$WS_ID/dataflows/$DF_ID/updateDefinition?updateMetadata=true" \
  --headers "Content-Type=application/json" --body "@$BODY_FILE"
rm -f "$BODY_FILE"

# Step 6: Verify connections[] persisted via getDefinition (NOT /items/{id}/connections).
# Assumes the sync 200 fast-path (typical, ~1s). If the call ever returns 202 LRO,
# az rest can't expose the Location header — switch to the curl + poll pattern from
# Example 3 / authoring-script-templates.md and decode the polled 200 body instead.
PERSISTED=$(az rest --method post --resource "$RES" \
  --url "$API/workspaces/$WS_ID/dataflows/$DF_ID/getDefinition" \
  --headers "Content-Length=0" \
  | jq -r '.definition.parts[] | select(.path=="queryMetadata.json") | .payload' | base64 -d \
  | jq -r '.connections | length')
[ "${PERSISTED:-0}" -gt 0 ] && echo "OK: connections[] persisted." || { echo "FAIL: bind missing (or getDefinition returned a 202 LRO body — see note above)." >&2; exit 1; }

# Step 7 (optional): Validate the M evaluates — top-level QueryName, PascalCase.
EQ_BODY=$(mktemp --suffix=.json 2>/dev/null || mktemp)
printf '{"QueryName":"Titanic"}' > "$EQ_BODY"
az rest --method post --resource "$RES" \
  --url "$API/workspaces/$WS_ID/dataflows/$DF_ID/executeQuery" \
  --headers "Content-Type=application/json" \
  --body "@$EQ_BODY" --output-file /tmp/titanic.arrow
rm -f "$EQ_BODY"
# Apache Arrow stream — embedded {"Error":"..."} means failure even on HTTP 200.
grep -q '"Error":"' /tmp/titanic.arrow && { echo "executeQuery surfaced an error." >&2; exit 1; }

# Step 8 (optional): Trigger refresh with ApplyChangesIfNeeded on first run — see Example 2.
例 2:更新ジョブをトリガーする

プロンプト:「このデータフローの更新をトリガーし、完了するまでポーリングしてください。」

エージェントの応答:

# Trigger refresh (returns 202 + Location header for polling).
# jobType MUST be "Refresh"; "Pipeline" returns 400 InvalidJobType.
# On the first refresh after any updateDefinition, body MUST include executeOption=ApplyChangesIfNeeded
# (otherwise Fabric refreshes the previously-applied definition).
# Acquire $TOKEN per common/COMMON-CLI.md § Token-in-Variable Pattern (resource = https://api.fabric.microsoft.com).
LOCATION=$(curl -sS -X POST \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  --data '{"executionData":{"executeOption":"ApplyChangesIfNeeded"}}' \
  "https://api.fabric.microsoft.com/v1/workspaces/${WS_ID}/dataflows/${DF_ID}/jobs/instances?jobType=Refresh" \
  -o /dev/null -D - | tr -d '\r' | grep -i "^location:" | awk '{print $2}')

# Poll while the status is non-terminal. Fabric refresh job status enum:
#   NotStarted / InProgress   -> non-terminal, keep polling
#   Completed                 -> success
#   Failed / Cancelled        -> terminal backend outcome (fatal-stop)
#   Deduped                   -> another refresh is already running; this trigger was skipped (NOT success)
# Treat ONLY NotStarted/InProgress as non-terminal and break on anything else, so a newly-added
# terminal status surfaces immediately instead of waiting out MAX_POLLS (the contract notes more
# status values may be added over time). MAX_POLLS bounds the wait if the job never terminates.
ATTEMPT=0; MAX_POLLS="${MAX_POLLS:-60}"
while [ "$ATTEMPT" -lt "$MAX_POLLS" ]; do
  STATUS=$(az rest --method get --url "$LOCATION" \
    --resource "https://api.fabric.microsoft.com" --query "status" -o tsv)
  echo "Status: $STATUS"
  case "$STATUS" in NotStarted|InProgress) ;; *) break ;; esac
  sleep 10; ATTEMPT=$((ATTEMPT + 1))
done
case "$STATUS" in
  Completed) : ;;  # success (exit 0)
  Deduped)
    # Concurrency, not success: another refresh is already running and this trigger was skipped.
    # Monitor the in-flight instance instead of re-triggering. Exit non-zero so automation does not
    # mistake a skipped trigger for a completed refresh.
    echo "Refresh deduplicated — another instance is already running; monitor that instance instead of re-triggering."
    exit 2 ;;
  NotStarted|InProgress)
    # Max-poll bound reached before any terminal status — a polling timeout, NOT a terminal outcome.
    # Surface the raw job instance and stop; do not assume success.
    echo "Polling stopped after ${MAX_POLLS} attempts with non-terminal status '$STATUS' (max-poll timeout, not a terminal outcome)."
    az rest --method get --url "$LOCATION" --resource "https://api.fabric.microsoft.com"
    exit 1 ;;
  *)  # Failed / Cancelled (or any other terminal status): a terminal backend outcome — not something
      # to debug-loop. Surface the job's raw error (the job-instance body's .failureReason, an
      # ErrorResponse with .errorCode / .isRetriable / .message) and STOP. Do NOT re-trigger or keep
      # polling when .failureReason.isRetriable=false or the error is workspace-wide.
      az rest --method get --url "$LOCATION" --resource "https://api.fabric.microsoft.com"
      exit 1 ;;
esac

PowerShell 用のバリエーション(Invoke-WebRequest はレスポンスヘッダーをネイティブに公開するため、tr | grep | awk のパイプを使わずに済みます):

# Notes:
# - $Resp.Headers["Location"] returns string or string[] depending on PS version — never
#   use .Location[0] (returns first character on Windows PS 5.1 plain-string case).
# - Wrap Invoke-WebRequest in try/catch on 5.1 (-SkipHttpErrorCheck is PS 7+).
# - Fabric refresh job status enum: NotStarted / InProgress (non-terminal); Completed (success);
#   Failed / Cancelled (fatal); Deduped (another refresh already running — NOT success). Treat only
#   NotStarted/InProgress as non-terminal and break on anything else, bounded by a max-poll count, so
#   a newly-added terminal status surfaces immediately instead of waiting out $MaxPolls.
#   This is distinct from the LRO operation enum (Running / Succeeded / Failed / Cancelled).
#   Refresh "success" = "Completed", not "Succeeded".
# Acquire $Token per common/COMMON-CLI.md § Token-in-Variable Pattern (resource = https://api.fabric.microsoft.com).
try {
  $Resp = Invoke-WebRequest -Method POST -UseBasicParsing `
    -Uri "https://api.fabric.microsoft.com/v1/workspaces/$WS_ID/dataflows/$DF_ID/jobs/instances?jobType=Refresh" `
    -Headers @{ Authorization = "Bearer $Token"; "Content-Type" = "application/json" } `
    -Body '{"executionData":{"executeOption":"ApplyChangesIfNeeded"}}'
} catch {
  Write-Error "Refresh trigger failed: $($_.Exception.Message)"; exit 1
}
$Location = $Resp.Headers["Location"]
if ($Location -is [array]) { $Location = $Location[0] }

$Attempt = 0; $MaxPolls = 60
do {
  $Status = az rest --method get --url $Location `
    --resource "https://api.fabric.microsoft.com" --query "status" -o tsv
  Write-Host "Status: $Status"
  if ($Status -notin 'NotStarted','InProgress') { break }
  Start-Sleep -Seconds 10; $Attempt++
} while ($Attempt -lt $MaxPolls)
if ($Status -in 'NotStarted','InProgress') {
  # Max-poll bound reached before any terminal status — a polling timeout, NOT a terminal outcome.
  Write-Host "Polling stopped after $MaxPolls attempts with non-terminal status '$Status' (max-poll timeout, not a terminal outcome)."
  az rest --method get --url $Location --resource "https://api.fabric.microsoft.com"
  exit 1
}
switch ($Status) {
  'Completed' { }  # success (exit 0)
  'Deduped' {
    # Concurrency, not success: another refresh is already running and this trigger was skipped.
    # Exit non-zero so callers don't treat a skipped trigger as a completed refresh.
    Write-Host "Refresh deduplicated — another instance is already running; monitor that instance instead of re-triggering."
    exit 2
  }
  default {
    # Failed / Cancelled (or any other terminal status): a terminal backend outcome — surface the job's
    # raw error (the job-instance body's .failureReason: .errorCode / .isRetriable / .message) and STOP;
    # do not re-trigger or debug-loop when failureReason.isRetriable=false or the error is workspace-wide.
    az rest --method get --url $Location --resource "https://api.fabric.microsoft.com"
    Write-Error "Refresh terminated '$Status' (not Completed)"; exit 1
  }
}
例 3:既存のデータフローの定義を変更する

プロンプト:「既存のデータフローのマッシュアップを、変更したクエリで更新してください。」

エージェントの応答 — 読み取り、変更、書き込みのループです。通常、getDefinition は同期的に 200 を返します。このテンプレートは、202 と LRO の分岐にも対応しています。

RESOURCE="https://api.fabric.microsoft.com"
# Acquire $TOKEN per common/COMMON-CLI.md § Token-in-Variable Pattern (resource = $RESOURCE).

# 1. Read current definition (sync 200 or 202 LRO — handle both).
HDR=$(mktemp); BODY=$(mktemp)
CODE=$(curl -sS -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Length: 0" \
  "$RESOURCE/v1/workspaces/${WS_ID}/dataflows/${DF_ID}/getDefinition" \
  -D "$HDR" -o "$BODY" -w "%{http_code}")
if [ "$CODE" = "202" ]; then
  LOC=$(tr -d '\r' < "$HDR" | grep -i "^location:" | awk '{print $2}')
  RETRY=$(tr -d '\r' < "$HDR" | grep -i "^retry-after:" | awk '{print $2}'); RETRY=${RETRY:-5}
  while :; do
    sleep "$RETRY"
    OP=$(az rest --method get --resource "$RESOURCE" --url "$LOC")
    case "$(echo "$OP" | jq -r '.status // empty')" in
      Succeeded) DEF=$(az rest --method get --resource "$RESOURCE" --url "${LOC%/}/result"); break ;;
      Failed|Cancelled) echo "ERROR: getDefinition $(echo "$OP" | jq -r '.status')" >&2; exit 1 ;;
    esac
  done
else
  DEF=$(cat "$BODY")
fi
rm -f "$HDR" "$BODY"

# 2. Decode each part, modify mashup.pq, re-encode all 3.
MASHUP=$(echo "$DEF" | jq -r '.definition.parts[] | select(.path=="mashup.pq")          | .payload' | base64 -d)
META=$(  echo "$DEF" | jq -r '.definition.parts[] | select(.path=="queryMetadata.json") | .payload' | base64 -d)
PLAT=$(  echo "$DEF" | jq -r '.definition.parts[] | select(.path==".platform")          | .payload' | base64 -d)

NEW_MASHUP=$(echo "$MASHUP" | sed 's/old-pattern/new-pattern/')   # edit M here

MASHUP_B64=$(echo -n "$NEW_MASHUP" | base64 -w0)
META_B64=$(echo -n "$META"        | base64 -w0)
PLAT_B64=$(echo -n "$PLAT"        | base64 -w0)

# 3. Build the updateDefinition body in a temp file (full replacement — all 3 parts).
BODY_FILE=$(mktemp --suffix=.json 2>/dev/null || mktemp)  # GNU + BSD/macOS compatible
cat > "$BODY_FILE" <<EOF
{"definition":{"parts":[
  {"path":"mashup.pq",          "payload":"${MASHUP_B64}", "payloadType":"InlineBase64"},
  {"path":"queryMetadata.json", "payload":"${META_B64}",   "payloadType":"InlineBase64"},
  {"path":".platform",          "payload":"${PLAT_B64}",   "payloadType":"InlineBase64"}
]}}
EOF
az rest --method post --resource "$RESOURCE" \
  --url "$RESOURCE/v1/workspaces/${WS_ID}/dataflows/${DF_ID}/updateDefinition?updateMetadata=true" \
  --headers "Content-Type=application/json" --body "@$BODY_FILE"
rm -f "$BODY_FILE"

新しい接続をバインドしますか?例 1 の手順 1~5 が、バインドと保存を行う標準的なフローです。バインドのみの手順については、authoring-cli-quickref.md § Connection Binding Quick Patterns と authoring-script-templates.md § Connection Binding Templates を参照してください。


出力の期待事項

このスキルがタスクを完了したとき、エージェントは次の内容を返す必要があります。

項目規定
詳細度作成または変更した内容を簡潔にまとめます(3〜10行)。
既定の形式ステータスレポートには Markdown を使用します。単一リソースの応答にはフェンス付き JSON コードブロックを、一覧の応答には Markdown テーブルを使用します。
副作用の開示作成・変更・削除した ID と対象のワークスペース ID を明示的に報告します。ID を示さずに成功を示唆してはいけません。データフロー定義を保存または置き換えた場合は、長いコマンド本文がトランスクリプトで切り詰められ、書き込んだ部分名が失われる可能性があるため、mashup.pq、queryMetadata.json、.platform のうち、書き込んだ部分を文章で明記します。また、実際に使用した永続化パスも明記します。エンドポイントを通じて定義を保存した場合は updateDefinition、作成時に定義を指定した場合は作成呼び出し POST /v1/workspaces/{ws}/dataflows を記載します。作成 POST で定義を永続化した場合に、updateDefinition を使用したと主張してはいけません。
検証完了を宣言する前に、影響を受けたリソース(データフロー、接続、ジョブインスタンス)を再度 GET し、その状態(例:provisionState、status、Completed)を提示します。
エラーの提示いずれかの手順で 2xx 以外のステータス、LRO の Failed/Cancelled、または Arrow ストリームの {"Error":"..."} が返された場合は、未加工のエラーをそのまま伝え、処理を停止します。終端状態の更新 Failed/Cancelled、isRetriable: false のバックエンドエラー、またはワークスペース全体の UnknownException は致命的な停止条件です。報告して終了し、再実行、再ポーリング、長時間のデバッグループに入ってはいけません。
プレビューの表示(ワークフロー C)executeQuery の後、埋め込みエラーのチェックに合格した場合でも、結果の head(10) を Markdown テーブルとして、保存済みの Arrow ファイルとともにチャットに表示します。これにより、埋め込みエラー検出では見つけられないサイレントな成功バグ(フィルターによる全行の除外、列の誤り、オフバイワン、誤ったキャスト)を検出できます。スニペットと抑制ルールについては、dataflows-consumption-cli § Example 5b を参照してください。
API 名回答で API エンドポイントまたはリクエスト本文のフィールドに言及する場合は、言い換えたり複数形にしたりせず、正確で大文字・小文字を区別した名前(executeQuery、customMashupDocument、QueryName、mashup.pq、queryMetadata.json、GET /v1/connections/supportedConnectionTypes)を使用します。

コメント