field-service-data-capture-form-deployer-configure
Assemble a Data Capture Flow from a JSON spec and deploy it to a connected Field Service org via the Tooling Flow sObject (JSON Metadata, no XML). U…
它会碰到什么
这一栏是扫描器报的事实,不是结论。命中多不等于有毒(安全工具、规则库、示例脚本本来就会包含危险写法),命中少也不等于干净。它和你手上的凭据、文件、网络有什么关系,需要你自己看。
技能内容
Build a Data Capture Form (Field Service Mobile)
This skill takes an intermediate JSON spec and produces a deployed Salesforce Flow with processType=DataCaptureFlow. It assumes the spec is already correct and approved — confirmation with the user happens upstream in the design skills.
> Runtime contract: every org interaction in this skill is a REST call
> dispatched through the Codey runtime (dispatch locally / the hosted
> Headless 360 MCP in shared surfaces). This skill has **no dependency on the
> execution environment** — no sf CLI, no shell scripts, no local Python, no
> temp files. Auth probes, record reads, and record writes are single REST
> calls; the Flow XML is authored by the agent inline from the reference docs.
> Do not shell out.
Input contract
A JSON file matching the schema in [reference/field-types.md](reference/field-types.md) and (optionally) [reference/post-screen-automation.md](reference/post-screen-automation.md). Canonical examples:
- [examples/sample-spec.json](examples/sample-spec.json) — minimal screens-only flow.
- [examples/inventory-transfer-spec.json](examples/inventory-transfer-spec.json) — full example with Repeater, Radio, visibility, decision, lookups, loop, and record-create.
Required top-level keys: formTitle, formType, screens. Optional: postScreen.
Output
A Data Capture Flow created in the org via a single Tooling API call — POST /services/data/vXX.0/tooling/sobjects/Flow with a JSON Metadata body (no .flow-meta.xml, no zip, no SFDX project). The flow is created in Draft status and the user activates it themselves in Flow Builder.
Workflow
1. Verify org auth
Confirm the connected org is reachable with a cheap auth probe — dispatch SELECT Id FROM Organization LIMIT 1 (GET /services/data/vXX.0/query):
- 2xx with
totalSize=1→ the session token is live; continue. - 401/403 → the org needs re-authentication. Surface that to the user and stop; do not deploy. (The Codey runtime resolves and refreshes the connected org — this skill does not manage org aliases.)
2. Pick a Flow API name
If the design skill already supplied <FlowApiName>, use it. Otherwise derive from formTitle: PascalCase, no spaces, must match ^[A-Z][A-Za-z0-9_]*$. If the title can't be coerced, ask the user.
3. Build the Flow Metadata JSON
Assemble the flow's Metadata object inline from the spec — the Tooling Flow sObject takes a JSON Metadata blob, so there is no XML to compile and no converter to run. Follow the JSON shape and field mappings in [reference/flow-metadata-json.md](reference/flow-metadata-json.md) and [reference/field-types.md](reference/field-types.md).
Notes:
- The JSON
Metadatais the exact same shape the ToolingFlowGET returns (GET /tooling/sobjects/Flow/{id}→Metadata), so you can retrieve a known-good sibling flow as a live reference before composing. - Dedupe choices across the entire flow — two fields with
["Good","Fair","Poor"]share the same three entries in the top-levelchoicesarray. - Repeater children are nested as
fieldsentries inside the parent Repeater field. Signature,UploadFile,UploadImage, andImagesauto-wireparentRecordId/recordIdto the standard DataCaptureFlow input variables. They deploy as functional components, no Flow Builder cleanup required.Lookuprequires alookupObjectspec key; without it, emit the labeleddcTextInputplaceholder.FileViewrequires afileName; same fallback. Collect any such fallbacks and surface them in step 5.- Self-check before deploying:
processTypeisDataCaptureFlow,environmentsincludesOffline, and the three input variables (parentObjectType,parentRecordId,recordId) are present.
4. Deploy to org
Create the flow with a single Tooling API call — dispatch POST /services/data/vXX.0/tooling/sobjects/Flow with body:
{
"FullName": "<FlowApiName>",
"Metadata": { "processType": "DataCaptureFlow", "environments": ["Offline"], "label": "...", "screens": [ ... ], "choices": [ ... ], "variables": [ ... ], "status": "Draft" }
}
FullNameis the Flow API name;Metadatais the object you assembled in step 3.- A 201 with
success: truereturns the new Flow version id.StatusstaysDraft(setMetadata.status: "Active"only if the user asked to activate on create — the default is Draft so the user reviews in Flow Builder first). - On a 400, the response body's
messagecarries the Flow validation error — diagnose against step 5's failure table.
5. Report back
On success:
- Look up the FlowDefinition Id with a Tooling API query — dispatch
GET /services/data/vXX.0/tooling/querywithSELECT Id, ActiveVersionId FROM FlowDefinition WHERE DeveloperName = '<FlowApiName>'. - Print a clickable Flow Builder URL:
<instanceUrl>/builder_platform_interaction/flowBuilder.app?flowId=<id>. - List screens, total field count, and any fallback fields (Lookup with no
lookupObject, FileView with nofileName) the user needs to wire up in Flow Builder. - Print the direct flow-launch URL:
<instanceUrl>/flow/<FlowApiName>— the fastest validation path that bypasses QuickActions, layouts, and the Forms tab.
On failure (the POST returned a 400 — read the error from the response body's message):
- If
Cannot find component 'runtime_service_fieldservice:dcXxx'→ org doesn't have Field Service enabled (or the component name is wrong). Surface the exact error and stop. - For Flow validation errors, the cause is usually a pattern listed in the prohibited-patterns table at [fs-data-capture-reference/SKILL.md](../fs-data-capture-reference/SKILL.md). Read that file before retrying. Common diagnoses: schema-grouping violations,
.AllItemsvs.AddedItemsaccessor mismatch, CUD ordering, missingnextOrFinishButtonLabel,IsLlmTargetableboolean-vs-string. - Don't loop more than twice without showing the user.
- Common gotcha: if you emit an implicit
Sec_Generalsection for any screen whose first field appears before an explicit{ "section": "..." }header, two such screens collide withDuplicate developer name: Sec_General. Give each such screen an explicit leading section in the JSON, then re-assemble and re-POST.
6. Make the form visible (optional but usually wanted)
Deploying the flow does NOT make it appear in the "Forms" related list on a Service Appointment, Work Order, or other parent. To make a deployed flow show up as a pending form a tech can pick up:
- Attach a
DynamicDataCapturerecord to the parent. This is the SDO's canonical "pending form" pattern — see how shipped SDO forms (Job Safety, Vehicle Inspection, Job Completion) are wired. Create the record with a single sObject insert — dispatchPOST /services/data/vXX.0/sobjects/DynamicDataCapturewith this body:
{
"Name": "<Display Name>",
"ParentRecordId": "<ParentRecordId>",
"ActionDefinition": "<FlowApiName>",
"ActionType": "Flow",
"ProcessType": "DataCaptureFlow",
"StatusCategory": "New",
"IsRequired": true,
"ExecutionOrder": 1
}
Name defaults to <FlowApiName> with underscores → spaces if the caller gives no display name; IsRequired is a real boolean (true/false), not a string. A 201 with success: true returns the new DDC id. ParentRecordId is polymorphic — accepted parent types are ServiceAppointment, ServiceResource, TimeSheet, Visit, WorkOrder, WorkOrderLineItem.
- For FSL Mobile / Service Appointment context, attach to the parent Work Order, not the SA itself. FSL Mobile's Forms tab on a Service Appointment typically aggregates
DynamicDataCapturerecords from the SA's parent Work Order (viaServiceAppointment.ParentRecordId). Attaching directly to the SA may not surface in mobile.
Resolve the SA's parent Work Order Id first — dispatch GET /services/data/vXX.0/query with SELECT ParentRecordId FROM ServiceAppointment WHERE Id = '<SA_Id>', then attach (sub-step 1) to that Work Order Id.
- Verify the parent's page layout has the Forms (DynamicDataCapture) related list. Different SDOs use different layouts per profile. Query with the Tooling API — dispatch
GET /services/data/vXX.0/tooling/querywithSELECT Layout.Name, Profile.Name FROM ProfileLayout WHERE TableEnumOrId = 'WorkOrder'.
Layout is itself a Tooling sObject with a JSON Metadata field, so the splice is a REST read-modify-write — no XML file, no deploy. Read the layout with GET /services/data/vXX.0/tooling/sobjects/Layout/{layoutId} (resolve {layoutId} from the ProfileLayout.LayoutId in the query above), check Metadata.relatedLists for a DynamicDataCapture entry, and if absent append this entry and PATCH /services/data/vXX.0/tooling/sobjects/Layout/{layoutId} with the updated Metadata:
{
"relatedList": "DynamicDataCapture",
"fields": ["Name", "StatusCategory", "IsRequired"]
}
- Caveats:
- Attached form must have
StatusCategory='New'to appear as pending.Completedrecords show as historical. ActionDefinitionmust exactly match the deployed flow's API name (case-sensitive).ProcessType='DataCaptureFlow'is required — the SDO sometimes also usesDiscoveryFrameworkFlow.- If the parent profile's layout lacks the Forms list, attaching the DDC succeeds at the data layer but the form is invisible in the UI.
- Each profile has its own page layout. Real SDOs commonly route different profiles to different Work Order layouts (e.g.
System Administrator→SDO SFS Work Order Layout,Standard User→Work Order Layout,SDO-Service→FSL Work Order Layout). Patching one layout doesn't help users on the others. Run the ProfileLayout query above for every profile that needs to see the form, then patch the union of layouts.
- DDC + WorkPlan OWD must be Public Read/Write for FSL Mobile. The Forms tab on FSL Mobile uses the UI API (
/ui-api/related-list-records/<woId>/DynamicDataCaptures), which enforces sharing. IfDynamicDataCaptureorWorkPlanOWD is Private (the platform default), the technician got the WO via AssignedResource sharing and has zero row access to the DDCs themselves — UI API returnsINSUFFICIENT_ACCESSand the Forms tab silently shows "No forms available. We couldn't find any forms to display." with a "Try Again" button. Desktop SOQL as admin doesn't catch this because admins bypass sharing.
Fix:
- Set the org-wide default for
DynamicDataCaptureandWorkPlanto Public Read/Write. Org-wide sharing defaults are a Setup-only surface — surface the deeplink<instanceUrl>/lightning/setup/SecuritySharing/homeand have the admin set both objects' Default Internal Access to Public Read/Write. (This is a click-through, not a shell step.) - Set
doesShareSaParentWoWithAranddoesShareSaWithArtotrueonFieldServiceSettingsvia a Tooling PATCH —GET /services/data/vXX.0/tooling/querySELECT Id, Metadata FROM FieldServiceSettingsto read the singleton, thenPATCH /services/data/vXX.0/tooling/sobjects/FieldServiceSettings/{id}with{"Metadata": {"doesShareSaParentWoWithAr": true, "doesShareSaWithAr": true}}(merge — include the existing Metadata keys). - Re-save existing
AssignedResourcerecords to trigger sharing recalc — a no-opPATCH /services/data/vXX.0/sobjects/AssignedResource/{id}per record re-fires the sharing rules. - User must sign out + back in to FSL Mobile — the sharing snapshot is cached at login.
Verify with a Tooling API query — dispatch GET /services/data/vXX.0/tooling/query with SELECT QualifiedApiName, InternalSharingModel FROM EntityDefinition WHERE QualifiedApiName IN ('DynamicDataCapture','WorkPlan'). Both should return ReadWrite. If either returns Private, the Forms tab will fail for the tech even though the DDC row exists.
- After attaching, mobile may need a refresh. Even with OWD correct, the FSL Mobile Forms tab caches the related list. To pick up a newly-attached DDC: pull-to-refresh on the Forms tab on the Work Order. Force-quit + reopen the app if pull-to-refresh doesn't surface it. Sign out + back in is only needed when sharing changes (#6).
- UI API version note (testing only). UI API v60 returns
INSUFFICIENT_ACCESSeven after sharing is correct; v62+ works. The iOS FSL Mobile app hardcodes v67, so this isn't a production issue — but it matters when reproducing the call via curl.
Scope
Generated automatically:
- Field labels, types, and required state from the spec.
- Native types:
ShortText,LongText,Name,Email,Phone,Numeric,Counter(withmin/max/value),Date,DateTime,Checkbox,Toggle,Picklist,Radio(dcRbGroup),CheckboxGroup,DisplayText,Repeater. - Specialized Field Service components:
Signature(auto-wiresparentRecordId+recordId),UploadFile,UploadImage,Images(auto-wirerecordId→parentRecordId),Address(compound),Matrix(column choices +questionsrow labels),Lookup(withlookupObject/lookupSearchFields/lookupMultispec keys),FileView(withfileNamespec key). - Conditional visibility on individual fields.
- Optional
postScreenautomation: a decision, multiplerecordLookups, oneloop, multiplerecordCreates, and extra non-input variables.
Falls back to deploy-safe placeholders (admin replaces in Flow Builder):
Lookupwith nolookupObject→dcTextInputwith[Lookup — set objectApiName in Flow Builder]prefix.FileViewwith nofileName→dcTextInputwith[FileView — set fileName in Flow Builder]prefix.
See [reference/field-types.md](reference/field-types.md) for the full mapping.
Out of scope:
- Multiple decisions / multiple loops / nested loops in
postScreen. - Subflows, formulas, text templates, assignments.
- Visual polish HTML (banners, progress bars, callouts) — those are hand-authored. See
fs-data-capture-referenceskill for patterns.
Files in this skill
This skill has no executable scripts. Auth checks, record reads, the DynamicDataCapture attach, and the flow create/deploy are all single REST calls dispatched through the Codey runtime (steps 1, 4, 5, 6). The Flow Metadata JSON is assembled by the agent inline (step 3) from the reference docs below.
reference/flow-metadata-json.md— the ToolingFlow.MetadataJSON shape (screens, choices, decisions, variables, post-screen chain) and the deploy/activate calls. Read this when composing the flow.reference/field-types.md— input contract: specfieldType→ runtime component + JSON attributes.reference/post-screen-automation.md— input contract for the optionalpostScreenblock.examples/sample-spec.json,examples/inventory-transfer-spec.json— canonical specs.
Related skills
fs-data-capture-reference(sibling library skill) — reference manual for hand-authoring patterns, prohibited patterns + exact deploy errors, visual polish HTML, supporting CustomObject/PermissionSet/CustomTab deploy. Read this when diagnosing a deploy error or extending the JSON field mappings.fs-data-capture-form-designer— produces the spec this skill consumes (from prose or an image/PDF).fs-data-capture-form-editor— patches an already-deployed flow in the org. Uses the same ToolingFlowJSON round-trip (GET Metadata → edit → PATCH) this skill uses to create.
想直接用这个技能?
本站把开放许可(MIT / Apache 等)的技能按仓库打包整理到网盘,点一下转存到你自己的网盘,不用一个个从 GitHub 拉。许可未声明的技能只给原始仓库链接,不打包。
它属于哪个仓库
skills/field-service-data-capture-form-deployer-configure/SKILL.md同一个仓库里的其他技能
- commerce-b2b-open-code-components-integrate
- commerce-b2b-open-code-components-replace
- dx-devops-conflict-resolve
- dx-devops-pipeline-manage
- dx-devops-test-failures-analyze
- dx-devops-test-pipeline-configure
- dx-devops-test-suite-assignments-configure
- dx-devops-test-suite-run
- dx-devops-work-item-manage
- dx-app-analytics-query
- platform-agentexchange-partner-offers-configure
- automation-sandbox-post-copy-config-generate