Uipath functions
UiPath Coded Functions — deterministic Python units built via `uip function` (new/init/run/pack/publish); the `functions` map in `uipath.json`, `entry-points.json`, Pydantic Input/Output. Rule-based logic, data transforms, ERP/Integration Service connector calls — no LLM reasoning or agent loop. For LLM/agentic projects (LangGraph, LlamaIndex, OpenAI Agents, `agent.json`)→uipath-agents.From its SKILL.md
npx -y skills add UiPath/skills --skill uipath-functionsAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
SKILL.md
11.4 KB, as published. Nobody here has run it
UiPath Python Coded Functions
What Python Coded Functions Are
Python Coded Functions are atomic, bespoke units of business logic — deterministic Python code packaged as a first-class UiPath artifact. Use them when generic activities don't cover the required logic: calling a third-party API with custom auth, processing documents with domain-specific rules, querying ERP systems via Integration Service connections, or transforming data in ways that no out-of-the-box activity handles.
A Coded Function is not an agent. It does not reason, route, or call LLMs. It takes typed input, executes deterministic code, and returns typed output.
Invocation surfaces
A Python Coded Function can be invoked from any UiPath surface:
| Surface | How |
|---|---|
| Maestro BPMN | Service Task node |
| Maestro Flow | Coded Agent node or Service Task |
| Coded Agents (LangGraph / LlamaIndex / OpenAI Agents) | Called as a tool or step |
| Other Coded Functions | Direct Python call or Orchestrator job |
| Orchestrator API | POST /Jobs/StartJobs |
| CLI | uip function pack → uip function publish |
Python Functions vs JS Functions
| Python Coded Function | JS/TS Function | |
|---|---|---|
| Job semantics | Yes — Orchestrator job ID, audit trail, retry, scheduling | No — inline HTTP only, no job lifecycle |
| Invocation | Maestro, Flow, Agents, Orchestrator API | HTTP endpoint (BFF for Coded Apps) |
| Runtime | Serverless or Local Unattended Robot | Serverless HTTP shared tier |
| SDK access | Full UiPath Python SDK (assets, buckets, queues, connections) | Workload token forwarding only |
| Scaffold | uip function new <name> --language py | uip function new <name> --language ts (default) |
| Init | uip function init (generates entry-points.json) | Not needed |
| Local dev | uip function run | uip function serve + uip function run |
| Best for | Agentic process steps, ERP integration, document AI, data pipelines | Backend-for-Frontend for Coded Apps |
Use Python when the logic needs job semantics, platform SDK access, or is invoked from Maestro/agents. Use JS when the caller is a Coded App frontend and low HTTP latency matters.
CLI Reference
All Python Coded Function lifecycle commands use uip function:
uip function new <name> -l py # scaffold a new Python Functions project (--language py required)
uip function init # Python only — generate entry-points.json, bindings.json, project.uiproj
uip function pack # pack to .nupkg for deployment
uip function publish # upload .nupkg to Orchestrator (prompts for feed, or use --feed-id)
uip function push # sync project to Studio Web
uip function runworks for both Python and JS/TS.uip function serveis JS/TS only — it starts the local HTTP server thatruninvokes against.
Workflow
Step 1: Scaffold
uip function new <name> --language py # Python Coded Function
uip function new <name> --language ts # TypeScript Function (JS/TS, no job semantics)
uip function new <name> --language js # JavaScript Function (JS/TS, no job semantics)
--language py is required for Python. The default language is TypeScript — omitting --language scaffolds a JS/TS project. Always pass -l py or --language py when building a Python Coded Function.
--empty skips the hello-world function (JS/TS only).
The scaffold follows the installed packages. With a framework package present in the environment (uipath-langchain, llama-index, openai-agents), uip function new -l py emits that framework's agent scaffold — langgraph.json plus an LLM main.py — not a function scaffold. Expected behaviour, not a broken flag. Recovery, in one pass:
- Delete the framework config (
langgraph.jsonand equivalents). - Replace
main.pywith the function template (Step 3). - Keep
pyproject.toml's[project]metadata (Step 5) — swapdependenciesfor what the function needs.
Do not re-run new with different flag spellings, and do not read CLI or SDK internals to explain the scaffold. Reshape the project and move on.
Step 2: Define Function Schema
Use typed I/O. The SDK accepts pydantic BaseModel, pydantic.dataclasses.dataclass, a stdlib @dataclass, or a thin class with typed annotations. The shipped samples favor pydantic (BaseModel in csv-processor, pydantic.dataclasses.dataclass in calculator/greeter):
from pydantic import BaseModel
class Input(BaseModel):
document_id: str = ""
class Output(BaseModel):
vendor_name: str = ""
total_amount: float = 0.0
error_type: str = "" # populated on failure, empty on success
error_message: str = "" # human-readable error detail
Step 3: Implement Business Logic
Do NOT make LLM calls inside a Coded Function. LLM calls introduce non-determinism and latency that break the function contract. If the step requires LLM reasoning or multi-step AI decisions, use a framework-based agent (LangGraph, LlamaIndex, OpenAI Agents) instead.
Minimal template
from __future__ import annotations
from pydantic import BaseModel
from uipath.tracing import traced
from uipath.platform import UiPath
class Input(BaseModel):
document_id: str = ""
class Output(BaseModel):
result: str = ""
error_type: str = ""
error_message: str = ""
# Lazy SDK singleton — never instantiate UiPath() at module level
_sdk: UiPath | None = None
def sdk() -> UiPath:
global _sdk
if _sdk is None:
_sdk = UiPath()
return _sdk
@traced(name="my_function", run_type="uipath")
def my_function(input: Input) -> Output:
out = Output()
try:
# SDK calls, data processing, rule-based logic only
asset = sdk().assets.retrieve("MY_ASSET", folder_path="Shared")
out.result = str(asset.value)
except Exception as exc:
out.error_type = "FAILED"
out.error_message = str(exc)
return out
Key rules:
- Typed I/O — pydantic
BaseModel,pydantic.dataclasses.dataclass, stdlib@dataclass, or a thin class with typed annotations; samples favor pydantic deforasync def— both supported (csv-processor usesasync def main); the function name is arbitrary- Lazy SDK init — instantiate
UiPath()inside a getter, never at module level - Errors returned, not raised — populate
error_type/error_messageoutput fields and return; never let exceptions bubble out of the entrypoint @traced(name=..., run_type="uipath")— apply to the entrypoint and any sub-functions you want visible in LLM Ops Traces
Step 4: Register in uipath.json
{
"runtimeOptions": { "isConversational": false },
"functions": {
"main": "main.py:my_function"
}
}
The key is the entrypoint name — it can be any string and marks this as the callable entrypoint. The value is "<file>:<function_name>". Both the key and the function name are arbitrary.
This functions map is what identifies the project as a Coded Function — the runtime's determine_project_type() reads the entrypoint type from uipath.json.
Step 5: Declare dependencies in pyproject.toml
[project]
name = "my-function"
version = "0.1.0"
description = "..."
authors = [{ name = "Your Name", email = "[email protected]" }]
requires-python = ">=3.11"
dependencies = [
"uipath",
"httpx>=0.28", # if making HTTP calls
"pydantic-settings>=2", # if using Settings for env/asset config
]
authors is required — without it uip function pack rejects the package with Project authors cannot be empty.
No [build-system] section. The project is identified as a Coded Function by the functions map in uipath.json (Step 4).
Step 6: Generate Entry Points
uip function init
Python only. Discovers entrypoints and generates entry-points.json, bindings.json, and project.uiproj. Must run before pack or push. Re-run whenever Input/Output schemas or the entrypoint registration in uipath.json changes.
Step 7: SDK Capabilities
Full SDK reference: https://uipath.github.io/uipath-python/
Access UiPath platform resources via sdk():
from uipath.platform import UiPath
from uipath.platform.connections.connections import ActivityMetadata, ActivityParameterLocationInfo
# Assets — retrieve named credentials or config values
asset = sdk().assets.retrieve("ASSET_NAME", folder_path="Shared")
value = asset.string_value # or credential_username / credential_password
# Buckets — download files for processing
sdk().buckets.download(
name="BucketName",
blob_file_path="relative/path/file.pdf",
destination_path="/tmp/local.pdf",
folder_path="Shared",
)
# Integration Service connections — invoke connector activities (ERP, CRM, etc.)
result = sdk().connections.invoke_activity(
activity_metadata=ActivityMetadata(
object_path="/executeSuiteQL",
method_name="POST",
content_type="application/json",
parameter_location_info=ActivityParameterLocationInfo(body_fields=["q"]),
),
connection_id="<connection-uuid>",
activity_input={"q": "SELECT id FROM vendor WHERE ..."},
)
File attachment inputs
To accept a runtime file, type an Input field as Attachment (pydantic model, not a dataclass):
from pydantic import BaseModel
from uipath.platform.attachments import Attachment
class Input(BaseModel):
attachment: Attachment
uip function init recognizes the Attachment type and emits x-uipath-resource-kind: JobAttachment in entry-points.json — the schema Studio Web and Orchestrator read to render a file picker for that field. Access fields snake_case: attachment.full_name, attachment.content.
Step 8: Pack and Publish
uip function pack # creates .nupkg
uip function publish # upload to Orchestrator (interactive feed picker)
uip function publish --feed-id <FEED_ID> # CI/non-interactive
To sync to Studio Web instead of publishing to Orchestrator:
uip function push
Important Notes
UiPath()must never be instantiated at module level — always inside a function body- The
functionsmap inuipath.jsonmarks the project as a Coded Function (determine_project_type()reads the entrypoint type fromuipath.json) uip function initmust run beforepackorpush— it generatesentry-points.json- Python Functions have full job semantics: Orchestrator job ID, audit trail, retry, scheduling
- JS Functions have no job semantics and cannot be started as Orchestrator jobs — use Python when the caller is Maestro, a Flow, or an agent
uip function runworks for both Python and JS/TS local execution;uip function serveis JS/TS only (starts the local HTTP server thatruninvokes against)- If cloud-backed work requires authentication, run
uip login --organization "<ORG>" --tenant "<TENANT>" --output json.