From 59ce1e7b1fb65b25dcd06ffe65a915848b1d038b Mon Sep 17 00:00:00 2001 From: Mayank Jha Date: Wed, 28 Jan 2026 13:42:22 -0800 Subject: [PATCH] feat(cli): add --wait-for-triggers flag for local execution without orchestrator Add CLI flags to enable polling mode for triggers instead of suspending: - `--wait-for-triggers`: Poll triggers until completion instead of suspending - `--trigger-poll-interval`: Configurable poll interval (default: 5.0s) This enables running agents locally with tool calls (InvokeProcess, CreateTask, etc.) without requiring serverless/orchestrator infrastructure. Usage: uipath run my_agent.main '{"query": "hello"}' --wait-for-triggers uipath run my_agent.main '{"query": "hello"}' --wait-for-triggers --trigger-poll-interval 10.0 Depends on: UiPath/uipath-runtime-python#74 Co-Authored-By: Claude Opus 4.5 --- pyproject.toml | 3 ++- src/uipath/_cli/cli_run.py | 27 +++++++++++++++++++++++++-- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index e174a86f5..d5caeed97 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,7 +6,8 @@ readme = { file = "README.md", content-type = "text/markdown" } requires-python = ">=3.11" dependencies = [ "uipath-core>=0.2.0, <0.3.0", - "uipath-runtime>=0.6.0, <0.7.0", + # TODO: Change back to "uipath-runtime>=0.7.0, <0.8.0" once PR #74 is merged and released + "uipath-runtime @ git+https://github.com/UiPath/uipath-runtime-python.git@feature/wait-for-triggers", "click>=8.3.1", "httpx>=0.28.1", "pyjwt>=2.10.1", diff --git a/src/uipath/_cli/cli_run.py b/src/uipath/_cli/cli_run.py index d09162c72..7bd7d5e42 100644 --- a/src/uipath/_cli/cli_run.py +++ b/src/uipath/_cli/cli_run.py @@ -80,6 +80,17 @@ is_flag=True, help="Keep the temporary state file even when not resuming and no job id is provided", ) +@click.option( + "--wait-for-triggers", + is_flag=True, + help="Poll triggers until completion instead of suspending. Useful for local execution without orchestrator.", +) +@click.option( + "--trigger-poll-interval", + type=float, + default=5.0, + help="Seconds between poll attempts when --wait-for-triggers is enabled (default: 5.0)", +) def run( entrypoint: str | None, input: str | None, @@ -92,6 +103,8 @@ def run( debug: bool, debug_port: int, keep_state_file: bool, + wait_for_triggers: bool, + trigger_poll_interval: float, ) -> None: """Execute the project.""" input_file = file or input_file @@ -112,6 +125,8 @@ def run( debug=debug, debug_port=debug_port, keep_state_file=keep_state_file, + wait_for_triggers=wait_for_triggers, + trigger_poll_interval=trigger_poll_interval, ) if result.error_message: @@ -129,7 +144,11 @@ def run( async def execute_runtime( ctx: UiPathRuntimeContext, runtime: UiPathRuntimeProtocol ) -> UiPathRuntimeResult: - options = UiPathExecuteOptions(resume=resume) + options = UiPathExecuteOptions( + resume=resume, + wait_for_triggers=wait_for_triggers, + trigger_poll_interval=trigger_poll_interval, + ) ctx.result = await runtime.execute( input=ctx.get_input(), options=options ) @@ -141,7 +160,11 @@ async def debug_runtime( debug_bridge: UiPathDebugProtocol = ConsoleDebugBridge() await debug_bridge.emit_execution_started() - options = UiPathStreamOptions(resume=resume) + options = UiPathStreamOptions( + resume=resume, + wait_for_triggers=wait_for_triggers, + trigger_poll_interval=trigger_poll_interval, + ) async for event in runtime.stream(ctx.get_input(), options=options): if isinstance(event, UiPathRuntimeResult): await debug_bridge.emit_execution_completed(event)