About uipath-api-workflow
UiPath skill for creating, editing, running, validating, and packaging API Workflows defined with CNCF Serverless Workflow DSL 1.0.0 and UiPath extensions. It also covers connector activities, triggers, and publishing through Solutions.
Key features
- 01Create and edit workflow JSON
- 02Run and validate workflows
- 03Build and package projects
- 04Discover connector activities
- 05Configure event triggers
Use cases
- 01Building workflows with HTTP or connector activities
- 02Testing a workflow locally
- 03Starting workflows from connector events
Install
Copy the command and run it in a terminal.
npx skills add https:/ / github.com/ uipath/ skills --skill uipath-api-workflowAfter installing, type/uipath-api-workflowin Claude Code to confirm it loaded.
Bundled files
References and scripts installed along with SKILL.md.
assets/templates/api-workflow-template.jsonconditional-workflow-example.jsonconnector-call-example.jsonfile-base64-roundtrip-example.jsonloop-aggregation-example.jsonnested-control-flow-example.jsonsolution-connection-resource-template.jsontrigger-workflow-template.jsonvendor-curated-call-example.jsonreferences/cli-reference.mdconnector-activity-discovery.mdcontrol-flow-patterns.mdexpressions-and-context.mdfiles-and-base64.mdhttp-retry-config.mdoperating-published-workflows.mdtask-types.mdtesting-and-evals.mdtrigger-authoring-guide.mdtroubleshooting.mdworkflow-file-format.mdDetails
From the project READMEUiPath API Workflow Assistant
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.
TDD gate — read first (rule 22). For create/edit requests, check
<project>/evals/besideWorkflow.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, Log Message, 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.
- Local runs, validation, build/packaging, publishing
- 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 - 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
- Operating published workflows
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
- 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.
- Know before writing. Read an existing workflow before editing and the relevant template before creating.
- Start minimal, iterate to correct. Add one activity at a time. Run with
--no-auth --output jsonafter each addition. Fix what breaks. Repeat. - Validate before running.
uip api-workflow validateis autonomous/offline.runis runtime validation, may access HTTP or connections, and requires consent.
- Fix by category: Structure > Expression > Activity Config > Logic.
Critical Rules
-
Workflow JSON. Top level has
documentwithdsl: "1.0.0",evaluatewithlanguage: "javascript"andmode: "strict", anddocontaining one root sequence. Root sequence names may vary; read the file. See references/workflow-file-format.md. -
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 usesisTransparent: true. -
Activity objects and keys. Each activity is one single-key object in a
doarray. Keys are globally unique, including wrapper suffixes such as#Wrapper,#Then,#Else, and#Body. -
Exports. Every activity except Log Message 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.
- Literal expressions. In Assign
set, Response, Ifwhen, 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. ConnectorbodyParameters,queryParameters, andpathParametersinstead use bare literals; references remain expressions. See references/connector-activity-discovery.md and references/troubleshooting.md.
-
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. -
If. Use
If_N#WrappercontainingIf_N,If_N#Then, andIf_N#Else. Both branches end withthen: "exit";whenis wrapped in${...}. See references/control-flow-patterns.md. -
Loops. ForEach and DoWhile require
#Body. ForEach uses index-aware accumulation, resetting on iteration 0; DoWhile uses simple accumulation.eachandatare plain names, not expressions. -
DoWhile.
for.inis always"${ [1] }";doWhilecontrols repetition. The body must update the condition variable or the loop may be infinite. -
Nested loops. Use distinct iterator and index names for each loop.
-
Loop/catch bindings. Declare
for.each,for.at, andcatch.aswithout$, but reference them in expressions/scripts with$:"row"binds$row,"idx"binds$idx, and"err"binds$err. Omitting$causes an undefined-name error. -
Break. It exits only the innermost loop and is valid only inside
#Body. Put it inside an If;breakmust be string"true", withthen: "exit"andset: "${$input}". To exit nested loops, set a flag and check it in the outer loop. See references/control-flow-patterns.md. -
Workflow inputs. Use
$workflow.input.<name>, never$input.<name>from a non-first activity;$inputis current task input and may be prior output. -
JavaScript. Scripts read
$context,$workflow, and$inputas globals and must return a value. Keep standard Studio Webrun.script.argumentsscaffolding:"${{ \"$context\": $context, \"$workflow\": $workflow, \"$input\": $input }}"; runtime ignores it. For logging, use Log Message, neverconsole.*in a script; its code is exactlyconsole.log|warn|error(<message>)with noreturn,export, or trailing;. See references/task-types.md. -
Response.
markJobAsFailedis a sibling ofresponse. Always usethen: "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. Never combine them:${{ { ... } }}passesvalidatebut fails at run time withUnexpected token '{'.
- **On-disk is authoritative.** After Studio Web saves, treat disk as authoritative and rerun `uip api-workflow run --no-auth` after reapplying needed workarounds.
- Connectors and HTTP are registry-generated only. Run
uip api-workflow registry resolvethenstub; never guessuiPathActivityTypeId,metadata.configuration, activity kind, endpoint,SlotKey, orExportBucketKey; use stub output verbatim.
- A keyword
resolvemiss is not proof of no curated activity because it AND-matches tokens. Identify product/vendor withuip is connectors list --filter, then enumerate withuip 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
--inputsif needed. - Connector parameters use flat dotted keys and bare literals; do not use
${'literal'}. - Do not use
UiPath.Httpwith a vendor connection UUID. IntSvc results are wrapped; read$context.outputs.<ExportBucketKey>.content.<field>. - IntSvc list and search activities that take a
nextPageparameter return one page per call. When the stub'swith.methodisGETand.contentis an array, add"maximumRecordsReturned": -1(or a positive cap) to the stub'swithand write no loop: the runtime fetches the pages, up to the cap, into one.contentlist. Add it by hand as a literal number; the stub omits it,--inputsdrops it, and an expression there is not evaluated. For another method, or when each page needs its own processing, loop on the activity's.pageoutput and stop when.pageis absent or.page.hasMorePagesis false. Never decide on the rawelements-next-page-tokenheader: it is present on every page, including the last. See references/connector-activity-discovery.md.
- In Solutions mode, sync IntSvc bindings with
uip api-workflow bindings sync --workflow <Workflow.json>and refresh withuip solution resources refresh --solution-folder <path>. Skip for HTTP, non-connectors, and standalone projects.
- See references/connector-activity-discovery.md for the discovery flow, field-shape rules, paging, 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.
- **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).
- **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.
-
CLI input. Pass JSON as a string:
--input-arguments '{"key":"value"}'; invalid JSON exits 1. -
CLI output. Parse with
--output json. Success:{ "Result": "Success", "Code": "WorkflowRun", "Data": {...} }; failure:{ "Result": "Failure", "Message": "...", "Instructions": "..." }with exit 1.
- Project creation and publishing. Scaffold with
uip api-workflow init <name>; do not hand-assemble project files. Project commands includebuild <projectDir>andpack <projectDir> <outputDir>. Useuip solution packanduip solution publish; there is nouip 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. Build throwaway probe workflows, such as one that only inspects connector data, outside the project and solution folders (for example under /tmp), and delete them before finishing; never leave extra projects in the solution. 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. Runtime success does not prove Studio Web compatibility; init-produced shape does.
- Static validation. Run
uip api-workflow validate <Workflow.json> --output jsonas the last autonomous command in every author/edit cycle. OnResult: "Failure", readInstructions, fix the activity at its JSON path, and repeat untilData.Status: "Valid". Prioritize semantic-tail errors over duplicateoneOfnoise.
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.
- Runtime consent. Never run
uip api-workflow runwithout explicit consent. After validation, ask whether to skip, run--no-auth, or run with auth. Recommend--no-authfor control-flow-only workflows and HTTP withImplicitConnection; 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 onlyuip api-workflow run, neveruip solution pack/publish: a build/package/publish request proceeds without the run question; a local run is a separate request, done only when asked.
-
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 modifyingWorkflow.jsonor 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, declareinput.schemaandoutput.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 §3. -
Files are references, not bytes — and base64 is a file too. File inputs and outputs are
JobAttachmentreferences ({ ID, FullName, MimeType, Metadata? }) to Orchestrator blobs;$workflow.input.<file>is never the bytes.- The two activities. Both are
run.scripttasks identified by their$helpers.file.*call (whatvalidatechecks): File to Base64 returns a new reference containing base64 text; Base64 to File returns a binary reference. The script must be exactly onereturnexpression and nothing else. Studio Web silently drops preceding/trailing statements, a second argument, or an extra option key;validatecatches 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 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.
fileNameandmimeTypeapply only to a raw base64 string. References keep their name, and the engine sniffs type from bytes; a.txtround-trip can therefore become extensionless. - Running. Both helpers need Orchestrator blob storage:
- The two activities. Both are
`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`).
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, the closest conditional/loop/nested-control-flow template, and 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, Log Message for logging, 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.
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:
{
"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
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.
Triage failures as Structure > Expression > Activity Config > Logic; see references/troubleshooting.md.
Phase 4: Package, Publish, and Operate
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:
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, delegating depth to uipath-platform or uipath-troubleshoot when appropriate.
Quick Start (CREATE from scratch)
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
Reference Navigation
| File | Use |
|---|---|
| references/workflow-file-format.md | JSON skeleton, schemas, variables, WorkflowStart, Studio Web structure |
| references/http-retry-config.md | Workflow-level HTTP retry/backoff |
| references/task-types.md | Activity shapes, required fields, exports, mistakes |
| references/control-flow-patterns.md | Nested If, loops, TryCatch, Break, branching, key uniqueness |
| 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, paging, multipart |
| 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 | Expressions, context, inputs, scripts, exports, strict mode |
| 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 |
| references/cli-reference.md | API workflow, solution, login, build, pack, validate, publish |
| references/operating-published-workflows.md | Published triggers, connections, jobs, logs, traces |
| references/troubleshooting.md | Runtime, structure, expression, connector, response, packaging, publish failures | | references/testing-and-evals.md | Eval contract, scoring, raw outputs, test-until-green protocol |
Templates
- assets/templates/api-workflow-template.json — empty valid skeleton.
- assets/templates/conditional-workflow-example.json — conditional branching/error handling.
- assets/templates/loop-aggregation-example.json — loop aggregation.
- assets/templates/nested-control-flow-example.json — deeply nested control flow.
- assets/templates/file-base64-roundtrip-example.json — Files — a
documentfile input → File to Base64 → Base64 to File → Response returning both references. The exactrun.scriptshape Studio Web writes for the two activities (rule 23). Verified end-to-end with a signed-in run: local file in →.base64reference → decoded file out, bytes identical. - assets/templates/trigger-workflow-template.json — event-driven skeleton:
WorkflowStart→UiPath.IntSvcEventtrigger → Response reading the payload. Its<REPLACE_WITH_*>connection UUID and trigger type id are sentinels; re-stub for real values (rules 16, 16a).
- assets/templates/connector-call-example.json — registry-generated HTTP with
ImplicitConnection.
- assets/templates/vendor-curated-call-example.json — IntSvc activity; replace its connection sentinel before writing.
- assets/templates/solution-connection-resource-template.json — Solutions-mode IntSvc connection resource.
Anti-patterns
- Do not use
call: "http"; use registry-generatedUiPath.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
JobAttachmentreferences. 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.;validaterejects the task and the runtime saysis not a function. See rule 23.
- Do not run autonomously or authenticated vendor calls without consent.
- Do not hand-assemble legacy projects, emit a lone
Workflow.json, or use solution projects add/remove.
- 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.schemaand 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.
- Authentication/organization errors: ask the user to run
uip login.
- File-not-found errors: verify paths with
ls. - Repeated structural errors: reread the workflow and relevant reference.