---
name: uipath-api-workflow
description: "UiPath API Workflow assistant — author, run, validate, package, publish, deploy, and troubleshoot JSON workflows for `uip api-workflow`. Load for ANY create/edit of a `Workflow.json` / API workflow project; with `evals/` present, tests come first (TDD). Covers Sequence, Assign, JavaScript, If (#Wrapper/#Then/#Else), ForEach, DoWhile, Break, TryCatch, Wait, Response, nested; files as JobAttachment refs via File to Base64 / Base64 to File (`$helpers.file.*`, `serializeData()`, `--input-file`/`--output-dir`); HTTP / IS connector activities via `uip api-workflow registry`. Operate: run, IS connections, pack/publish/deploy. Test/eval: `evals/<scope>/eval-sets/` datasets (exact-match, Evaluations panel); loop until green. Triggers on API workflows, project type \"Api\", JSON with `document.dsl`/`do[]`, those activity types, or file/base64 handling. Agent evals (`evals/eval-sets/`, no scope) & coded agents→uipath-agents. Flow & its evals→uipath-maestro-flow. .xaml/coded RPA→uipath-rpa. Coded Apps→uipath-coded-apps."
allowed-tools: Bash, Read, Write, Edit, Glob, Grep
---

# UiPath API Workflow Assistant

<!--skill-flavor:surface-summary:start-->
Build, run, and publish UiPath API Workflows: JSON conforming to CNCF Serverless Workflow DSL 1.0.0 with UiPath activity extensions. Workflows run through `@uipath/api-workflow-executor` and `uip api-workflow run`, and package as `Type: "Api"` projects through `uip solution pack`.
<!--skill-flavor:surface-summary:end-->
<!--skill-flavor:host-command-contract:start-->
<!--skill-flavor:host-command-contract:end-->

> **TDD gate — read first (rule 22).** For create/edit requests, check `<project>/evals/` beside `Workflow.json`, never at workspace or solution root. If absent, Evaluations is off: do not ask about tests or loop mode; author normally. If present, stop before authoring and ask whether existing rows remain/change or empty tests should be added, and whether to run/retry until all pass or author once. After both answers, declare schemas, write/update evals first, then author. A request not to ask skips these questions, not runtime consent; run rows only when requested. Later behavior changes require asking whether affected expectations should change.

## When to Use This Skill

Use for API workflow JSON creation/editing and activities including Sequence, Assign, JavaScript, If, ForEach, DoWhile, Break, TryCatch, Wait, Response, HTTP Request, and connector activities. Use the connector and testing references for Studio Web connector workflows and project `evals/` layouts.

<!--skill-flavor:surface-lifecycle-scope:start-->
- Local runs, validation, build/packaging, publishing
<!--skill-flavor:surface-lifecycle-scope:end-->
- User wants to **handle a file** in an API workflow — take a file input, send a file as base64 to an API, turn a base64 payload back into a file, or asks about `JobAttachment`, `$helpers.file`, `serializeData()`, `--input-file` / `--output-dir`. See [references/files-and-base64.md](references/files-and-base64.md)
- Starting a workflow from a connector event (Slack button clicked, new Outlook calendar entry), or inspecting/changing an existing trigger (`call: "UiPath.IntSvcEvent"`). See [references/trigger-authoring-guide.md](references/trigger-authoring-guide.md)
<!--skill-flavor:surface-operations-scope:start-->
- Operating published workflows
<!--skill-flavor:surface-operations-scope:end-->

Do not use for `.flow` Maestro flows (`uipath-maestro-flow`), `.xaml` or coded RPA (`uipath-rpa`), coded agents (`uipath-agents`), or Coded Web Apps (`uipath-coded-apps`). API-workflow evals are only `evals/` beside `Workflow.json` using `evals/<scope>/eval-sets/`; `evals/eval-sets/` is for low-code agents and Flow evals for `uipath-maestro-flow`.

## Core Principles

0. **Escalate judgment-based forks before building.** If a connection is unavailable, no curated activity exists, an undocumented HTTP fallback is needed, an assumed input is missing, or structurally different workflows are plausible, perform only shared discovery, then stop with trade-offs and a recommendation. Do not build every branch. Mechanical choices need no escalation.
1. **Know before writing.** Read an existing workflow before editing and the relevant template before creating.
<!--skill-flavor:runtime-validation-contract:start-->
2. **Start minimal, iterate to correct.** Add one activity at a time. Run with `--no-auth --output json` after each addition. Fix what breaks. Repeat.
3. **Validate before running.** `uip api-workflow validate` is autonomous/offline. `run` is runtime validation, may access HTTP or connections, and requires consent.
<!--skill-flavor:runtime-validation-contract:end-->
4. **Fix by category:** Structure > Expression > Activity Config > Logic.

## Critical Rules

1. **Workflow JSON.** Top level has `document` with `dsl: "1.0.0"`, `evaluate` with `language: "javascript"` and `mode: "strict"`, and `do` containing one root sequence. Root sequence names may vary; read the file. See [references/workflow-file-format.md](references/workflow-file-format.md).

2. **WorkflowStart.** It is first in the root sequence, hydrates variable defaults into `$context.variables`, forwards inputs to `$input`, and must not be removed, renamed, or modified. Only it uses `isTransparent: true`.

3. **Activity objects and keys.** Each activity is one single-key object in a `do` array. Keys are globally unique, including wrapper suffixes such as `#Wrapper`, `#Then`, `#Else`, and `#Body`.

4. **Exports.** Every activity should export output. Assign uses `{ ...$context, variables: { ...$context.variables, ...$output } }`; all others use `{ ...$context, outputs: { ...$context?.outputs, "<ActivityKey>": $output } }`. See [references/expressions-and-context.md](references/expressions-and-context.md).

<!--skill-flavor:designer-literal-runtime-comparison:start-->
5. **Literal expressions.** In Assign `set`, Response, If `when`, and variable contexts, string literals must be expressions such as `"${'literal'}"`, because Studio Web rewrites a bare `"literal"` into `"${literal}"` on save and that fails at runtime; numbers, booleans, and references need no wrapping. Connector `bodyParameters`, `queryParameters`, and `pathParameters` instead use bare literals; references remain expressions. See [references/connector-activity-discovery.md](references/connector-activity-discovery.md) and [references/troubleshooting.md](references/troubleshooting.md#studioweb-roundtrip-pitfalls).
<!--skill-flavor:designer-literal-runtime-comparison:end-->

6. **Assign.** Each Assign sets exactly one variable. Studio Web collapses multi-key `set`; use sequential Assign activities and merge each single key through the variables export.

7. **If.** Use `If_N#Wrapper` containing `If_N`, `If_N#Then`, and `If_N#Else`. Both branches end with `then: "exit"`; `when` is wrapped in `${...}`. See [references/control-flow-patterns.md](references/control-flow-patterns.md).

8. **Loops.** ForEach and DoWhile require `#Body`. ForEach uses index-aware accumulation, resetting on iteration 0; DoWhile uses simple accumulation. `each` and `at` are plain names, not expressions.

9. **DoWhile.** `for.in` is always `"${ [1] }"`; `doWhile` controls repetition. The body must update the condition variable or the loop may be infinite.

10. **Nested loops.** Use distinct iterator and index names for each loop.

11. **Loop/catch bindings.** Declare `for.each`, `for.at`, and `catch.as` without `$`, but reference them in expressions/scripts with `$`: `"row"` binds `$row`, `"idx"` binds `$idx`, and `"err"` binds `$err`. Omitting `$` causes an undefined-name error.

12. **Break.** It exits only the innermost loop and is valid only inside `#Body`. Put it inside an If; `break` must be string `"true"`, with `then: "exit"` and `set: "${$input}"`. To exit nested loops, set a flag and check it in the outer loop. See [references/control-flow-patterns.md](references/control-flow-patterns.md#5-conditional-break-inside-a-loop).

13. **Workflow inputs.** Use `$workflow.input.<name>`, never `$input.<name>` from a non-first activity; `$input` is current task input and may be prior output.

14. **JavaScript.** Scripts read `$context`, `$workflow`, and `$input` as globals and must return a value. Keep standard Studio Web `run.script.arguments` scaffolding: `"${{ \"$context\": $context, \"$workflow\": $workflow, \"$input\": $input }}"`; runtime ignores it.

15. **Response.** `markJobAsFailed` is a sibling of `response`. Always use `then: "end"`; `then: "exit"` is for branches/loops. Object responses use one expression, e.g. `"${{ key: $context.variables.value }}"`, not independently interpolated fields. Single values may use `"${$context.outputs.Activity}"` or `"${'done'}"`. `${ { ... } }` and `${{ ... }}` are both valid; stay consistent.
<!--skill-flavor:response-roundtrip-validation:start-->
    - **On-disk is authoritative.** After Studio Web saves, treat disk as authoritative and rerun `uip api-workflow run --no-auth` after reapplying needed workarounds.
<!--skill-flavor:response-roundtrip-validation:end-->

16. **Connectors and HTTP are registry-generated only.** Run `uip api-workflow registry resolve` then `stub`; never guess `uiPathActivityTypeId`, `metadata.configuration`, activity kind, endpoint, `SlotKey`, or `ExportBucketKey`; use stub output verbatim.
   - A keyword `resolve` miss is not proof of no curated activity because it AND-matches tokens. Identify product/vendor with `uip is connectors list --filter`, then enumerate with `uip is activities list <connector-key>` before fallback.
   - IntSvc/vendor activities require successful `uip is connections ping <uuid>`. If listing is empty/fails, try unfiltered listing, then `--all-folders`, and ping another matching connection.
   - If none ping successfully, stop and ask whether to continue with explicit placeholder consent or wait for a fixed connection. Never silently choose.
   - Never put replacement sentinels in `with.connectionId`, `connectionResourceId`, or an HTTP URL. Re-stub with a real value before writing.
   - After every stub, check required fields using resource description or stub inputs, then re-stub with `--inputs` if needed.
   - Connector parameters use flat dotted keys and bare literals; do not use `${'literal'}`.
   - Do not use `UiPath.Http` with a vendor connection UUID. IntSvc results are wrapped; read `$context.outputs.<ExportBucketKey>.content.<field>`.
<!--skill-flavor:connector-solution-registration:start-->
   - In Solutions mode, sync IntSvc bindings with `uip api-workflow bindings sync --workflow <Workflow.json>` and refresh with `uip solution resources refresh --solution-folder <path>`. Skip for HTTP, non-connectors, and standalone projects.
<!--skill-flavor:connector-solution-registration:end-->
   - See [references/connector-activity-discovery.md](references/connector-activity-discovery.md) for the discovery flow, field-shape rules, and multipart.

16a. **A connector-event trigger is a separate catalog, a separate activity shape, and a second artifact.** When the workflow must start from an event (Slack button clicked, new Outlook calendar entry), run `uip api-workflow registry resolve "<keyword>" --kind trigger` then `registry stub` — never hand-author. Place the stub in exactly one slot: the root Sequence's `do` array, directly after `WorkflowStart` (`do[0].Sequence_1.do[1]`) — never inside an If / ForEach / TryCatch, never after another activity, never a second trigger. `validate` rejects a misplaced or second trigger. A `GenericTrigger` needs `--object-name`. Full flow, filter syntax, anti-patterns: [references/trigger-authoring-guide.md](references/trigger-authoring-guide.md).
<!--skill-flavor:trigger-binding-registration:start-->
    - **Run `uip api-workflow bindings sync` after every trigger add or edit.** It writes the `EventTrigger` entry in `bindings_v2.json` that registers the Orchestrator event trigger on deploy. **Without it the workflow validates, packs, publishes and deploys clean — and never fires.** No gate catches this. In Solutions mode follow with `uip solution resources refresh` (rule 16).
<!--skill-flavor:trigger-binding-registration:end-->
<!--skill-flavor:trigger-debug-contract:start-->
    - **A `webhooks` trigger cannot run locally without input.** `uip api-workflow run` replays a live event only for `polling` (side-effecting under rule 21); for either mode, `--input-arguments` shaped like the event payload exercises the rest of the workflow offline.
<!--skill-flavor:trigger-debug-contract:end-->

<!--skill-flavor:runtime-invocation-io:start-->
17. **CLI input.** Pass JSON as a string: `--input-arguments '{"key":"value"}'`; invalid JSON exits 1.

18. **CLI output.** Parse with `--output json`. Success: `{ "Result": "Success", "Code": "WorkflowRun", "Data": {...} }`; failure: `{ "Result": "Failure", "Message": "...", "Instructions": "..." }` with exit 1.
<!--skill-flavor:runtime-invocation-io:end-->

<!--skill-flavor:project-creation:start-->
19. **Project creation and publishing.** Scaffold with `uip api-workflow init <name>`; do not hand-assemble project files. Project commands include `build <projectDir>` and `pack <projectDir> <outputDir>`. Use `uip solution pack` and `uip solution publish`; there is no `uip api-workflow publish`. Solution type is `"Api"`.

19a. **Init shape and registration.** Run `uip api-workflow init <name> --output json` inside the solution directory. It creates `project.uiproj`, `Workflow.json`, `entry-points.json`, and `bindings_v2.json`, and registers the project in the nearest `.uipx`. Use `--skip-solution-registration` only when explicitly requested for a standalone CLI/local project. Always create a full project, never a lone workflow file. Do not use solution projects add/remove or change existing project IDs. For legacy `project.json`, initialize a fresh sibling and move content into its `Workflow.json`, or convert in place; see [references/troubleshooting.md](references/troubleshooting.md). Runtime success does not prove Studio Web compatibility; init-produced shape does.
<!--skill-flavor:project-creation:end-->

20. **Static validation.** Run `uip api-workflow validate <Workflow.json> --output json` as the last autonomous command in every author/edit cycle. On `Result: "Failure"`, read `Instructions`, fix the activity at its JSON path, and repeat until `Data.Status: "Valid"`. Prioritize semantic-tail errors over duplicate `oneOf` noise.

<!--skill-flavor:runtime-validation-limit:start-->
    Validation catches malformed JSON, unknown types, required-field errors, bad evaluate settings, duplicate/empty variables, and empty task lists; not broken connections, wrong resource IDs, runtime expression errors, unwrapped literals, or multi-key Assign sets — those need `uip api-workflow run` once the user consents.
<!--skill-flavor:runtime-validation-limit:end-->

<!--skill-flavor:runtime-execution-consent:start-->
21. **Runtime consent.** Never run `uip api-workflow run` without explicit consent. After validation, ask whether to skip, run `--no-auth`, or run with auth. Recommend `--no-auth` for control-flow-only workflows and HTTP with `ImplicitConnection`; recommend authenticated execution only for IntSvc after confirming real side effects. Authenticated calls may send emails, create tickets, or upload files. Loop-mode consent authorizes eval rows with `--no-auth`, but authenticated connector runs still require explicit consent. This gates only `uip api-workflow run`, never `uip solution pack`/`publish`: a build/package/publish request proceeds without the run question; a local run is a separate request, done only when asked.
<!--skill-flavor:runtime-execution-consent:end-->

22. **TDD gate.** Check `<project>/evals/` on every create/edit. Without it, do not offer tests, create the folder, or mention loop mode. With it, stop before modifying `Workflow.json` or evals and ask whether existing cases change or new cases are added, and whether to run/retry until all pass or author once. If rows exist, report their count and summarize each; if empty, propose 2–3 cases. After answers, declare `input.schema` and `output.schema`, update evals, author, then run rows only in loop mode or hand over in author-once mode. Behavior changes require identifying affected rows and asking whether expectations should change. A request not to ask keeps existing tests and does not authorize runtime. See [references/testing-and-evals.md](references/testing-and-evals.md) §3.

23. **Files are references, not bytes — and base64 is a file too.** File inputs and outputs are `JobAttachment` references (`{ ID, FullName, MimeType, Metadata? }`) to Orchestrator blobs; `$workflow.input.<file>` is never the bytes.
    - **The two activities.** Both are `run.script` tasks identified by their `$helpers.file.*` call (what `validate` checks): File to Base64 returns a new reference containing base64 text; Base64 to File returns a binary reference. The script must be exactly one `return` expression and nothing else. Studio Web silently drops preceding/trailing statements, a second argument, or an extra option key; `validate` catches only extra statements, so an extra argument or key can still break the activity. Put preprocessing in a separate JavaScript activity. See [references/files-and-base64.md](references/files-and-base64.md) for exact shapes and examples.
    - **Reading results.** Use `$context.outputs.<Key>.output`.
    - **Inlining content.** Use `<ref>.serializeData()` directly in an HTTP body or Response field; it is a deferred-read marker, so do not store it or use it in script logic. Nested in a JSON body, it works only for a base64 reference (the File to Base64 output); nesting a binary file's marker or a bare reference is a send-time error. Send a binary file as the whole body or convert it first.
    - **Naming.** `fileName` and `mimeType` apply only to a raw base64 string. References keep their name, and the engine sniffs type from bytes; a `.txt` round-trip can therefore become extensionless.
    - **Running.** Both helpers need Orchestrator blob storage:
<!--skill-flavor:file-run-cli:start-->
    `uip api-workflow run --no-auth` refuses such a workflow up front; run it signed in (`uip login`, no `--no-auth`) — it still needs the rule-21 "yes". Pass local files with `--input-file <name>=<path>` (uploaded, arriving as `$workflow.input.<name>`), collect returned files with `--output-dir <dir>` (each reference in the output gains a `LocalPath`), and `--folder-key <guid>` if the tenant's Attachments API requires a folder. In the printed output the CLI PascalCases keys (`ID` → `Id`).
<!--skill-flavor:file-run-cli:end-->
    Shapes, worked examples, and pitfalls: [references/files-and-base64.md](references/files-and-base64.md).

## Workflow Phases

### Phase 0: Discovery

Check the project directory for `evals/`, then read `evals/<scope>/eval-sets/*.json` and evaluators when present. For edits, read `Workflow.json`, keys, variables, schemas, and export patterns. For creates, read [assets/templates/api-workflow-template.json](assets/templates/api-workflow-template.json), the closest conditional/loop/nested-control-flow template, and [references/control-flow-patterns.md](references/control-flow-patterns.md) as needed. Apply rule 22 before authoring.

### Phase 1: Plan

Choose activities, unique keys, variables, inputs, outputs, and nesting. Use Assign for variables, JavaScript/JsInvoke for custom logic, If for branching, ForEach for collections, DoWhile for repetition, TryCatch for errors, Wait for pauses, Response for termination, Break inside an If, and registry-generated `UiPath.Http` or `UiPath.IntSvc` for HTTP/connectors. For files/base64, **File to Base64** encodes a file (input or downloaded) as base64 for an inline API body and **Base64 to File** turns a base64 payload back into a file (rule 23). Use generic connector activities only when registry discovery finds no curated operation. Read [references/task-types.md](references/task-types.md).

### Phase 2: Generate or Edit

Copy minimal shapes from references. Create from the template and place activities after `WorkflowStart` in the root sequence. For edits, preserve conventions and use sufficient unique context. When rule 22 applies, declare schemas before eval rows. Skeleton:

```json
{
  "document": { "dsl": "1.0.0", "name": "...", "version": "0.0.1", "namespace": "default", "metadata": { "variables": { "schema": { "format": "json", "document": { "type": "object", "properties": {}, "title": "Variables" } } } } },
  "input": { "schema": { "format": "json", "document": { "type": "object", "properties": {}, "title": "Inputs" } } },
  "output": { "schema": { "format": "json", "document": { "type": "object", "properties": {}, "title": "Outputs" } } },
  "do": [{ "Sequence_1": { "do": [{ "WorkflowStart": {} }] } }],
  "evaluate": { "mode": "strict", "language": "javascript" }
}
```

### Phase 3: Validate, Then Run With Consent

<!--skill-flavor:validation-run-lifecycle:start-->
```bash
uip api-workflow validate ./<project>/Workflow.json --output json
uip api-workflow run ./<project>/Workflow.json [--no-auth] --output json
```

Validate autonomously and fix until valid; then ask before running. Name the concrete side effect in the question (an email sent, a ticket created), then wait. If skipped, provide the exact command.
<!--skill-flavor:validation-run-lifecycle:end-->
<!--skill-flavor:runtime-troubleshooting:start-->
Triage failures as Structure > Expression > Activity Config > Logic; see [references/troubleshooting.md](references/troubleshooting.md).
<!--skill-flavor:runtime-troubleshooting:end-->

### Phase 4: Package, Publish, and Operate

<!--skill-flavor:deployment-lifecycle:start-->
Packaging needs a passing `validate` (rule 20), not a local run — on a build/package/publish request, pack right away (rule 21 gates `run`, never `pack`). Confirm init-produced shape, then:

```bash
uip solution pack <solutionDir> <outputDir> --name <PACKAGE_NAME> --version 1.0.0 --output json
uip solution publish <outputDir>/<package>.zip --tenant <TENANT_NAME> --output json
```

Publishing requires `uip login`. The packager detects `Type: "Api"`, validates/copies workflows, generates deployment metadata, and produces a `.nupkg` inside a `.zip`. After deployment, operate through Orchestrator/API triggers, jobs, connections, logs, and traces; local `uip api-workflow` verbs no longer operate the published workflow. See [references/operating-published-workflows.md](references/operating-published-workflows.md), delegating depth to `uipath-platform` or `uipath-troubleshoot` when appropriate.
<!--skill-flavor:deployment-lifecycle:end-->

<!--skill-flavor:quick-start-create:start-->
## Quick Start (CREATE from scratch)

```bash
uip solution init <SolutionName> --output json
cd <SolutionName>
uip api-workflow init <ProjectName> --output json
# If <ProjectName>/evals/ exists, stop and apply rule 22; otherwise edit after WorkflowStart.
uip api-workflow validate ./<ProjectName>/Workflow.json --output json
# Ask for consent, then run if approved:
uip api-workflow run ./<ProjectName>/Workflow.json --no-auth --output json
uip solution pack . ./build --name <PackageName> --version 1.0.0 --output json
uip login
uip solution publish ./build/<package>.zip --tenant <TenantName> --output json
```
<!--skill-flavor:quick-start-create:end-->

## Reference Navigation

| File | Use |
|---|---|
| [references/workflow-file-format.md](references/workflow-file-format.md) | JSON skeleton, schemas, variables, `WorkflowStart`, Studio Web structure |
| [references/http-retry-config.md](references/http-retry-config.md) | Workflow-level HTTP retry/backoff |
| [references/task-types.md](references/task-types.md) | Activity shapes, required fields, exports, mistakes |
| [references/control-flow-patterns.md](references/control-flow-patterns.md) | Nested If, loops, TryCatch, Break, branching, key uniqueness |
| [references/connector-activity-discovery.md](references/connector-activity-discovery.md) | Authoring HTTP Request / Gmail / Outlook / GitHub / Slack / etc. activities via `uip api-workflow registry resolve` + `stub` — discovery flow, connection verification, field-shape rules, multipart |
| [references/trigger-authoring-guide.md](references/trigger-authoring-guide.md) | Connector-event triggers: `registry resolve --kind trigger` + `stub`, `UiPath.IntSvcEvent` shape, mandatory `EventTrigger` binding, JMESPath filters, polling vs webhooks |
| [references/expressions-and-context.md](references/expressions-and-context.md) | Expressions, context, inputs, scripts, exports, strict mode |
| [references/files-and-base64.md](references/files-and-base64.md) | **Files & base64** — `JobAttachment` references, the File to Base64 / Base64 to File activities (exact JSON, `$helpers.file.*`), `serializeData()` for inline bodies/Responses, passing local files in and getting files out of a run, pitfalls |
<!--skill-flavor:cli-reference-navigation:start-->
| [references/cli-reference.md](references/cli-reference.md) | API workflow, solution, login, build, pack, validate, publish |
<!--skill-flavor:cli-reference-navigation:end-->
<!--skill-flavor:published-reference-navigation:start-->
| [references/operating-published-workflows.md](references/operating-published-workflows.md) | Published triggers, connections, jobs, logs, traces |
<!--skill-flavor:published-reference-navigation:end-->
| [references/troubleshooting.md](references/troubleshooting.md) | Runtime, structure, expression, connector, response, packaging, publish failures |
| [references/testing-and-evals.md](references/testing-and-evals.md) | Eval contract, scoring, raw outputs, test-until-green protocol |
<!--skill-flavor:reference-navigation-extra:start-->
<!--skill-flavor:reference-navigation-extra:end-->

## Templates

- [assets/templates/api-workflow-template.json](assets/templates/api-workflow-template.json) — empty valid skeleton.
- [assets/templates/conditional-workflow-example.json](assets/templates/conditional-workflow-example.json) — conditional branching/error handling.
- [assets/templates/loop-aggregation-example.json](assets/templates/loop-aggregation-example.json) — loop aggregation.
- [assets/templates/nested-control-flow-example.json](assets/templates/nested-control-flow-example.json) — deeply nested control flow.
- [assets/templates/file-base64-roundtrip-example.json](assets/templates/file-base64-roundtrip-example.json) — **Files** — a `document` file input → File to Base64 → Base64 to File → Response returning both references. The exact `run.script` shape Studio Web writes for the two activities (rule 23). Verified end-to-end with a signed-in run: local file in → `.base64` reference → decoded file out, bytes identical.
- [assets/templates/trigger-workflow-template.json](assets/templates/trigger-workflow-template.json) — event-driven skeleton: `WorkflowStart` → `UiPath.IntSvcEvent` trigger → Response reading the payload. Its `<REPLACE_WITH_*>` connection UUID and trigger type id are sentinels; re-stub for real values (rules 16, 16a).
<!--skill-flavor:template-execution-proof:start-->
- [assets/templates/connector-call-example.json](assets/templates/connector-call-example.json) — registry-generated HTTP with `ImplicitConnection`.
<!--skill-flavor:template-execution-proof:end-->
- [assets/templates/vendor-curated-call-example.json](assets/templates/vendor-curated-call-example.json) — IntSvc activity; replace its connection sentinel before writing.
<!--skill-flavor:solution-resource-template:start-->
- [assets/templates/solution-connection-resource-template.json](assets/templates/solution-connection-resource-template.json) — Solutions-mode IntSvc connection resource.
<!--skill-flavor:solution-resource-template:end-->

## Anti-patterns

- Do not use `call: "http"`; use registry-generated `UiPath.Http`.
- Do not wrap connector parameter literals as `${'literal'}`.
- Do not ship connection or URL replacement sentinels.
- Do not read later workflow inputs from `$input.<name>`.
- **Do NOT** treat a file input or a File to Base64 result as a string — both are `JobAttachment` references. Inline a file's content only with `<ref>.serializeData()` inside an HTTP body / Response, never in an Assign or script — and inside a JSON body field only on the File to Base64 output (`$workflow.input.document.serializeData()` nested in a body fails with "Raw bytes cannot be embedded in JSON"). See rule 23.
- **Do NOT** write `$helpers.fileToBase64(...)` / `$helpers.base64ToFile(...)` — the helpers live under `$helpers.file.`; `validate` rejects the task and the runtime says `is not a function`. See rule 23.
<!--skill-flavor:runtime-execution-antipattern:start-->
- Do not run autonomously or authenticated vendor calls without consent.
<!--skill-flavor:runtime-execution-antipattern:end-->
<!--skill-flavor:project-creation-antipatterns:start-->
- Do not hand-assemble legacy projects, emit a lone `Workflow.json`, or use solution projects add/remove.
<!--skill-flavor:project-creation-antipatterns:end-->
- Do not treat runtime, pack, or publish success as Studio Web compatibility proof.
- Do not copy expected eval outputs from PascalCased CLI display data; derive keys from `output.schema` and Response, using raw output for expectations.
- Do not author first when `evals/` exists; apply rule 22. Do not create or offer evals when absent. Do not change logic merely to satisfy stale expectations.

## Infinite Loop Prevention

If a command fails with the same error twice, investigate instead of retrying. Allow at most three attempts per operation, then stop and report what was tried.

<!--skill-flavor:authentication-remediation:start-->
- Authentication/organization errors: ask the user to run `uip login`.
<!--skill-flavor:authentication-remediation:end-->
- File-not-found errors: verify paths with `ls`.
- Repeated structural errors: reread the workflow and relevant reference.
