field-service-data-capture-form-deployer-configure について
承認済みの JSON 仕様から、Salesforce に Field Service Mobile 用 Data Capture Flow を作成する Agent スキルです。モバイルフォームを構築する管理者やエージェント向けで、Tooling API 経由で Draft として作成し、ユーザーが確認・有効化します。
主な機能
- 01JSON 仕様から Flow を生成
- 02Tooling API で Flow を作成
- 03画面、項目、自動化に対応
- 04不足コンポーネントの代替項目を報告
- 05保留フォームのレコードを関連付け
- 06ページレイアウトの関連リストを確認・更新
活用シーン
- 01Field Service モバイル用データ収集フォームをデプロイ
- 02在庫移動などの複数ステップ Flow を作成
- 03フォームを Work Order に関連付け
- 04モバイルでフォームが表示されない問題を調査
MCP 対応
README によると、共有環境では Headless 360 MCP 経由で REST 呼び出しを実行します。このスキルはそれらの呼び出しで Salesforce org を読み書きします。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ forcedotcom/ sf-skills --skill field-service-data-capture-form-deployer-configureインストール後、Claude Code で/field-service-data-capture-form-deployer-configureを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
examples/inventory-transfer-spec.jsonsample-spec.jsonsectioned-spec.jsonreferences/field-types.mdflow-metadata-json.mdpost-screen-automation.md詳細
データ収集フォームを作成する(Field Service Mobile)
このスキルは、中間 JSON 仕様を受け取り、processType=DataCaptureFlow の Salesforce Flow をデプロイします。仕様はすでに正しく、承認済みであることを前提とします。ユーザーへの確認は、上流の設計スキルで行います。
ランタイム契約: このスキルにおけるすべての組織とのやり取りは、Codey ランタイムを通じてディスパッチされる REST 呼び出しです(ローカルでは
dispatch、共有サーフェスではホスト型 Headless 360 MCP)。このスキルは実行環境に依存しません。sfCLI、シェルスクリプト、ローカル Python、一時ファイルは必要ありません。認証プローブ、レコードの読み取り、レコードの書き込みは、それぞれ単一の REST 呼び出しです。Flow XML は、参照ドキュメントに基づいてエージェントがインラインで作成します。 シェルコマンドを実行してはいけません。
入力契約
reference/field-types.md のスキーマに適合する JSON ファイル。必要に応じて、reference/post-screen-automation.md のスキーマも使用できます。標準的な例:
- examples/sample-spec.json — 画面のみの最小構成フロー。
- examples/inventory-transfer-spec.json — Repeater、Radio、表示条件、Decision、Lookup、Loop、レコード作成を含む完全な例。
必須のトップレベルキー:formTitle、formType、screens。省略可能なキー:postScreen。
出力
単一の Tooling API 呼び出し(Metadata 本文を含む JSON で POST /services/data/vXX.0/tooling/sobjects/Flow)を使用して、組織内に作成される Data Capture Flow です(.flow-meta.xml、zip、SFDX プロジェクトは不要です)。Flow は Draft ステータスで作成され、ユーザー自身が Flow Builder で有効化します。
ワークフロー
1. 組織の認証を確認する
軽量な認証プローブをディスパッチして、接続先の組織に到達できることを確認します — SELECT Id FROM Organization LIMIT 1 をディスパッチします(GET /services/data/vXX.0/query)。
- 2xx で
totalSize=1→ セッショントークンは有効です。続行します。 - 401/403 → 組織の再認証が必要です。その旨をユーザーに伝え、停止します。デプロイしてはいけません。(Codey ランタイムが接続先の組織を解決し、トークンを更新します。このスキルは組織エイリアスを管理しません。)
2. Flow API 名を決める
設計スキルから <FlowApiName> がすでに渡されている場合は、それを使用します。それ以外の場合は、formTitle から導出します。PascalCase で、空白を含まず、^[A-Z][A-Za-z0-9_]*$ に一致する必要があります。タイトルをこの形式に変換できない場合は、ユーザーに確認します。
3. Flow Metadata JSON を作成する
仕様から Flow の Metadata オブジェクトをインラインで組み立てます。Tooling の Flow sObject は JSON の Metadata ブロブを受け取るため、コンパイルする XML も、実行する変換ツールもありません。reference/flow-metadata-json.md と reference/field-types.md に記載された JSON の構造とフィールドのマッピングに従います。
注意事項:
- JSON の
Metadataは、Tooling のFlowGET が返すものとまったく同じ構造です(GET /tooling/sobjects/Flow/{id}→Metadata)。そのため、組み立てる前に、既知の正常な別の Flow を取得し、実際の参照例として利用できます。 - フロー全体で選択肢を重複排除します。
["Good","Fair","Poor"]の 2 つのフィールドは、トップレベルのchoices配列内にある同じ 3 つのエントリを共有します。 - Repeater の子要素は、親 Repeater フィールド内の
fieldsエントリとしてネストします。 Signature、UploadFile、UploadImage、Imagesは、標準の DataCaptureFlow 入力変数にparentRecordId/recordIdを自動的に接続します。これらは機能するコンポーネントとしてデプロイされ、Flow Builder での修正は不要です。LookupにはlookupObject仕様キーが必要です。これがない場合は、ラベル付きのdcTextInputプレースホルダーを出力します。FileViewにはfileNameが必要です。同様に、指定がない場合は代替表示になります。このような代替表示をすべて収集し、ステップ 5 で提示します。- デプロイ前に自己チェックします。
processTypeがDataCaptureFlowであること、environmentsにOfflineが含まれていること、3 つの入力変数(parentObjectType、parentRecordId、recordId)が存在することを確認します。
4. 組織にデプロイする
Tooling API を 1 回呼び出してフローを作成します。次の本文を指定して POST /services/data/vXX.0/tooling/sobjects/Flow をディスパッチします。
{
"FullName": "<FlowApiName>",
"Metadata": { "processType": "DataCaptureFlow", "environments": ["Offline"], "label": "...", "screens": [ ... ], "choices": [ ... ], "variables": [ ... ], "status": "Draft" }
}
FullNameは Flow API 名です。Metadataはステップ 3 で組み立てたオブジェクトです。- 201 が返され、
success: trueの場合、新しい Flow バージョン ID が返されます。StatusはDraftのままにしてください(作成時に有効化するようユーザーから指示があった場合に限り、Metadata.status: "Active"を設定します。デフォルトは Draft なので、ユーザーはまず Flow Builder で内容を確認できます)。 - 400 が返された場合、レスポンス本文の
messageに Flow の検証エラーが記載されています。ステップ 5 の失敗時の表に照らして原因を特定してください。
5. 結果を報告する
成功した場合:
- Tooling API のクエリで FlowDefinition Id を確認します。
SELECT Id, ActiveVersionId FROM FlowDefinition WHERE DeveloperName = '<FlowApiName>'を指定してGET /services/data/vXX.0/tooling/queryをディスパッチします。 - クリック可能な Flow Builder URL を表示します:
<instanceUrl>/builder_platform_interaction/flowBuilder.app?flowId=<id>。 - 画面数、フィールドの総数、ユーザーが Flow Builder で設定する必要のあるフォールバックフィールド(
lookupObjectのない Lookup、fileNameのない FileView)を一覧表示します。 - フローの直接起動 URL を表示します:
<instanceUrl>/flow/<FlowApiName>。QuickActions、レイアウト、Forms タブを経由せずに検証できる最短の方法です。
失敗した場合(POST が 400 を返した場合は、レスポンス本文の message からエラーを読み取ります):
Cannot find component 'runtime_service_fieldservice:dcXxx'の場合 → 組織で Field Service が有効になっていないか、コンポーネント名が正しくありません。正確なエラーを提示して、処理を停止します。- Flow の検証エラーの原因は、通常、fs-data-capture-reference/SKILL.md の禁止パターン表に記載されているパターンです。再試行する前に、そのファイルを読んでください。よくある原因:スキーマのグループ化違反、
.AllItemsと.AddedItemsのアクセサーの不一致、CUD の順序、nextOrFinishButtonLabelの欠落、IsLlmTargetableのブール値と文字列の不一致。 - ユーザーに知らせずに 2 回を超えて再試行しないでください。
- よくある落とし穴:明示的な
{ "section": "..." }ヘッダーより前に最初のフィールドがある画面で暗黙のSec_Generalセクションを出力すると、2 つの画面でDuplicate developer name: Sec_Generalが発生します。そのような画面にはそれぞれ JSON で明示的な先頭セクションを指定してから、再度組み立てて POST してください。
6. フォームを表示できるようにする(任意ですが、通常は必要です)
フローをデプロイしても、Service Appointment、Work Order、その他の親レコードの「Forms」関連リストには表示されません。デプロイしたフローを、技術者が選択できる保留中のフォームとして表示するには、次の手順を実行します。
-
親レコードに
DynamicDataCaptureレコードを関連付けます。 これは SDO で標準的に使用されている「保留中のフォーム」のパターンです。出荷済みの SDO フォーム(Job Safety、Vehicle Inspection、Job Completion)の設定方法を参照してください。次の本文を指定してPOST /services/data/vXX.0/sobjects/DynamicDataCaptureをディスパッチし、sObject の挿入を 1 回行ってレコードを作成します。{ "Name": "<Display Name>", "ParentRecordId": "<ParentRecordId>", "ActionDefinition": "<FlowApiName>", "ActionType": "Flow", "ProcessType": "DataCaptureFlow", "StatusCategory": "New", "IsRequired": true, "ExecutionOrder": 1 }呼び出し側が表示名を指定しない場合、
Nameはデフォルトで<FlowApiName>のアンダースコアをスペースに置き換えた値になります。IsRequiredは文字列ではなく、実際のブール値(true/false)です。201 が返され、success: trueの場合、新しい DDC ID が返されます。ParentRecordIdはポリモーフィックです。指定できる親の種類はServiceAppointment、ServiceResource、TimeSheet、Visit、WorkOrder、WorkOrderLineItemです。 -
FSL Mobile/Service Appointment のコンテキストでは、SA 自体ではなく親 Work Order に関連付けます。 Service Appointment の FSL Mobile の Forms タブでは通常、SA の親 Work Order に関連付けられた
DynamicDataCaptureレコードが集約されます(ServiceAppointment.ParentRecordId経由)。SA に直接関連付けても、モバイルで表示されない場合があります。まず SA の親 Work Order Id を解決します。
SELECT ParentRecordId FROM ServiceAppointment WHERE Id = '<SA_Id>'を指定してGET /services/data/vXX.0/queryをディスパッチし、その後、手順 1 のサブステップに従ってその Work Order Id に関連付けます。 -
親レコードのページレイアウトに「Forms(DynamicDataCapture)」関連リストがあることを確認します。 SDO によって、プロファイルごとに異なるレイアウトが使われます。Tooling API を使用して、
SELECT Layout.Name, Profile.Name FROM ProfileLayout WHERE TableEnumOrId = 'WorkOrder'を指定したGET /services/data/vXX.0/tooling/queryをディスパッチします。Layout自体は JSON のMetadataフィールドを持つ Tooling sObject なので、この追加は REST による読み取り・変更・書き込みで行います。XML ファイルもデプロイも不要です。GET /services/data/vXX.0/tooling/sobjects/Layout/{layoutId}でレイアウトを読み込み({layoutId}は上記のクエリにあるProfileLayout.LayoutIdから特定します)、Metadata.relatedListsにDynamicDataCaptureエントリがあるか確認します。ない場合はこのエントリを追加し、更新したMetadataを指定してPATCH /services/data/vXX.0/tooling/sobjects/Layout/{layoutId}を実行します。{ "relatedList": "DynamicDataCapture", "fields": ["Name", "StatusCategory", "IsRequired"] } -
注意事項:
- 関連付けるフォームの
StatusCategory='New'が必要です。これにより、保留中として表示されます。Completedのレコードは履歴として表示されます。 ActionDefinitionは、デプロイしたフローの API 名と完全に一致している必要があります(大文字と小文字が区別されます)。ProcessType='DataCaptureFlow'が必要です。SDO ではDiscoveryFrameworkFlowも使用されることがあります。- 親プロファイルのレイアウトに Forms リストがない場合、データレイヤーでは DDC の関連付けに成功しますが、フォームは UI に表示されません。
- 関連付けるフォームの
-
プロファイルごとに独自のページレイアウトがあります。 実際の SDO では、プロファイルごとに異なる Work Order レイアウトが割り当てられていることがよくあります(例:
System Administrator→SDO SFS Work Order Layout、Standard User→Work Order Layout、SDO-Service→FSL Work Order Layout)。1 つのレイアウトにパッチを適用しても、ほかのレイアウトを使うユーザーには効果がありません。フォームを表示する必要があるプロファイルごとに、上記の ProfileLayout クエリを実行し、対象となるレイアウトすべてにパッチを適用します。 -
FSL Mobile では DDC と WorkPlan の OWD を Public Read/Write にする必要があります。 FSL Mobile の Forms タブは UI API(
/ui-api/related-list-records/<woId>/DynamicDataCaptures)を使用し、共有設定を適用します。DynamicDataCaptureまたはWorkPlanの OWD が Private(プラットフォームのデフォルト)の場合、技術者は AssignedResource の共有によって WO にアクセスできますが、DDC 自体の行アクセス権はありません。その結果、UI API はINSUFFICIENT_ACCESSを返し、Forms タブには「No forms available. We couldn't find any forms to display.」と「Try Again」ボタンが表示されます。管理者は共有設定を回避できるため、デスクトップでの SOQL ではこの問題を検出できません。修正方法:
DynamicDataCaptureとWorkPlanの組織全体のデフォルトを Public Read/Write に設定します。組織全体の共有設定は Setup からのみ変更できます。ディープリンク<instanceUrl>/lightning/setup/SecuritySharing/homeを提示し、管理者に両オブジェクトの Default Internal Access を Public Read/Write に設定してもらいます。(これはクリック操作であり、シェルで実行する手順ではありません。)- Tooling PATCH を使用して、
FieldServiceSettingsのdoesShareSaParentWoWithArとdoesShareSaWithArをtrueに設定します。まず、GET /services/data/vXX.0/tooling/queryにSELECT Id, Metadata FROM FieldServiceSettingsを指定してシングルトンを読み込み、次に{"Metadata": {"doesShareSaParentWoWithAr": true, "doesShareSaWithAr": true}}を指定してPATCH /services/data/vXX.0/tooling/sobjects/FieldServiceSettings/{id}を実行します(マージし、既存の Metadata キーも含めます)。 - 共有の再計算をトリガーするため、既存の
AssignedResourceレコードを再保存します。レコードごとにPATCH /services/data/vXX.0/sobjects/AssignedResource/{id}を変更なしで実行すると、共有ルールが再適用されます。 - ユーザーは FSL Mobile からサインアウトし、再度サインインする必要があります。共有のスナップショットはログイン時にキャッシュされます。
Tooling API クエリを実行して確認します。
SELECT QualifiedApiName, InternalSharingModel FROM EntityDefinition WHERE QualifiedApiName IN ('DynamicDataCapture','WorkPlan')を指定したGET /services/data/vXX.0/tooling/queryをディスパッチします。どちらもReadWriteを返す必要があります。どちらかがPrivateを返す場合、DDC レコードが存在していても技術者の Forms タブは機能しません。 -
添付後、モバイルでは更新が必要な場合があります。 OWD が正しく設定されていても、FSL Mobile の Forms タブでは関連リストがキャッシュされます。新しく添付された DDC を反映するには、Work Order の Forms タブでプルして更新してください。プルして更新しても表示されない場合は、アプリを強制終了してから再度開いてください。サインアウトして再度サインインする必要があるのは、共有設定が変更された場合のみです(#6)。
-
UI API バージョンに関する注意(テストのみ)。 UI API v60 は共有設定が正しくても
INSUFFICIENT_ACCESSを返しますが、v62 以降では動作します。iOS の FSL Mobile アプリは v67 をハードコードしているため、本番環境での問題にはなりません。ただし、curl で呼び出しを再現する際は重要です。
対象範囲
自動生成されるもの:
- 仕様から取得する項目ラベル、型、必須状態。
- ネイティブ型:
ShortText、LongText、Name、Email、Phone、Numeric、Counter(min/max/valueを使用)、Date、DateTime、Checkbox、Toggle、Picklist、Radio(dcRbGroup)、CheckboxGroup、DisplayText、Repeater。 - Field Service 専用コンポーネント:
Signature(parentRecordIdとrecordIdを自動設定)、UploadFile、UploadImage、Images(recordId→parentRecordIdを自動設定)、Address(複合型)、Matrix(列の選択肢と行ラベルのquestions)、Lookup(lookupObject/lookupSearchFields/lookupMulti仕様キーを使用)、FileView(fileName仕様キーを使用)。 - 個々の項目での条件付き表示。
- オプションの
postScreen自動化:判断要素、複数のrecordLookups、1 つのloop、複数のrecordCreates、および追加の非入力変数。
デプロイ可能なプレースホルダーにフォールバックします(管理者が Flow Builder で置き換えます):
LookupにlookupObjectがない場合 →[Lookup — set objectApiName in Flow Builder]を先頭に付けたdcTextInput。FileViewにfileNameがない場合 →[FileView — set fileName in Flow Builder]を先頭に付けたdcTextInput。
マッピングの全容は reference/field-types.md を参照してください。
対象外:
postScreen内の複数の判断要素/複数のループ/ネストされたループ。- サブフロー、数式、テキストテンプレート、割り当て。
- 視覚的な装飾用 HTML(バナー、進行状況バー、コールアウト)。これらは手動で作成します。パターンについては
fs-data-capture-referenceスキルを参照してください。
このスキルのファイル
このスキルに実行可能なスクリプトはありません。認証チェック、レコードの読み取り、DynamicDataCapture の添付、フローの作成/デプロイは、すべて Codey ランタイムを通じて実行する単一の REST 呼び出しです(手順 1、4、5、6)。Flow Metadata JSON は、以下のリファレンスドキュメントをもとにエージェントが手順 3 でその場で組み立てます。
reference/flow-metadata-json.md— Tooling のFlow.MetadataJSON の形式(画面、選択肢、判断要素、変数、画面後のチェーン)とデプロイ/有効化の呼び出し。フローを組み立てる際に参照してください。reference/field-types.md— 入力仕様:仕様のfieldType→ ランタイムコンポーネント+JSON 属性。reference/post-screen-automation.md— オプションのpostScreenブロックの入力仕様。examples/sample-spec.json、examples/inventory-transfer-spec.json— 正式な仕様例。
関連スキル
fs-data-capture-reference(関連するライブラリスキル)— 手動作成のパターン、禁止パターンと正確なデプロイエラー、視覚的な装飾用 HTML、補助的な CustomObject/PermissionSet/CustomTab のデプロイに関するリファレンスマニュアル。デプロイエラーの原因を調査する場合や、JSON の項目マッピングを拡張する場合に参照してください。fs-data-capture-form-designer— このスキルが使用する仕様を、文章または画像/PDF から生成します。fs-data-capture-form-editor— 組織にすでにデプロイされているフローにパッチを適用します。このスキルと同じ ToolingFlowJSON の往復処理(GET Metadata → 編集 → PATCH)を使用してフローを作成します。