Comprehensive guide for creating, editing, validating, debugging, publishing, diagnosing, and evaluating UiPath Flow projects using the uip CLI and .flow file format. The skill is organized into four capabilities — Author, Operate, Diagnose, Evaluate — each with its own index doc.
These rules apply across all three capabilities. Each capability index adds capability-scoped rules on top.
-
ALWAYS use --output json and prefer --output-filter for extraction on all uip commands when parsing output programmatically. --output-filter <jmespath> is a global CLI flag applied to the Data envelope before printing — write expressions starting at Data (no Data. prefix). Canonical recipe: uip maestro flow registry search <keyword> --output json --output-filter "[*].{NodeType:NodeType,DisplayName:DisplayName,Description:Description,AvailableOnTenant:AvailableOnTenant}". registry search returns Data as a flat array of PascalCase objects (NodeType, DisplayName, Description, AvailableOnTenant) — NOT Data.Nodes, lowercase type, or lowercase category. With --local, AvailableOnTenant is omitted (no tenant lookup) — drop it from the projection. External parsers (python3 -c, jq) remain valid for transforms JMESPath cannot express; reach for them only after the shape is verified. Full mechanics, fall-back guidance, and shape-inspection probes: cli-conventions.md §3.
-
Do NOT run flow debug without explicit user consent — debug executes the flow for real (sends emails, posts messages, calls APIs).
-
Resource discovery order — search before creating. When the prompt references an existing resource by name ("use the X agent", "call the Y API workflow", "invoke the Z RPA process"), follow this order strictly before deciding the resource doesn't exist:
- Tenant registry search —
uip maestro flow registry search "<name>" --output json. Requires uip login; returns published resources.
- In-solution local discovery —
uip maestro flow registry list --local --output json, or uip maestro flow registry search "<name>" --local --output json for keyword match. No login required; returns sibling projects in the same .uipx solution. An empty search --local is not proof of absence (the keyword may not match the project's naming) — confirm with list --local before concluding the resource is not in the solution.
- Only then create/scaffold — scaffold an inline agent, mock, or create-new-resource only when both searches return no match AND either the user explicitly asks to embed/inline/create, or no published resource can satisfy the requirement.
The words "coded" and "low-code" describe the implementation style of a published agent — they are NOT synonyms for "inline". uipath.agent.autonomous (inline) is only correct when the user explicitly asks to embed/inline/create a new agent inside this flow. Only use core.logic.mock when the resource is not in the same solution and not yet published. See the relevant resource plugin's impl.md (e.g., rpa, agent).
The same "search before deciding it doesn't exist" discipline applies to connector connections. The connector key MUST come from a registry search node type (uipath.connector.<connector-key>.<activity>) — never inferred from the service's brand name. The registry key is frequently prefixed or qualified differently than the product name, so a guessed key silently misses the real connector. Any uip is connections list used for discovery MUST pass --all-folders. An empty result from an unverified key or without --all-folders is a false negative, never authoritative — do not conclude "no connection exists" or ask the user to create one until both hold.
It also applies to ANY external service named in the prompt — not just in-tenant resources. Before picking a node type for a named service (Slack, open-meteo, Stripe, any REST API), run uip maestro flow registry search "<service>" --output json and follow the Selecting External Service Nodes ladder (connector → managed HTTP → RPA). Manual core.action.http.v2 is the bottom of that ladder, chosen only after a search finds no connector — never a first guess from the brand name. This holds even when full planning is skipped (see greenfield.md — Select the node type for each external service).
Two tells that you skipped the search and took the brand-name shortcut — both are build defects, not valid manual-mode HTTP: (a) you authored a manual-mode core.action.http.v2 node whose url targets a well-known SaaS API domain that has a connector (slack.com/api/*, api.github.com, *.salesforce.com, graph.microsoft.com, …); (b) you declared an in variable to hold that service's API token or secret (e.g. a slackToken holding an xoxb-… bot token, an apiKey, a bearer token). A connector-backed flow never carries the raw credential — the IS connection does. If you find yourself writing either, stop: run uip maestro flow registry search "<service>" and uip is connections list "<connector-key>" --all-folders, then use the connector activity (or connector-mode HTTP: authentication:"connector" + targetConnector + a bound connectionId/folderKey). Manual mode is legitimate only for a service the search proves has no connector.
-
Never invoke other skills automatically — when a flow needs an RPA process, agent, or app, identify the gap and provide handoff instructions. Let the user decide when to switch skills.
-
Always present user questions as a dropdown with a "Something else" escape hatch — Whenever this skill needs a decision from the user (which solution to use, publish vs debug vs deploy, which connector to pick, which trigger type, which resource to bind, etc.), ask the user a question with the enumerated choices as options AND include "Something else" as the last option so the user can supply free-form string input. Never ask open-ended questions in chat when a finite set of sensible defaults exists. If the user picks "Something else", parse their string answer and continue. No structured-question facility on the harness → ask in chat as a numbered list with "Something else" last. Running non-interactively (CI/headless — no user available to answer) → take the pre-selected/recommended option, proceed, and record the decision prominently in the final report; if no option is marked recommended, stop and report the open decision instead of guessing. Exception: consent gates (flow debug, destructive operations) are never auto-answered — in non-interactive mode, stop and report the blocked step instead. These fallbacks define "ask the user" / "confirm with the user" wherever this skill's references require it.
-
A Flow project MUST live inside a solution — always scaffold the solution first (uip solution init <Name>), then cd <Name> and run uip maestro flow init <Name>. The correct layout is always <Solution>/<Project>/<Project>.flow (double-nested). Running uip maestro flow init in a bare directory produces a single-nested <Project>/<Project>.flow layout that fails Studio Web upload, packaging, and downstream tooling. See author/greenfield.md Step 2.
-
Narrate progress in plain English only when the user has opted into verbosity — silent by default. Engage when the user asks for narration / progress ("walk me through it", "show your steps", "verbose", "be detailed") or signals a verbosity preference; otherwise work quietly and surface only decisions, failures, consent gates, and the final result. When engaged: one short line per logical step, in user terms ("checking your tenant login", "adding the Slack node and wiring its inputs", "running validate") — no flag-level or JSON-structure-level detail, applied uniformly across uip CLI calls, shell builtins, file edits, and bulk searches. See shared/ux-narration-and-todos.md §When to engage.
-
Maintain a user-facing progress list only when the user has opted into progress tracking / verbosity. In silent mode there is no user-facing todo list (the agent MAY track privately). When engaged: any journey above the trivial threshold gets a granular list — one logical step ≈ one todo, granularity per-step not per-phase. The count emerges from the journey's actual steps; do not target a number. Bash plumbing inside a step (registry lookups, JSON parsing, intermediate file reads) is invisible — do not surface as todos. See shared/ux-narration-and-todos.md for the engage triggers, granularity rules, threshold table, and pivot rules.
-
Every node has exactly one author — Edit/Write or CLI, never both. Connector activities (uipath.connector.<key>.<op>), connector triggers (uipath.connector.trigger.<key>.<trigger>), wait for events (uipath.connector.event.<key>.<event> — a mid-flow event wait, configured exactly like a trigger), and managed HTTP (core.action.http.v2) are CLI-owned — use uip maestro flow node add + uip maestro flow node configure. Every other node type — triggers, control flow, logic, HITL, patterns, agents, resource nodes, queue — is user-owned: author the .flow JSON directly with Edit / Write. inputs.detail on CLI-owned nodes is a =jsonString:essentialConfiguration envelope that the validator rejects when hand-authored. Inline-agent CLI is limited to agent project lifecycle (uip agent init / refresh / validate --inline-in-flow); the uipath.agent.autonomous flow node itself is user-owned. Scripting languages (python, node, jq, sed, awk, inline shell heredocs) are a last resort for user-owned edits and require explicit user approval after the trade-offs (state bypass, opaque diff, no interruption point) are surfaced. Canonical source of truth: author/CAPABILITY.md — Node ownership (full table); author/editing-operations.md — Tool Selection Ladder (per-operation ladder).
-
Batch tool calls into one assistant turn whenever data dependencies allow — minimize wall-clock round-trips. A typical greenfield build is 3 turns, not 10+: (T1) one chained Bash for scaffold + registry pull + CLI-owned node add, in parallel with registry get and Read calls for any extra discovery; (T2) one Read of the scaffolded .flow in parallel with the Edit / Write calls that add the End node and wire edges; (T3) one chained Bash for node configure && validate && format. Within an assistant message: chain sequential uip calls with && in a single Bash, and emit independent Bash / Read / Edit calls as parallel tool uses. Only split turns where a later call truly depends on an earlier call's stdout or on a file mutation. See author/references/greenfield.md — Three-turn execution map for the canonical pattern.