@uipath/skills 1.201.0-preview.637 → 1.201.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uipath/skills",
3
- "version": "1.201.0-preview.637",
3
+ "version": "1.201.0",
4
4
  "description": "UiPath agent skills for Claude Code, Codex, Cursor, Copilot, Gemini and OpenCode — RPA, UI automation, UI testing, coded agents/apps/workflows, and troubleshooting. Distributed as the UiPath Claude Code plugin.",
5
5
  "author": {
6
6
  "name": "UiPath"
@@ -1,12 +1,12 @@
1
1
  ---
2
2
  name: uipath-human-in-the-loop
3
- description: "UiPath Human-in-the-Loop / HITL node authoring — building approval gates, escalations, write-back validation, and data enrichment checkpoints in Flow, Maestro, or Coded Agents. NOT for managing, reassigning, or monitoring tasks at runtime (use uipath-tasks for that)."
3
+ description: "UiPath Human-in-the-Loop / HITL node authoring — building approval gates, escalations, write-back validation, and data enrichment checkpoints in Flow, Maestro, Case Management, or Coded Agents. NOT for managing, reassigning, or monitoring tasks at runtime (use uipath-tasks for that)."
4
4
  allowed-tools: Bash, Read, Write, Edit, Glob, Grep
5
5
  ---
6
6
 
7
7
  # UiPath Human-in-the-Loop Assistant
8
8
 
9
- Recognizes when a business process needs a human decision point, designs the task schema through conversation, and wires the HITL node into the automation — Flow, Maestro, or Agent.
9
+ Recognizes when a business process needs a human decision point, designs the task schema through conversation, and wires the HITL node into the automation — Flow, Maestro, Case Management, or Agent.
10
10
 
11
11
  > **Coded agents:** for wiring HITL inside a coded agent, use the `uipath-agents` skill — see `skills/uipath-agents/references/coded/capabilities/human-in-the-loop.md`.
12
12
 
@@ -32,7 +32,7 @@ See [references/hitl-patterns.md](references/hitl-patterns.md) for the full busi
32
32
 
33
33
  ## Critical Rules
34
34
 
35
- 1. **Confirm schema with the user before writing anything for quickform type.** Show the designed schema and wait for explicit confirmation. **Running non-interactively (CI/headless — no user available to answer):** do not block — design the schema from the prompt and any upstream `.flow` data, write the node, and record the chosen schema prominently in the final report. Only stop and report the open decision if the request is too ambiguous to pick a sensible default. (A prompt that already specifies the fields, outcomes, and output shape is never too ambiguous.)
35
+ 1. **Never block on schema confirmation.** Design the schema from the prompt and any upstream `.flow`/`caseplan.json` data, write the node, and record the chosen schema prominently in the final report so the user can adjust it afterward. Asking the user is never a precondition for proceeding — if the user is present and offers input, use it, but do not wait for it. Only stop and report the open decision when the request is genuinely too ambiguous to make any reasonable inference. (A prompt that already specifies the fields, outcomes, and output shape is never too ambiguous.)
36
36
  2. **Always wire the `completed` handle.** A HITL node with no outgoing edge on `completed` blocks the flow forever. Only `completed` is available as an output handle — **not** `output`, `success`, or any other name. This is true even when inserting into an existing flow whose other nodes use `"sourcePort": "output"`.
37
37
  3. **Always add the definition entry when inserting into an existing flow.** Before writing the node, check `workflow.definitions[]` for the correct `nodeType` for the selected path (`"uipath.human-in-the-loop.quick-form"` for QuickForm, `"uipath.human-in-the-loop.coded-action-app"` for app-based). If absent, append the full definition entry (with `handleConfiguration` including the `completed` handle). Skipping the definition means the `completed` handle is invisible to the runtime and the wiring check fails.
38
38
  4. **Regenerate `variables.nodes` after adding the node.** Replace the entire `workflow.variables.nodes` array — do not append. See the reference docs for the algorithm.
@@ -72,6 +72,11 @@ Run these checks in order:
72
72
  # Check for a .flow file (Flow project)
73
73
  find . -name "*.flow" -maxdepth 4 | head -5
74
74
 
75
+ # Check for a Case Management project. The on-disk filename varies
76
+ # (caseplan.json, or content/<name>.json.bpmn under a `uip maestro case init`
77
+ # project) — detect by content marker, not by filename.
78
+ find . -maxdepth 4 -iname "*.json*" -print0 2>/dev/null | xargs -0 grep -l '"case-management:root"' 2>/dev/null | head -3
79
+
75
80
  # Check for agent.json (Low-Code Agent project)
76
81
  find . -name "agent.json" -maxdepth 4 | head -3
77
82
 
@@ -82,6 +87,7 @@ find . -name "*.bpmn" -maxdepth 4 | head -3
82
87
  | Found | Surface | How HITL is added |
83
88
  |---|---|---|
84
89
  | `.flow` file | **Flow** | Write node JSON directly — see reference docs |
90
+ | `caseplan.json` (any `*.json` with `root.type: "case-management:root"`) | **Case** | Write `action` task into stage — see [hitl-casetask-action.md](references/hitl-casetask-action.md) |
85
91
  | `agent.json` | **Low Code Agent** | Escalation CLI in-flight — guide manually for now |
86
92
  | `.bpmn` (Maestro) | **Maestro** | Write the `UserTask` XML directly — see Step 5 Surface: Maestro |
87
93
 
@@ -127,22 +133,26 @@ Read the existing `.flow` file to understand current nodes and edges. Use the Re
127
133
  | "fills in missing", "validates extraction", "corrects" | Data enrichment | Automation produced incomplete data |
128
134
  | "compliance", "regulatory", "audit trail" | Compliance checkpoint | Mandated human sign-off |
129
135
 
130
- **When a signal is found, say this before doing anything else:**
136
+ **Never block on this.** When a signal is clear-cut (an explicit approval / review / sign-off requirement), add the HITL step and state that you did so, in this form:
131
137
 
132
- > "I noticed that [quote the specific part of their description]. This is a [pattern name] — a point where [brief consequence if no human reviews]. I recommend inserting a Human-in-the-Loop step here so that [human role] can [action] before the automation [continues/writes/sends]. Should I add it?"
138
+ > "I noticed that [quote the specific part of their description]. This is a [pattern name] — a point where [brief consequence if no human reviews]. I'm inserting a Human-in-the-Loop step here so that [human role] can [action] before the automation [continues/writes/sends]."
133
139
 
134
- Wait for confirmation. Do not proceed to schema design until the user confirms. **Running non-interactively (CI/headless — no user available to answer):** treat the recommendation as accepted when the signal is clear-cut (an explicit approval / review / sign-off requirement), add the HITL step, and record that you did so in the final report; only skip it and report the open decision when the signal is ambiguous.
140
+ Proceed straight to schema design after saying this — do not wait for a reply. Record the decision prominently in the final report so the user can remove the step if they disagree. Only skip adding it and report the open decision when the signal is genuinely ambiguous (not just "no explicit HITL mention" — the signals table above is itself the ambiguity test).
135
141
 
136
142
  **Example:**
137
143
  > User: "Build an automation that reads support tickets, uses AI to generate an RCA, and updates the ticket in ServiceNow."
138
144
  >
139
- > Agent: "I noticed that the automation writes AI-generated content directly back to ServiceNow. This is a write-back validation pattern — if the RCA is incorrect and nobody reviews it, wrong data goes into production tickets. I recommend inserting a Human-in-the-Loop step so that a support lead can review and optionally edit the RCA before the update is applied. Should I add it?"
145
+ > Agent: "I noticed that the automation writes AI-generated content directly back to ServiceNow. This is a write-back validation pattern — if the RCA is incorrect and nobody reviews it, wrong data goes into production tickets. I'm inserting a Human-in-the-Loop step so that a support lead can review and optionally edit the RCA before the update is applied."
140
146
 
141
147
  ---
142
148
 
143
149
  ## Step 3 — Choose Task Type
144
150
 
145
- Present the user with three options. Do not choose on their behalf or perform any registry search.
151
+ **The options differ by surface.** Never block here — pick the option that best fits the surface and the business description, state the choice, and proceed. Only ask when the user is actually present and available; in a non-interactive run, infer and move on.
152
+
153
+ ### Surface: Flow
154
+
155
+ Infer the right option from the signals below and state your choice — do not perform a registry search first, and do not wait for the user to pick before proceeding.
146
156
 
147
157
  | # | Option | Node type | Description |
148
158
  |---|---|---|---|
@@ -150,37 +160,65 @@ Present the user with three options. Do not choose on their behalf or perform an
150
160
  | 2 | **New Coded Action App** | `uipath.human-in-the-loop.coded-action-app` | Scaffold a new React + TypeScript app inside the solution — full UI control |
151
161
  | 3 | **Existing Deployed App** | `uipath.human-in-the-loop.coded-action-app` | Reference an app already deployed to Orchestrator |
152
162
 
153
- > **If the user's request is purely business-oriented** (no mention of a deployed app, coded action app, or custom UI): skip the question and proceed directly with QuickForm. Do not ask. Say: "I'll use QuickForm — it's inline, no deployment step needed, and works for most approval and review tasks."
163
+ > **Default: QuickForm.** Pick QuickForm unless the request explicitly names a deployed app, a coded action app, or a custom UI requirement — those are the only signals that point at options 2 or 3. State the choice, do not ask: "I'll use QuickForm — it's inline, no deployment step needed, and works for most approval and review tasks. You can swap in a Coded Action App or an existing deployed app later if you need one."
154
164
 
155
- > **If the user is unsure or says "just pick one":** Default to QuickForm. Say: "I'll use QuickForm — it's the quickest to set up and works for most approval and review tasks. You can always upgrade to a Coded Action App later."
156
-
157
- | User selects | Next step |
165
+ | Option chosen | Next step |
158
166
  |---|---|
159
167
  | QuickForm | Read [How to write a QuickForm HITL node](references/hitl-node-quickform.md) for Steps 1–2, then continue with Step 4 |
160
168
  | New Coded Action App | Read [How to scaffold a new Coded Action App](references/hitl-node-coded-action-app.md) for Step 4c details, then continue with Step 4 |
161
- | Existing Deployed App → ask: "What is the name of the deployed action app?" | Read [How to wire an existing deployed Action App](references/hitl-node-apptask.md) for Step 4b details, then continue with Step 4 |
169
+ | Existing Deployed App — the request must already name the app | Read [How to wire an existing deployed Action App](references/hitl-node-apptask.md) for Step 4b details, then continue with Step 4 |
162
170
 
163
- **Fallback rules — what to do when the chosen path hits a blocker:**
171
+ **Fallback rules — never block on these, fall back and state what you did:**
164
172
 
165
173
  | Path | Blocker | Response |
166
174
  |---|---|---|
167
- | Existing Deployed App | App not found in Orchestrator | "I couldn't find an app with that name. Would you like to try a different name, or fall back to QuickForm while you prepare the app?" |
168
- | New Coded Action App | No `dist/` build present in the source path | "The source folder doesn't have a `dist/` build yet. Run your build first (`npm run build` or equivalent), then come back. Or I can set up a QuickForm now so the flow is wired and ready — you can swap in the app later." |
169
- | New Coded Action App | User can't provide a source path | "If you don't have the app code ready yet, I'll use QuickForm to wire the HITL checkpoint. You can replace it with a Coded Action App once it's built." |
170
- | Any custom app | Auth expired (401 on API call) | "The session looks expired — run `uip login` to refresh your credentials, then retry." |
175
+ | Existing Deployed App | App not found in Orchestrator, or no app name was given | Fall back to QuickForm and proceed. State: "I couldn't find (or wasn't given) a deployed app name, so I used QuickForm instead. Point me at a real app name and I'll swap it in." |
176
+ | New Coded Action App | No `dist/` build present in the source path | Fall back to QuickForm and proceed. State: "The source folder doesn't have a `dist/` build yet, so I wired a QuickForm for now — run your build and ask me to swap in the Coded Action App once it's ready." |
177
+ | New Coded Action App | No source path given | Fall back to QuickForm and proceed. State: "No app source path was given, so I used QuickForm to wire the checkpoint now. Point me at the app code and I'll replace it with a Coded Action App." |
178
+ | Any custom app | Auth expired (401 on API call) | Fall back to QuickForm and proceed. State: "The session looked expired, so I used QuickForm rather than stall on re-authenticating. Run `uip login` and ask me to swap in the app when you're ready." |
179
+
180
+ ---
181
+
182
+ ### Surface: Case
183
+
184
+ Infer the right option from the description below — do not pull the registry first, and do not wait for the user to pick before proceeding.
185
+
186
+ | # | Option | Fingerprint | Description |
187
+ |---|---|---|---|
188
+ | 1 | **QuickForm (file-based schema)** | separate `<TaskLabel>.hitl.json` file + `hitlType: "quick"` context entry in the action task | Structured form fields in a `.hitl.json` file alongside `caseplan.json`. Action Center renders fields at runtime. No deployed app needed. |
189
+ | 2 | **App-based action task** | `data.name` and `data.folderPath` as `=bindings.<id>` references + `data.actionCatalogName` | Uses a deployed Action Center app with custom input/output fields. Requires the app to exist in Orchestrator. |
190
+
191
+ > **Default: QuickForm.** Pick QuickForm unless the request explicitly names a deployed Action Center app. State the choice, do not ask: "I'll use QuickForm — it's the quickest to set up, supports structured form fields, and doesn't need a deployed app. You can upgrade to an app-based task later if you need a custom UI layout."
192
+
193
+ > **Build vs design time.** QuickForm in case management must round-trip both ways: the JSON written here is what Studio Web's case designer reads (design time), and what `uip maestro case validate` + Action Center render at runtime (build time). Always validate after writing.
194
+
195
+ | Option chosen | Next step |
196
+ |---|---|
197
+ | QuickForm (file-based schema) | Read [references/hitl-casetask-action.md — Path 1](references/hitl-casetask-action.md#path-1--quickform-file-based-schema-no-deployed-app), then continue with Step 4 |
198
+ | App-based action task — the request must already name the app | Read [references/hitl-casetask-action.md — Path 2](references/hitl-casetask-action.md#path-2--app-based-action-task-deployed-action-center-app), then continue with Step 4 |
199
+
200
+ **Fallback rules — never block on these, fall back and state what you did:**
201
+
202
+ | Path | Blocker | Response |
203
+ |---|---|---|
204
+ | App-based | App not found in registry or `action-apps-index.json`, or no app name was given | Fall back to QuickForm and proceed. State: "I couldn't find (or wasn't given) that app, so I used QuickForm instead. Point me at a real app name and I'll swap it in." |
205
+ | QuickForm | Schema design rejected on validate (e.g. duplicate field IDs, missing primary outcome) | Fix the schema yourself from the validator's error and re-validate. Apply Step 4b checks. Note the fix in the final report — do not pause to re-show the schema first. |
206
+ | Any | Auth expired (401 on API call) | Fall back to QuickForm and proceed. State: "The session looked expired, so I used QuickForm rather than stall on re-authenticating. Run `uip login` and ask me to swap in the app when you're ready." |
171
207
 
172
208
  ---
173
209
 
174
210
  ## Step 4 — Common configuration
175
211
 
176
- | Timeout | "How long before the task times out if nobody acts? (default: 24 hours)" |
177
- | Priority | "What priority should this task have? Options: Low, Medium, High (default: Low)" |
212
+ Never block on these — use the stated default when no answer is available, write it into the node, and note the default in the final report so the user can change it.
213
+
214
+ | Timeout | Default: 24 hours. If the description states or implies a different duration, use that instead. |
215
+ | Priority | Default: Low. If the description states or implies urgency (e.g. "high priority", "urgent", "time-sensitive"), use High or Medium accordingly. Write the chosen value into the node's `priority` field — asking the question is not enough; the value must land in the node. |
178
216
 
179
217
  ---
180
218
 
181
- ## Step 4b — Schema Design Rules (QuickForm only)
219
+ ## Step 4b — Schema Design Resilience (QuickForm — Flow and Case)
182
220
 
183
- Apply these rules unconditionally while designing the schema.
221
+ Apply these checks while designing the schema, before writing it — per Critical Rule 1, do not wait on the user to confirm. Applies equally to Flow QuickForm nodes and Case QuickForm action tasks — same `fields[]` + `outcomes[]` shape, same `direction` semantics.
184
222
 
185
223
  ### Field direction
186
224
 
@@ -196,14 +234,15 @@ Pick direction based on what the human does with the field:
196
234
 
197
235
  ### Field types
198
236
 
199
- Use the JS/JSON type that fits the field: `string`, `number`, `boolean`, `date`, or `file`. These are the only valid values — do not use `text`.
237
+ Use the JS/JSON type that fits the field: `string`, `number`, `boolean`, `date`, or `file`. These are the only valid values — do not use `text`. Case also supports `datetime` (distinct from `date`, for full date+time values) — see [hitl-casetask-action.md](references/hitl-casetask-action.md) for the Case-specific type table.
200
238
 
201
239
  ### Vague or incomplete schema descriptions
202
240
 
203
241
  If the user says something like "just add some fields" or "use whatever makes sense":
204
242
 
205
- 1. Infer sensible defaults from the upstream data and downstream needs visible in the `.flow` file.
206
- 2. If there are no upstream nodes to bind to (flow is just a trigger), use output-direction fields only.
243
+ 1. Infer sensible defaults from the upstream data and downstream needs visible in the `.flow` file (Flow) or in `caseplan.json` upstream task `outputs[]` and `root.data.uipath.variables` (Case).
244
+ 2. Show the proposed schema explicitly before writing: "Here's what I'm proposing — let me know if you want to change anything."
245
+ 3. If there is nothing upstream to bind to (Flow with only a trigger; Case with this as the first task), use output-direction fields only and note: "There are no upstream values to pull data from, so the reviewer will fill in all fields from scratch."
207
246
 
208
247
  ### Empty field labels block validation
209
248
 
@@ -266,6 +305,27 @@ After writing, validate:
266
305
  uip maestro flow validate <file> --output json
267
306
  ```
268
307
 
308
+ ### Surface: Case
309
+
310
+ Read the `caseplan.json` to identify the target stage. Write an `action` task directly into `stage.data.tasks[lane][]`. **Direct JSON write is the only supported method** — the `uipath-maestro-case` skill ships no `hitl` CLI subcommand (unlike Flow's `uip maestro flow hitl add`).
311
+
312
+ Full reference: **[references/hitl-casetask-action.md](references/hitl-casetask-action.md)** — three task JSON shapes (QuickForm, generic, app-based), field reference, assignee handling, post-write verification, and downstream output access.
313
+
314
+ | Path chosen in Step 3 | What gets written |
315
+ |---|---|
316
+ | QuickForm | A `<TaskLabel>.hitl.json` schema file (unified `fields[]` with `direction`, `outcomes[]`) + action task in `caseplan.json` with `data.context[hitlType].value: "quick"`, `_schemaFileId` (placeholder UUID), and `hitlSchemaId` (matches `schemaId` in `.hitl.json`). `data.inputs[]` and `data.outputs[]` are empty arrays. No `root.data.uipath.bindings[]` entries. Apply Step 4b schema-design checks before writing. |
317
+ | App-based | Action task with `data.actionCatalogName`, `data.name` and `data.folderPath` as `=bindings.<id>` references. Add 2 root-level bindings. |
318
+
319
+ After writing, validate (build-time check — must pass before reporting success):
320
+
321
+ ```bash
322
+ uip maestro case validate <caseplan.json> --output json
323
+ ```
324
+
325
+ > `uip maestro case validate` is the only `uip maestro case` CLI used by this skill on the Case surface. All authoring is direct JSON.
326
+
327
+ ---
328
+
269
329
  ### Surface: Low-Code Agent
270
330
 
271
331
  The Low-Code Agent escalation CLI (`uip agent escalation add`) is currently in-flight. Until it ships, configure manually:
@@ -296,9 +356,46 @@ response = interrupt(CreateTask(
296
356
 
297
357
  ### Surface: Maestro
298
358
 
299
- QuickForm and coded-action-app HITL nodes are both supported on Maestro BPMN processes — `uipath.human-in-the-loop.quick-form` and `uipath.human-in-the-loop.coded-action-app` are registered element types in the BPMN validator ([bpmn-spec.json](../uipath-maestro-bpmn/validator/bpmn-spec.json)), same node-type strings as the Flow surface. Write the node directly into the `.bpmn` XML as a `bpmn:UserTask` with a `uipath:activity` extension element (see the `Actions.HITL` extension type in the validator spec for the app-based/coded-action-app XML shape and context fields — `appId`, `appVersion`, `actions`, `key`, `taskTitle`).
359
+ QuickForm and coded-action-app HITL nodes are both supported on Maestro BPMN processes. `uipath.human-in-the-loop.quick-form` and `uipath.human-in-the-loop.coded-action-app` are registered as **registry shortcut names** in the BPMN validator ([bpmn-spec.json](../uipath-maestro-bpmn/validator/bpmn-spec.json)) — these are palette/discovery identifiers, not literal XML to write. There is no dedicated CLI subcommand for Maestro (unlike Flow's `uip maestro flow hitl add`) — write the node directly into the `.bpmn` XML.
360
+
361
+ **Confirmed node shape (verified by direct reproduction against a real Studio Web BPMN process with a working, editable QuickForm task):**
362
+
363
+ ```xml
364
+ <bpmn:task id="Activity_InvoiceApproval" name="Invoice Approval">
365
+ <bpmn:extensionElements>
366
+ <uipath:activity version="v1">
367
+ <uipath:type value="Actions.HITL" version="v2" />
368
+ <uipath:context>
369
+ <uipath:input name="hitlType" type="string" value="quick" />
370
+ <uipath:input name="taskTitle" type="string" value="Please review this invoice and approve or reject" />
371
+ <uipath:input name="labels" type="string" />
372
+ <uipath:input name="priority" type="string" value="Medium" />
373
+ <uipath:input name="actionCatalogName" type="string" />
374
+ <uipath:input name="enableActionableNotifications" type="boolean" value="false" />
375
+ <uipath:input name="assignmentCriteria" type="string" />
376
+ <uipath:input name="recipient" type="json" />
377
+ <uipath:input name="_schemaFileId" type="string" value="<see file-id callout below>" />
378
+ <uipath:input name="hitlSchemaId" type="string" value="<matches schemaId in the .hitl.json sidecar>" />
379
+ <uipath:inputSchema type="jsonSchema"><![CDATA[{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"invoiceid":{"type":"string","title":"Invoice ID"},"amount":{"type":"number","title":"Amount"}},"required":[]}]]></uipath:inputSchema>
380
+ </uipath:context>
381
+ <uipath:input name="HitlTaskArguments" type="json" target="bodyField"><![CDATA[{"invoiceid":"INV-1001","amount":500}]]></uipath:input>
382
+ <uipath:output name="Action" type="string" source="=Action" var="invoiceDecision" options="[{&#34;value&#34;:&#34;Approve&#34;,&#34;label&#34;:&#34;Approve&#34;},{&#34;value&#34;:&#34;Reject&#34;,&#34;label&#34;:&#34;Reject&#34;}]" />
383
+ </uipath:activity>
384
+ </bpmn:extensionElements>
385
+ <bpmn:incoming>edge_into_task</bpmn:incoming>
386
+ <bpmn:outgoing>edge_out_of_task</bpmn:outgoing>
387
+ </bpmn:task>
388
+ ```
389
+
390
+ Notes on what's easy to get wrong:
391
+ - **Element is `bpmn:task`, not `bpmn:UserTask`.** `bpmn-spec.json`'s generic `Actions.HITL` XML template uses `bpmn:UserTask` and `version="v1"` — that template is for the app-based/coded-action-app path (its `context` fields are `appId`, `appVersion`, `actions`, `key`, `taskTitle`). A real QuickForm task exported from Studio Web is a plain `bpmn:task` with `uipath:type value="Actions.HITL" version="v2"`. Use the shape above for QuickForm; the spec's template for app-based.
392
+ - **`<uipath:inputSchema>` (last child of `<uipath:context>`) and `<uipath:input name="HitlTaskArguments">` (sibling of `<uipath:context>`, not inside it) are both required.** Without them the "Edit Schema" canvas in Studio Web doesn't open at all — confirmed by direct reproduction. This mirrors the Case surface's `data.inputSchema`/`data.inputs[]` requirement — see [hitl-casetask-action.md § Step 3](references/hitl-casetask-action.md) for the parallel Case shape and full field-by-field rationale.
393
+ - **The `Action` output requires a matching process-level variable declaration** — add `<uipath:inputOutput id="<varId>" name="Action" type="string" elementId="<taskId>" />` inside the process's top-level `<uipath:variables version="v1">` block.
394
+ - **A separate `<TaskLabel>.hitl.json` sidecar file is required**, same shape as the Case surface's (`title`, `fields[]` with `direction`/optional `colSpan`/`binding` or `variable`, `outcomes[]` with **no** `action` key, `schemaId`) — see [hitl-casetask-action.md § Step 2](references/hitl-casetask-action.md) for the exact shape; it's identical across both surfaces.
395
+ - **`_schemaFileId` cannot be authored blind — it is a server-assigned foreign key, not a UUID you invent.** A placeholder value makes "Edit Schema" fail silently (a `404` on Studio Web's internal `FileOperations/File/Rename` call, confirmed by direct reproduction). There is no `uip` CLI command that resolves this today. **Never block on this.** Write a fresh placeholder UUID v4, finish the rest of the node, validate, and move on — do not attempt the live reconciliation yourself and do not stop to ask about it. State plainly in the final report: "This task's schema was written with a placeholder `_schemaFileId`, so Studio Web's 'Edit Schema' canvas won't open for it yet. Making it editable requires resolving the real file ID Studio Web assigns to the `.hitl.json` after upload (`GET /api/Project/{projectId}/FileOperations/Structure`) and pushing it back with a targeted single-file update (`PUT /api/Project/{projectId}/FileOperations/File/{fileId}`) — not another whole-project `uip solution upload`, which mints a new random ID for every file and undoes the fix. Ask me to do this reconciliation if you want the schema editable in Studio Web." This is a real product/tooling gap the user can act on later, not something to resolve mid-task.
396
+ - **Diagram-interchange edges are required for the connector lines to render, even though the logical `bpmn:sequenceFlow`s already exist.** Every `bpmn:sequenceFlow` needs a matching `bpmndi:BPMNEdge` (with two `di:waypoint` points, aligned to the source/target shapes' connecting edges) in the `bpmndi:BPMNPlane` — omitting it leaves the nodes logically connected but visually disconnected in the canvas. Confirmed by direct reproduction.
300
397
 
301
- Design the schema per Step 4b, confirm it with the user, then validate frequently (`uip maestro bpmn validate <file>.bpmn --output json`) while wiring the node so any shape mistakes surface immediately rather than at deploy time. In Maestro, field names in `outputs`/`inOuts` must exactly match declared process variable names and types.
398
+ Design the schema per Step 4b — never block waiting on the user, per Critical Rule 1 — then validate frequently (`uip maestro bpmn validate <file>.bpmn --output json`) while wiring the node so any shape mistakes surface immediately rather than at deploy time. In Maestro, field names in `outputs`/`inOuts` must exactly match declared process variable names and types.
302
399
 
303
400
  ---
304
401
 
@@ -326,3 +423,4 @@ After completing the wiring:
326
423
  - **[How to scaffold a new Coded Action App](references/hitl-node-coded-action-app.md)** — Read this when the user wants to build a new React app inside the solution. Covers full project template, UUID generation, solution CLI commands, and post-creation build steps.
327
424
  - **[HITL business pattern recognition](references/hitl-patterns.md)** — Read this during Step 2 / Step 2b to identify whether a process needs a human checkpoint and which pattern applies. Includes proactive recommendation language and when NOT to recommend HITL.
328
425
  - **[Action Center URL patterns](../uipath-tasks/references/action-center-urls.md)** (in `uipath-tasks` skill) — Read this before surfacing any Action Center task URL to the user. Covers the missing-tenant-slug anti-pattern and the API-host vs UI-host mapping.
426
+ - **[Case Action Task (HITL)](references/hitl-casetask-action.md)** — Case surface: action task JSON, QuickForm vs app-based paths, `.hitl` file format, context entries, field binding, and downstream output access.
@@ -0,0 +1,415 @@
1
+ # HITL Case Action Task — Implementation Reference
2
+
3
+ The agent writes an `action` task into a stage of `caseplan.json`. **Direct JSON write is the primary method on the Case surface.** Unlike the Flow surface (`uip maestro flow hitl add`), the `uipath-maestro-case` skill ships no single `hitl add` CLI subcommand for the HITL-specific parts (`context[]` entries, `.hitl.json` linkage) — edit `caseplan.json` directly per the path-specific JSON shapes below.
4
+
5
+ > If the stage or case predates required entry/exit/completion rules (see the checklist below), `uip maestro case` does have CLI mutation commands for those (`stage-entry-conditions`, `stage-exit-conditions`, `case-exit-conditions`, `task-entry-conditions` — each with an `add` subcommand). Prefer them over hand-writing that JSON when the case project already exists as a file you can pass to the CLI. If you're editing a caseplan.json given to you directly (not one you scaffolded yourself with these commands), it's simplest to just include the correct rule shapes directly per the examples below.
6
+
7
+ Two paths exist. **Never block on choosing — infer the path from the business description using the table below (§ Common business descriptions → path selection) and proceed. Do not wait for the user to pick.**
8
+
9
+ | Path | When to use | Requires |
10
+ |---|---|---|
11
+ | **QuickForm** | Structured form fields, no deployed app needed | A separate `.hitl.json` schema file written alongside `caseplan.json` |
12
+ | **App-based action task** | Existing deployed Action Center app with a custom form | `task-type-id` from registry + `tasks describe` |
13
+
14
+ > **If the user is unsure or says "just pick one":** Default to QuickForm. Say: "I'll use QuickForm — it's the quickest to set up and works for most approval and review tasks. You can always upgrade to a deployed Action Center app later."
15
+
16
+ > **Build time vs design time.** A case action task lives in two surfaces:
17
+ > - **Design time** — the JSON written into `caseplan.json` (what this skill produces). Studio Web's case designer round-trips this JSON; the QuickForm schema must be valid here.
18
+ > - **Build / runtime time** — `uip maestro case validate` accepts it, `uip solution upload` packs it, and Action Center renders the form to the assignee at runtime.
19
+ >
20
+ > Every shape documented below is required to round-trip in both. After writing, always run `uip maestro case validate <caseplan.json> --output json`.
21
+
22
+ ---
23
+
24
+ ## Step 1 — Extract the Task Configuration Through Conversation
25
+
26
+ **Never block on this.** Infer each answer below from the business description; only ask if the user is actually present and it would help. Defaults when nothing in the description settles it: recipient → a group named after the relevant team (e.g. "finance-team", "data-enrichment-team" — infer the team name from context); priority → Low, per Step 4.
27
+
28
+ | What you need to know | Where to infer it from |
29
+ |---|---|
30
+ | What the reviewer sees | Data the automation already extracted or produced upstream |
31
+ | What they decide or fill in | Whether the description says "approve/reject" (decision only) or "fill in", "correct", "enrich" (data entry) |
32
+ | Who receives the task | A named person/email or team/group mentioned in the description; otherwise infer a sensible team name from the business context |
33
+ | Priority | Any urgency language in the description ("urgent", "high priority") → High/Medium; otherwise Low |
34
+
35
+ **Common business descriptions → path selection:**
36
+
37
+ | Description | Path |
38
+ |---|---|
39
+ | "Reviewer approves invoice; sees ID + amount, clicks Approve/Reject" | QuickForm — `inputs[]` (read-only) + `outcomes[]` |
40
+ | "Human fills in missing vendor name and cost center, then submits" | QuickForm — `outputs[]` (writable) |
41
+ | "Reviewer edits an AI-drafted email, then sends or discards" | QuickForm — `inOuts[]` for the body |
42
+ | "Finance team approves expense claims before payment" | QuickForm — group assignee, outcomes are Approve/Reject |
43
+ | "Manager approves a leave request" | QuickForm — user email assignee, outcomes are Approve/Reject |
44
+ | "Legal reviews and signs off on a contract with custom fields" | App-based — deployed app with custom form layout |
45
+ | "Agent fills in form that a human corrects before submitting" | App-based — outputs populate downstream task inputs |
46
+
47
+ ---
48
+
49
+ ## Path 1 — QuickForm (file-based schema, no deployed app)
50
+
51
+ The form schema lives in a separate `.hitl.json` file that sits alongside `caseplan.json` in the case project directory. Action Center renders the fields at runtime from the schema — no deployed app required.
52
+
53
+ > **What makes Path 1 (QuickForm) unique — checklist before you finish:**
54
+ > - ✅ A `<TaskLabel>.hitl.json` file is **created** alongside `caseplan.json`
55
+ > - ✅ `data.context[hitlType].value` is `"quick"` (not `"custom"`)
56
+ > - ✅ `data.context[_schemaFileId].value` is a **plain UUID v4 string** — e.g. `"f1e2d3c4-b5a6-7890-abcd-ef1234567890"`. Never an `=bindings.xxx` expression.
57
+ > - ✅ `data.context[hitlSchemaId].value` is a **plain UUID v4 string** matching `schemaId` in the `.hitl.json` file. Never an `=bindings.xxx` expression.
58
+ > - ✅ `data.inputs[]` and `data.outputs[]` are **empty arrays** (`[]`)
59
+ > - ❌ `data.name` and `data.folderPath` do NOT exist — those are App-based (Path 2) only
60
+ > - ❌ No `=bindings.xxx` expressions anywhere in the task JSON — those are App-based only
61
+ > - ❌ No top-level `bindings[]` entries added
62
+
63
+ ### Step 1 — Design the Schema
64
+
65
+ Use these roles to plan the fields before writing:
66
+
67
+ | Role | `field.direction` | Human can… | Use for |
68
+ |---|---|---|---|
69
+ | Input field | `"input"` | Read only | Context the human needs to make a decision |
70
+ | Output field | `"output"` | Write | Data the automation needs back |
71
+ | InOut field | `"inOut"` | Read + modify | Data the human can see and optionally correct |
72
+
73
+ **Supported field types:** `string`, `number`, `boolean`, `date`, `datetime` (canonical — see [hitl-node-quickform.md](hitl-node-quickform.md) for the same vocabulary on the Flow surface; legacy aliases like `text`/`dateTime` are silently normalized by the runtime, but write the canonical form directly)
74
+
75
+ **Design rules:**
76
+ - Input fields: bind to upstream case variables via `=vars.<varId>` — never hardcode literals from runtime data
77
+ - Output fields: only what downstream tasks actually consume; set `required: true` for mandatory outputs
78
+ - `outcomes[]`: use domain-specific names (Approve/Reject, not just Submit)
79
+ - Keep it focused — don't add fields the case won't use
80
+
81
+ **Never block on this — write the schema, per Critical Rule 1 in SKILL.md, and record it in the final report so the user can adjust it afterward.**
82
+
83
+ ### Step 2 — Write the `.hitl.json` File
84
+
85
+ Generate two UUID v4 values:
86
+ - `schemaId` — identity of the schema, stored inside the file and referenced from the action task
87
+ - `fileId` — placeholder file system ID (Studio Web assigns the real one when it processes the project; use a fresh UUID v4 as a stable placeholder)
88
+
89
+ Create a file named `<TaskLabel>.hitl.json` in the case project directory (alongside `caseplan.json`).
90
+
91
+ The file uses a **unified `fields[]` array** — every field has a `direction` property that determines its role. This is the format the sync runtime reads (`parsed?.fields`).
92
+
93
+ ```json
94
+ {
95
+ "title": "Invoice Approval",
96
+ "fields": [
97
+ {
98
+ "id": "invoiceid",
99
+ "label": "Invoice ID",
100
+ "type": "string",
101
+ "direction": "input",
102
+ "colSpan": 6,
103
+ "binding": "=vars.invoiceIdVar"
104
+ },
105
+ {
106
+ "id": "amount",
107
+ "label": "Amount",
108
+ "type": "number",
109
+ "direction": "input",
110
+ "colSpan": 6,
111
+ "binding": "=vars.amountVar"
112
+ },
113
+ {
114
+ "id": "notes",
115
+ "label": "Notes",
116
+ "type": "string",
117
+ "direction": "output",
118
+ "colSpan": 6,
119
+ "variable": "vars.notes"
120
+ },
121
+ {
122
+ "id": "decision",
123
+ "label": "Decision",
124
+ "type": "string",
125
+ "direction": "output",
126
+ "colSpan": 6,
127
+ "variable": "vars.decision"
128
+ }
129
+ ],
130
+ "outcomes": [
131
+ { "id": "outcome-0", "name": "Approve", "type": "string", "isPrimary": true },
132
+ { "id": "outcome-1", "name": "Reject", "type": "string", "isPrimary": false }
133
+ ],
134
+ "schemaId": "a3f7c2d1-8b4e-4f9a-b2c5-6d8e1f3a7b9c"
135
+ }
136
+ ```
137
+
138
+ **Field shape reference:**
139
+
140
+ | Property | Required | Notes |
141
+ |---|---|---|
142
+ | `id` | Yes | lowercase label, strip spaces and non-alphanumeric characters (no separator). `"Invoice ID"` → `"invoiceid"`, `"Due Date"` → `"duedate"` |
143
+ | `label` | Yes | Display label in the form. Validator rejects empty. |
144
+ | `type` | Yes | `string`, `number`, `boolean`, `date`, `datetime` |
145
+ | `direction` | Yes | `"input"`, `"output"`, or `"inOut"` |
146
+ | `colSpan` | No | Grid width hint for the form layout (e.g. `6` of 12). Safe to omit — confirmed optional against a real Studio Web export. |
147
+ | `binding` | For `direction: "input"` / `"inOut"` | `"=vars.<varId>"` — reads from a case variable. A literal is also valid as an `=`-expression (e.g. `="Acme Corp"`), confirmed against a real export, but prefer a variable binding when the value comes from upstream data. |
148
+ | `variable` | For `direction: "output"` / `"inOut"` | The **full** `"vars.<name>"` reference (no leading `=`) the output writes to — not a bare name. Downstream tasks read it as `=vars.<name>`. |
149
+ | `required` | No | `true` for mandatory outputs — omit if false |
150
+
151
+ **`outcomes[]` shape:** `{ "id": "<slug>", "name": "<OutcomeName>", "type": "string", "isPrimary": <bool> }` — first entry is the primary action. **No `action` key** — confirmed against a real Studio Web export; an earlier draft of this doc invented one, do not reintroduce it.
152
+
153
+ > **`title` is required, top-level in the `.hitl.json` file** — the form's display title in Action Center, separate from both the task's `displayName` (canvas label) and `data.taskTitle` (the assignee-facing message). All three are independent strings and do not need to match.
154
+
155
+ ### Step 3 — Write the Action Task in `caseplan.json`
156
+
157
+ ```json
158
+ {
159
+ "id": "ta1b2c3d4",
160
+ "elementId": "Stage_aB3kL9-ta1b2c3d4",
161
+ "type": "action",
162
+ "displayName": "Invoice Approval",
163
+ "isRequired": true,
164
+ "shouldRunOnlyOnce": false,
165
+ "entryConditions": [
166
+ {
167
+ "id": "Condition_EnTk1",
168
+ "displayName": "Entry Rule 1",
169
+ "rules": [ [ { "id": "Rule_EnTk1", "rule": "current-stage-entered" } ] ]
170
+ }
171
+ ],
172
+ "data": {
173
+ "taskTitle": "Please review this invoice and approve or reject",
174
+ "context": [
175
+ { "name": "hitlType", "type": "string", "value": "quick" },
176
+ { "name": "taskTitle", "type": "string", "value": "Please review this invoice and approve or reject" },
177
+ { "name": "labels", "type": "string" },
178
+ { "name": "priority", "type": "string", "value": "Medium" },
179
+ { "name": "actionCatalogName", "type": "string" },
180
+ { "name": "enableActionableNotifications","type": "boolean", "value": "false" },
181
+ { "name": "assignmentCriteria", "type": "string", "value": "user" },
182
+ { "name": "recipient", "type": "json", "body": { "Type": 2, "Value": "approver@company.com" } },
183
+ { "name": "_schemaFileId", "type": "string", "value": "f1e2d3c4-b5a6-7890-abcd-ef1234567890" },
184
+ { "name": "hitlSchemaId", "type": "string", "value": "a3f7c2d1-8b4e-4f9a-b2c5-6d8e1f3a7b9c" }
185
+ ],
186
+ "inputs": [
187
+ { "name": "invoiceid", "type": "string", "displayName": "Invoice ID", "target": "bodyField", "value": "=vars.invoiceIdVar" },
188
+ { "name": "amount", "type": "number", "displayName": "Amount", "target": "bodyField", "value": "=vars.amountVar" }
189
+ ],
190
+ "outputs": [
191
+ { "name": "Action", "type": "string", "displayName": "Action", "source": "=Action", "var": "invoiceDecision",
192
+ "options": [ { "value": "Approve", "label": "Approve" }, { "value": "Reject", "label": "Reject" } ] }
193
+ ],
194
+ "inputSchema": {
195
+ "$schema": "http://json-schema.org/draft-07/schema#",
196
+ "type": "object",
197
+ "properties": {
198
+ "invoiceid": { "type": "string", "title": "Invoice ID" },
199
+ "amount": { "type": "number", "title": "Amount" }
200
+ },
201
+ "required": []
202
+ }
203
+ }
204
+ }
205
+ ```
206
+
207
+ > **`displayName`, `inputs[]`/`outputs[]`, and `inputSchema` are all required — this is the part an earlier draft of this doc got wrong.** It previously claimed `data.inputs[]`/`data.outputs[]` "are always empty arrays for QuickForm — the schema is in the `.hitl.json` file." That is false. Confirmed against a real Studio Web export and by direct reproduction: without `inputSchema` (a JSON-Schema mirror of the input fields) and populated `inputs[]`/`outputs[]` on the task node itself, Studio Web's "Edit Schema" canvas does not open at all — clicking it does nothing, silently. The `.hitl.json` file and the task's own `data.*` fields are **two parallel representations of the same schema** that must both be written; neither one alone is sufficient.
208
+ > - `inputs[]`: one entry per input field, `name` = field `id`, `value` = the same `=`-expression as that field's `binding` in `.hitl.json`.
209
+ > - `outputs[]`: one entry per **output field with a `variable`**, plus one always-present `Action` entry whose `options[]` mirrors `outcomes[]` from `.hitl.json` (`{value, label}` pairs) — this is the decision/outcome the reviewer picks, not a separate field.
210
+ > - `inputSchema`: a `draft-07` JSON Schema, `properties` keyed by the same field ids as `inputs[]`, each `{"type": "<field type>", "title": "<field label>"}`.
211
+
212
+ **Context entry notes:**
213
+
214
+ | `name` | Notes |
215
+ |---|---|
216
+ | `hitlType` | Always `"quick"` for QuickForm |
217
+ | `_schemaFileId` | **Not a value you can invent — see the callout below.** It must be the real, backend-assigned file ID of the uploaded `.hitl.json`, not a fresh UUID. |
218
+ | `hitlSchemaId` | Must match the `schemaId` value inside the `.hitl.json` file exactly. |
219
+ | `taskTitle` | Appears both as `data.taskTitle` (top-level) and in `context[]` — **both are required**. |
220
+ | `labels` | No `value` — leave the entry present but empty. |
221
+ | `priority` | `"Low"` \| `"Medium"` (default) \| `"High"` \| `"Critical"` |
222
+ | `actionCatalogName` | No `value` for QuickForm — leave the entry present but empty. |
223
+ | `enableActionableNotifications` | Leave as `"false"` unless the user explicitly wants email notifications. |
224
+ | `assignmentCriteria` | `"user"` when assigning to a specific email. Omit the `value` (or omit the entry) for group rules. |
225
+ | `recipient` | `{ "Type": 2, "Value": "<email>" }` for email; `{ "Type": 1, "Value": "<group>" }` for group; `{ "Type": 3, "Value": "=vars.<varId>" }` for runtime-resolved assignee. |
226
+
227
+ > **`_schemaFileId` cannot be authored blind — it is a server-assigned foreign key, not a UUID you invent.** Confirmed by direct reproduction against Studio Web: a placeholder UUID here makes "Edit Schema" fail with a `404` on `FileOperations/File/Rename` (the fileId in that failed request is whatever placeholder was written) — Studio Web does **not** silently reconcile it on upload, contrary to what an earlier draft of this doc claimed. There is currently no `uip` CLI command that resolves this.
228
+ >
229
+ > **Never block on this.** Write a fresh placeholder UUID v4, finish the task, validate, and move on — do not attempt the reconciliation below yourself, and do not stop to ask about it. State plainly in the final report that this task's schema won't be editable in Studio Web until the real file ID is reconciled, and offer to do it if asked:
230
+ > 1. Upload the project once with any placeholder value in `_schemaFileId` (`uip solution upload`).
231
+ > 2. Look up the real ID Studio Web assigned to the `.hitl.json` file via `GET /api/Project/{projectId}/FileOperations/Structure` (find the entry whose `name` matches the `.hitl.json` filename — an internal Studio Web REST endpoint, not a `uip` CLI verb).
232
+ > 3. Patch `_schemaFileId` in `caseplan.json` to that real ID.
233
+ > 4. Push the corrected `caseplan.json` back with a **targeted single-file update** — `PUT /api/Project/{projectId}/FileOperations/File/{fileId}` (same file's own real ID) — **not** another whole-project `uip solution upload`. A second whole-project upload re-imports everything and mints a **new** random file ID for every file, including `.hitl.json`, immediately invalidating whatever you just patched.
234
+ >
235
+ > This is a real gap, not just a documentation gap: today there is no supported CLI path to make a freshly-authored QuickForm task's schema editable in Studio Web without dropping to this undocumented internal API. It's a follow-up the user can request, never a mid-task blocker.
236
+
237
+ ### Step 4 — Discover Upstream Variables
238
+
239
+ Read available case variables from the top-level `variables` field in `caseplan.json` (current schema is flat — no `root` wrapper; see [case-schema.md](../../uipath-maestro-case/references/case-schema.md#top-level-shape) in the case skill):
240
+
241
+ ```json
242
+ {
243
+ "inputs": [ { "id": "<varId>", "name": "invoiceId", "type": "string" } ],
244
+ "outputs": [],
245
+ "inputOutputs":[]
246
+ }
247
+ ```
248
+
249
+ For cross-task references, source values come from upstream task `outputs[].var` — see [bindings-and-expressions.md](../../../uipath-maestro-case/references/bindings-and-expressions.md) in the case skill for the full discovery procedure.
250
+
251
+ > **No root-level bindings needed for QuickForm.** Unlike App-based (Path 2), QuickForm does **not** add entries to the top-level `bindings[]` array.
252
+
253
+ ### Post-Write Verification (QuickForm)
254
+
255
+ Run `uip maestro case validate <caseplan.json> --output json`. Confirm:
256
+
257
+ - `.hitl.json` file exists in the project directory with `schemaId`, `fields[]` (unified array with `direction`), `outcomes[]`
258
+ - Action task `type === "action"`
259
+ - `data.taskTitle` non-empty and matches `data.context[taskTitle].value`
260
+ - `data.context[]` has entries for: `hitlType` (`"quick"`), `_schemaFileId`, `hitlSchemaId`, `taskTitle`, `labels`, `priority`, `actionCatalogName`, `enableActionableNotifications`
261
+ - `data.context[hitlSchemaId].value` matches `schemaId` in the `.hitl.json` file
262
+ - `data.inputs[]`/`data.outputs[]` are populated (mirroring `.hitl.json`'s fields) and `data.inputSchema` is present — see the callout in Step 3
263
+ - top-level `bindings[]` is **not** modified by this path
264
+
265
+ ### Downstream Output Access (QuickForm)
266
+
267
+ Each field in `outputs[]` and `inOuts[]` exposes its value downstream via the field's `variable` property — the **full** `"vars.<name>"` string, not a bare name:
268
+
269
+ ```json
270
+ { "id": "decision", "variable": "vars.decision", "type": "string", "label": "Decision" }
271
+ ```
272
+
273
+ Downstream task input value: `"=vars.decision"`. The selected outcome is available via the task's `Action` output (see Step 3).
274
+
275
+ For the full cross-task wiring procedure, see [bindings-and-expressions.md](../../../uipath-maestro-case/references/bindings-and-expressions.md).
276
+
277
+ ---
278
+
279
+ ## Path 2 — App-Based Action Task (deployed Action Center app)
280
+
281
+ The task form is defined by a deployed Action Center app. Inputs are shown to the human; outputs are collected from the form and usable downstream via `=vars.<var>` expressions.
282
+
283
+ ### Step 1 — Discover the App
284
+
285
+ ```bash
286
+ # Pull the registry first (requires uip login)
287
+ uip maestro case registry pull
288
+
289
+ # Search for action apps
290
+ uip maestro case registry search --type action-apps --output json
291
+
292
+ # Get a specific app by name (check action-apps-index.json if CLI search fails)
293
+ uip maestro case registry get "<app-name>" --type action-apps --output json
294
+ ```
295
+
296
+ > CLI search is known to fail for action-apps — always fall back to direct inspection of `~/.uipcli/case-resources/action-apps-index.json`. Use `id` (not `entityKey`), `deploymentTitle` (not `name`), and `deploymentFolder.fullyQualifiedName` for the folder path.
297
+
298
+ ### Step 2 — Get the Input/Output Schema
299
+
300
+ ```bash
301
+ uip maestro case tasks describe --type action --id "<action-app-id>" --output json
302
+ ```
303
+
304
+ Returns `inputs[]` and `outputs[]`. Capture both — they define what the human fills in and what the automation reads back.
305
+
306
+ ### Step 3 — Write Root-Level Bindings
307
+
308
+ Add 2 entries to the top-level `bindings[]` array — one for `name` and one for `folderPath`. Deduplicate by `(default + resource + resourceKey)`.
309
+
310
+ ```json
311
+ {
312
+ "id": "bG0SraLpg",
313
+ "name": "name",
314
+ "type": "string",
315
+ "resource": "app",
316
+ "resourceKey": "Shared.Contract Review App",
317
+ "propertyAttribute": "name",
318
+ "default": "Contract Review App"
319
+ },
320
+ {
321
+ "id": "bH1iJK2lm",
322
+ "name": "folderPath",
323
+ "type": "string",
324
+ "resource": "app",
325
+ "resourceKey": "Shared.Contract Review App",
326
+ "propertyAttribute": "folderPath",
327
+ "default": "Shared"
328
+ }
329
+ ```
330
+
331
+ `resourceKey` = `<folderPath>.<deploymentTitle>`. Binding IDs: `b` + 8 chars.
332
+
333
+ For the full binding procedure, see [bindings/impl-json.md](../../../uipath-maestro-case/references/plugins/variables/bindings/impl-json.md) in the case skill.
334
+
335
+ ### Step 4 — Write the Task
336
+
337
+ ```json
338
+ {
339
+ "id": "ta1b2c3d4",
340
+ "elementId": "Stage_aB3kL9-ta1b2c3d4",
341
+ "type": "action",
342
+ "isRequired": true,
343
+ "shouldRunOnlyOnce": false,
344
+ "entryConditions": [
345
+ {
346
+ "id": "Condition_EnTk1",
347
+ "displayName": "Entry Rule 1",
348
+ "rules": [ [ { "id": "Rule_EnTk1", "rule": "current-stage-entered" } ] ]
349
+ }
350
+ ],
351
+ "data": {
352
+ "taskTitle": "Please review this contract and fill in the required fields",
353
+ "name": "=bindings.bG0SraLpg",
354
+ "folderPath": "=bindings.bH1iJK2lm",
355
+ "actionCatalogName": "Contract Review App",
356
+ "assignmentCriteria": "user",
357
+ "recipient": { "Type": 2, "Value": "reviewer@company.com" },
358
+ "context": [
359
+ { "name": "hitlType", "type": "string", "value": "custom" }
360
+ ],
361
+ "inputs": [],
362
+ "outputs": []
363
+ }
364
+ }
365
+ ```
366
+
367
+ `data.name` and `data.folderPath` MUST be `=bindings.<id>` references — never string literals.
368
+ `data.inputs[]` and `data.outputs[]` are populated from the `tasks describe` response in Step 2.
369
+
370
+ > **`hitlType` is `"custom"` for app-based tasks.** App-based tasks have no schema file at all — the form is defined by the deployed app itself, not by a schema document. **Never write `_schemaFileId` or `hitlSchemaId` for an app-based task** — those two context entries exist only on the QuickForm path (Path 1), where they identify the `.hitl.json` schema file. An app-based task is fully described by `data.name`/`data.folderPath` (the bindings to the deployed app) plus `data.inputs[]`/`data.outputs[]` (from `tasks describe`) — nothing else identifies its "schema."
371
+
372
+ For the full `inputs[]`/`outputs[]` variable shapes, see [action/impl-json.md](../../../uipath-maestro-case/references/plugins/tasks/action/impl-json.md).
373
+
374
+ ---
375
+
376
+ ## Post-Write Verification (all paths)
377
+
378
+ ```bash
379
+ uip maestro case validate <caseplan.json> --output json
380
+ ```
381
+
382
+ | Path | Verify |
383
+ |---|---|
384
+ | QuickForm | `.hitl.json` file present with `title`, `fields[]`, `outcomes[]` (no `action` key), `schemaId`; task has `displayName`; `data.context[]` has `hitlType: "quick"`, `_schemaFileId`, `hitlSchemaId` (matches `.hitl.json` `schemaId`), `taskTitle`; `data.inputs[]`/`data.outputs[]` populated (not empty) and `data.inputSchema` present, mirroring `.hitl.json`'s fields; no `actionCatalogName` value; no top-level `bindings[]` entries added |
385
+ | App-based | `type: "action"`, `data.taskTitle` non-empty, `data.name` and `data.folderPath` start with `=bindings.`, `data.context[]` has `hitlType: "custom"` and **no** `_schemaFileId`/`hitlSchemaId` entries (app-based tasks have no schema file), top-level `bindings[]` has 2 entries with `resource: "app"` and `propertyAttribute` = `name` / `folderPath`, `data.actionCatalogName` matches the deployed `deploymentTitle` |
386
+ | Both | The task node has `entryConditions[]` set — e.g. `current-stage-entered` (see the Step 3/4 examples above). Without it, validate fails with `Task has no entry rules`. This is a case-structural requirement, not HITL-specific — it applies to every action task written via direct JSON. |
387
+
388
+ If validate reports errors, **never report success**. Diagnose from the JSON output and fix before reporting back. A validate error unrelated to the HITL task itself (e.g. `Case has no completion rules` on a stage/case that predates your edit) is a pre-existing gap in the case plan, not something this skill introduces — surface it to the user rather than reverse-engineering the CLI to silence it.
389
+
390
+ ---
391
+
392
+ ## Downstream Output Access
393
+
394
+ | Path | Outputs available downstream? | How |
395
+ |---|---|---|
396
+ | QuickForm | Yes — every `outputs[]` and `inOuts[]` field in the `.hitl.json` | `field.variable` is already the full `=vars.<name>` reference (minus the leading `=`) |
397
+ | App-based | Yes — every `data.outputs[]` entry | `=vars.<output.var>` |
398
+
399
+ **QuickForm example:**
400
+
401
+ ```json
402
+ { "id": "decision", "variable": "vars.decision", "type": "string", "label": "Decision" }
403
+ ```
404
+
405
+ Downstream task input: `"value": "=vars.decision"`.
406
+
407
+ **App-based example:**
408
+
409
+ ```json
410
+ { "name": "decision", "type": "string", "id": "out_decision", "var": "decisionVar" }
411
+ ```
412
+
413
+ Downstream task input: `"value": "=vars.decisionVar"`.
414
+
415
+ For the full cross-task wiring procedure, see [bindings-and-expressions.md](../../../uipath-maestro-case/references/bindings-and-expressions.md).
@@ -97,17 +97,13 @@ Flatten both `solutionResources` and `availableResources` folder groups into a s
97
97
  **Selection rules:**
98
98
 
99
99
  - **Exactly one match** → use it, proceed to Step 3.
100
- - **Multiple matches** → present a numbered list to the user and wait for their choice before proceeding:
100
+ - **Multiple matches** → never block waiting for a choice. Pick the best match automatically (prefer an exact case-insensitive name match in a `Shared` folder, else the first result), proceed, and state the choice plus the alternatives so the user can correct it:
101
101
 
102
- > I found multiple apps matching that name. Which one should I use?
103
- > 1. **Invoice Approval** — Shared / Coded Action
104
- > 2. **Invoice Approval** — Finance / VB Action
105
- >
106
- > Reply with the number of the app you want.
102
+ > I found multiple apps matching that name and used **Invoice Approval** (Shared / Coded Action). Other matches, if this was the wrong one: **Invoice Approval** (Finance / VB Action). Tell me to swap it if I picked wrong.
107
103
 
108
- Use `nextPageCursor` to fetch additional pages if the list is truncated. Do not proceed until the user selects.
104
+ Use `nextPageCursor` to fetch additional pages if the list is truncated.
109
105
 
110
- - **Zero matches** → stop and tell the user: "No deployed app named `<APP_NAME>` was found. Verify the name and that the app is deployed, then try again. Show them the app name, folder name and type"
106
+ - **Zero matches** → never block. Fall back to QuickForm (per SKILL.md Step 3's fallback rule) and proceed. State: "No deployed app named `<APP_NAME>` was found, so I used QuickForm instead. Verify the name and that the app is deployed, then ask me to swap it in."
111
107
 
112
108
  ### Step 3 — Retrieve app configuration
113
109
 
@@ -88,7 +88,7 @@ The source path provided by the user must already contain the built `dist/` fold
88
88
  rsync -a --exclude='node_modules' "<SOURCE_PATH>/" "<SOLUTION_DIR>/<APP_NAME>/source/"
89
89
  ```
90
90
 
91
- > The `dist/` folder must exist inside `<SOURCE_PATH>` before copying — it is the compiled output that the solution packages. If it is missing, ask the user to run their build first.
91
+ > The `dist/` folder must exist inside `<SOURCE_PATH>` before copying — it is the compiled output that the solution packages. If it is missing, never block waiting for a build: fall back to QuickForm instead (per SKILL.md Step 3's fallback rule), proceed, and state that you did so — the user can ask you to swap in the Coded Action App once it's built.
92
92
 
93
93
  ---
94
94
 
@@ -6,7 +6,7 @@ The agent writes the `uipath.human-in-the-loop.quick-form` node directly into th
6
6
 
7
7
  ## Step 1 — Extract the Schema Through Conversation
8
8
 
9
- Before designing the schema, ask these focused questions if the business description doesn't answer them. **Ask all missing ones in a single message — never one at a time.** **Running non-interactively (CI/headless — no user available to answer):** do not ask — infer the answers from the prompt and any upstream `.flow` data, and proceed to design the schema. Only stop and report the open decision if the request is too ambiguous to pick a sensible default.
9
+ **Never block on this.** Infer the answers to the questions below from the prompt and any upstream `.flow` data, and proceed straight to schema design — do not wait for a reply. If the user is present and volunteers this information unprompted, use it. Only stop and report the open decision if the request is genuinely too ambiguous to pick a sensible default.
10
10
 
11
11
  | What you need to know | Question to ask |
12
12
  |---|---|
@@ -93,7 +93,7 @@ The node schema uses `fields[]` entries inside `inputs.schema`. Use these concep
93
93
  - `outcomes`: use domain-specific names (Approve/Reject, not just Submit)
94
94
  - Keep it focused — don't add fields the automation won't use
95
95
 
96
- **Show the designed schema to the user and confirm before writing the node.** **Running non-interactively (CI/headless — no user available to answer):** do not block — design the schema from the prompt and any upstream `.flow` data, write the node, and record the chosen schema prominently in the final report. Only stop and report the open decision if the request is too ambiguous to pick a sensible default. (A prompt that already specifies the fields, outcomes, and output shape is never too ambiguous.)
96
+ **Never block on this — write the node, don't wait to show the schema first.** Design the schema from the prompt and any upstream `.flow` data, write the node, and record the chosen schema prominently in the final report so the user can adjust it afterward. Only stop and report the open decision if the request is genuinely too ambiguous to pick a sensible default. (A prompt that already specifies the fields, outcomes, and output shape is never too ambiguous.)
97
97
 
98
98
  ---
99
99
 
@@ -147,8 +147,6 @@ A monetary action above a threshold or of a certain type requires human sign-off
147
147
 
148
148
  ## Proactive HITL Recommendation
149
149
 
150
- If a business description contains any of the above signals but the user has not asked for a HITL, flag it:
150
+ **Never block on this.** If a business description contains any of the above signals but the user has not asked for a HITL, state it and proceed straight to Step 3 (schema design) — do not wait for a reply:
151
151
 
152
- > "This process includes [signal]. Before the automation [action], a human should review [data]. I recommend inserting a HITL node here — want me to add it?"
153
-
154
- Then proceed to Step 3 (schema design) only after the user confirms.
152
+ > "This process includes [signal]. Before the automation [action], a human should review [data]. I'm inserting a HITL node here — remove it if you don't want it."
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "schemaVersion": 2,
3
- "skillsVersion": "1.201.0-preview.637",
3
+ "skillsVersion": "1.201.0",
4
4
  "targetCli": "^1.201.0"
5
5
  }