From 6c784c24b2a3ad23cf38f9cf2daec957e61c2880 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/2] 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 0aeaf50fc73099e3b9acb0d58d3d2f4efce5973d 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/2] 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