From 232bac171ae4ae7fae146062c52bd3e05ef4de48 Mon Sep 17 00:00:00 2001 From: Maxwell Du <60411452+maxduu@users.noreply.github.com> Date: Tue, 30 Jun 2026 23:35:43 -0400 Subject: [PATCH 1/6] feat: conversational-agent output --- .../uipath/src/uipath/agent/react/__init__.py | 6 ++++ .../agent/react/conversational_prompts.py | 15 +++++++++ .../uipath/src/uipath/agent/react/tools.py | 23 ++++++++++++++ .../react/test_conversational_prompts.py | 31 +++++++++++++++++++ 4 files changed, 75 insertions(+) diff --git a/packages/uipath/src/uipath/agent/react/__init__.py b/packages/uipath/src/uipath/agent/react/__init__.py index 835fd0bda..539f062b6 100644 --- a/packages/uipath/src/uipath/agent/react/__init__.py +++ b/packages/uipath/src/uipath/agent/react/__init__.py @@ -6,15 +6,18 @@ from .conversational_prompts import ( PromptUserSettings, get_chat_system_prompt, + get_generate_output_prompt, ) from .conversational_voice_prompts import get_voice_system_prompt from .prompts import AGENT_SYSTEM_PROMPT_TEMPLATE from .tools import ( END_EXECUTION_TOOL, RAISE_ERROR_TOOL, + SET_CONVERSATIONAL_OUTPUT_TOOL, EndExecutionToolSchemaModel, FlowControlToolConfig, RaiseErrorToolSchemaModel, + SetConversationalOutputToolSchemaModel, ) __all__ = [ @@ -22,9 +25,12 @@ "FlowControlToolConfig", "END_EXECUTION_TOOL", "RAISE_ERROR_TOOL", + "SET_CONVERSATIONAL_OUTPUT_TOOL", "EndExecutionToolSchemaModel", "RaiseErrorToolSchemaModel", + "SetConversationalOutputToolSchemaModel", "PromptUserSettings", "get_chat_system_prompt", + "get_generate_output_prompt", "get_voice_system_prompt", ] diff --git a/packages/uipath/src/uipath/agent/react/conversational_prompts.py b/packages/uipath/src/uipath/agent/react/conversational_prompts.py index f79de6185..0d3fbf8d6 100644 --- a/packages/uipath/src/uipath/agent/react/conversational_prompts.py +++ b/packages/uipath/src/uipath/agent/react/conversational_prompts.py @@ -233,3 +233,18 @@ def get_conversation_id_template(conversation_id: str | None) -> str: if not conversation_id: return "" return _CONVERSATION_ID_TEMPLATE.format(conversation_id=conversation_id) + + +_GENERATE_OUTPUT_INSTRUCTION = """The conversational response for this turn has already been delivered to the user. Call the `set_conversational_output` tool to record the structured output fields for this turn. + +Rules: +- For each field, use values inferred from the conversation's recent turn. +- For optional fields that are not yet relevant or determinable from the conversation so far, omit them entirely. +- For required fields that cannot yet be determined (e.g., the conversation is still gathering context, or the topic hasn't surfaced yet), use a clear placeholder value (e.g. "N/A" or "unknown" for string fields). DO NOT fabricate, guess, or hallucinate values. +- Do not produce any text content — only call the tool.""" + + +def get_generate_output_prompt() -> str: + """Framework-internal instruction appended as a final user-message to the + conversational structured-output node's LLM call.""" + return _GENERATE_OUTPUT_INSTRUCTION \ No newline at end of file diff --git a/packages/uipath/src/uipath/agent/react/tools.py b/packages/uipath/src/uipath/agent/react/tools.py index c2a162be9..050653543 100644 --- a/packages/uipath/src/uipath/agent/react/tools.py +++ b/packages/uipath/src/uipath/agent/react/tools.py @@ -11,6 +11,7 @@ class FlowControlToolName(str, Enum): END_EXECUTION = "end_execution" RAISE_ERROR = "raise_error" + SET_CONVERSATIONAL_OUTPUT = "set_conversational_output" @dataclass(frozen=True) @@ -72,3 +73,25 @@ class RaiseErrorToolSchemaModel(BaseModel): description="Raises an error and ends the execution of the agent", args_schema=RaiseErrorToolSchemaModel, ) + + +class SetConversationalOutputToolSchemaModel(BaseModel): + """Placeholder args_schema for the `set_conversational_output` tool. + + Always overridden at construction time with the agent's stripped output + schema (i.e. the user's `outputSchema` with `uipath__agent_response_messages` + removed). Declared here so the tool entry has a well-typed default. + """ + + model_config = ConfigDict(extra="forbid") + + +SET_CONVERSATIONAL_OUTPUT_TOOL = FlowControlToolConfig( + name=FlowControlToolName.SET_CONVERSATIONAL_OUTPUT, + description=( + "Sets the structured output fields for the current conversational " + "turn. Called once per turn after the conversational response has been " + "delivered, to populate fields as the agent's output." + ), + args_schema=SetConversationalOutputToolSchemaModel, +) diff --git a/packages/uipath/tests/agent/react/test_conversational_prompts.py b/packages/uipath/tests/agent/react/test_conversational_prompts.py index 434f68465..b32a36e85 100644 --- a/packages/uipath/tests/agent/react/test_conversational_prompts.py +++ b/packages/uipath/tests/agent/react/test_conversational_prompts.py @@ -8,6 +8,7 @@ from uipath.agent.react.conversational_prompts import ( PromptUserSettings, get_chat_system_prompt, + get_generate_output_prompt, get_user_settings_template, ) @@ -348,3 +349,33 @@ def test_full_settings_json_format(self): assert json_data["company"] == "Big Corp" assert json_data["country"] == "UK" assert json_data["timezone"] == "Europe/London" + + +class TestGetGenerateOutputInstruction: + """Tests for get_generate_output_prompt function.""" + + def test_returns_non_empty_string(self): + instruction = get_generate_output_prompt() + assert isinstance(instruction, str) + assert instruction.strip() + + def test_references_set_conversational_output_tool(self): + """The instruction must name the tool the new node binds.""" + assert "set_conversational_output" in get_generate_output_prompt() + + def test_mentions_placeholder_rule_for_required_fields(self): + """The instruction must steer the model toward 'N/A'-style placeholders + rather than fabricated values for required fields with no context yet.""" + instruction = get_generate_output_prompt() + assert "N/A" in instruction or "unknown" in instruction.lower() + + def test_mentions_omit_rule_for_optional_fields(self): + """The instruction must steer the model toward omitting optional fields + when they're not yet relevant.""" + instruction = get_generate_output_prompt().lower() + assert "omit" in instruction or "optional" in instruction + + def test_no_text_content_directive(self): + """The instruction must explicitly forbid producing conversational text.""" + instruction = get_generate_output_prompt().lower() + assert "do not produce" in instruction or "only call the tool" in instruction From bf12bffc66b89aecdb4f979e2b3d7810b4fa0756 Mon Sep 17 00:00:00 2001 From: Maxwell Du <60411452+maxduu@users.noreply.github.com> Date: Wed, 1 Jul 2026 18:00:04 -0400 Subject: [PATCH 2/6] fix: formatting --- .../src/uipath/agent/react/conversational_prompts.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/uipath/src/uipath/agent/react/conversational_prompts.py b/packages/uipath/src/uipath/agent/react/conversational_prompts.py index 0d3fbf8d6..66d8a1399 100644 --- a/packages/uipath/src/uipath/agent/react/conversational_prompts.py +++ b/packages/uipath/src/uipath/agent/react/conversational_prompts.py @@ -245,6 +245,9 @@ def get_conversation_id_template(conversation_id: str | None) -> str: def get_generate_output_prompt() -> str: - """Framework-internal instruction appended as a final user-message to the - conversational structured-output node's LLM call.""" - return _GENERATE_OUTPUT_INSTRUCTION \ No newline at end of file + """Return the framework-internal generate-output instruction. + + Appended as a final user-message to the conversational structured-output + node's LLM call. + """ + return _GENERATE_OUTPUT_INSTRUCTION From 9ee6ad19a47f33af480c9c6d970ef8a54aaedd80 Mon Sep 17 00:00:00 2001 From: Maxwell Du <60411452+maxduu@users.noreply.github.com> Date: Tue, 7 Jul 2026 13:19:04 -0400 Subject: [PATCH 3/6] fix: prompting placeholder --- .../agent/react/conversational_prompts.py | 6 +++--- .../agent/react/test_conversational_prompts.py | 17 ----------------- 2 files changed, 3 insertions(+), 20 deletions(-) diff --git a/packages/uipath/src/uipath/agent/react/conversational_prompts.py b/packages/uipath/src/uipath/agent/react/conversational_prompts.py index 66d8a1399..d966dd55b 100644 --- a/packages/uipath/src/uipath/agent/react/conversational_prompts.py +++ b/packages/uipath/src/uipath/agent/react/conversational_prompts.py @@ -239,9 +239,9 @@ def get_conversation_id_template(conversation_id: str | None) -> str: Rules: - For each field, use values inferred from the conversation's recent turn. -- For optional fields that are not yet relevant or determinable from the conversation so far, omit them entirely. -- For required fields that cannot yet be determined (e.g., the conversation is still gathering context, or the topic hasn't surfaced yet), use a clear placeholder value (e.g. "N/A" or "unknown" for string fields). DO NOT fabricate, guess, or hallucinate values. -- Do not produce any text content — only call the tool.""" +- For optional fields that are not yet relevant or determinable (e.g. the conversation is still gathering context, or the topic hasn't surfaced yet), omit them entirely. +- For required fields that cannot yet be determined, provide a default placeholder. DO NOT fabricate, guess, or hallucinate meaningful values. +- Do not produce any text response, as this will not be seen by the user. Only call the tool.""" def get_generate_output_prompt() -> str: diff --git a/packages/uipath/tests/agent/react/test_conversational_prompts.py b/packages/uipath/tests/agent/react/test_conversational_prompts.py index b32a36e85..33f6979d5 100644 --- a/packages/uipath/tests/agent/react/test_conversational_prompts.py +++ b/packages/uipath/tests/agent/react/test_conversational_prompts.py @@ -362,20 +362,3 @@ def test_returns_non_empty_string(self): def test_references_set_conversational_output_tool(self): """The instruction must name the tool the new node binds.""" assert "set_conversational_output" in get_generate_output_prompt() - - def test_mentions_placeholder_rule_for_required_fields(self): - """The instruction must steer the model toward 'N/A'-style placeholders - rather than fabricated values for required fields with no context yet.""" - instruction = get_generate_output_prompt() - assert "N/A" in instruction or "unknown" in instruction.lower() - - def test_mentions_omit_rule_for_optional_fields(self): - """The instruction must steer the model toward omitting optional fields - when they're not yet relevant.""" - instruction = get_generate_output_prompt().lower() - assert "omit" in instruction or "optional" in instruction - - def test_no_text_content_directive(self): - """The instruction must explicitly forbid producing conversational text.""" - instruction = get_generate_output_prompt().lower() - assert "do not produce" in instruction or "only call the tool" in instruction From 59dc43ff789dde5bbba64caad729c63d09b89052 Mon Sep 17 00:00:00 2001 From: Maxwell Du <60411452+maxduu@users.noreply.github.com> Date: Tue, 7 Jul 2026 13:19:45 -0400 Subject: [PATCH 4/6] fix: rename test --- .../uipath/tests/agent/react/test_conversational_prompts.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/uipath/tests/agent/react/test_conversational_prompts.py b/packages/uipath/tests/agent/react/test_conversational_prompts.py index 33f6979d5..2ddafc904 100644 --- a/packages/uipath/tests/agent/react/test_conversational_prompts.py +++ b/packages/uipath/tests/agent/react/test_conversational_prompts.py @@ -351,7 +351,7 @@ def test_full_settings_json_format(self): assert json_data["timezone"] == "Europe/London" -class TestGetGenerateOutputInstruction: +class TestGetGenerateOutputPrompt: """Tests for get_generate_output_prompt function.""" def test_returns_non_empty_string(self): From 53b8fa7da191cc160b9e67399e4f01ecfffb68f3 Mon Sep 17 00:00:00 2001 From: Maxwell Du <60411452+maxduu@users.noreply.github.com> Date: Tue, 7 Jul 2026 13:22:25 -0400 Subject: [PATCH 5/6] chore: bump version --- packages/uipath/pyproject.toml | 2 +- packages/uipath/uv.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/uipath/pyproject.toml b/packages/uipath/pyproject.toml index bfb1a3626..45594c2f5 100644 --- a/packages/uipath/pyproject.toml +++ b/packages/uipath/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "uipath" -version = "2.13.4" +version = "2.13.5" description = "Python SDK and CLI for UiPath Platform, enabling programmatic interaction with automation services, process management, and deployment tools." readme = { file = "README.md", content-type = "text/markdown" } requires-python = ">=3.11" diff --git a/packages/uipath/uv.lock b/packages/uipath/uv.lock index e90c2794a..a8da9fe0f 100644 --- a/packages/uipath/uv.lock +++ b/packages/uipath/uv.lock @@ -2598,7 +2598,7 @@ wheels = [ [[package]] name = "uipath" -version = "2.13.4" +version = "2.13.5" source = { editable = "." } dependencies = [ { name = "applicationinsights" }, From e8cc11ff8f7481c5452e34e423580015be804be3 Mon Sep 17 00:00:00 2001 From: Maxwell Du <60411452+maxduu@users.noreply.github.com> Date: Tue, 7 Jul 2026 13:23:45 -0400 Subject: [PATCH 6/6] chore: bump version again --- packages/uipath/pyproject.toml | 2 +- packages/uipath/uv.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/uipath/pyproject.toml b/packages/uipath/pyproject.toml index 210adae85..035dac2d1 100644 --- a/packages/uipath/pyproject.toml +++ b/packages/uipath/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "uipath" -version = "2.13.5" +version = "2.13.6" description = "Python SDK and CLI for UiPath Platform, enabling programmatic interaction with automation services, process management, and deployment tools." readme = { file = "README.md", content-type = "text/markdown" } requires-python = ">=3.11" diff --git a/packages/uipath/uv.lock b/packages/uipath/uv.lock index 881bfdaf7..19e974d12 100644 --- a/packages/uipath/uv.lock +++ b/packages/uipath/uv.lock @@ -2598,7 +2598,7 @@ wheels = [ [[package]] name = "uipath" -version = "2.13.5" +version = "2.13.6" source = { editable = "." } dependencies = [ { name = "applicationinsights" },