feat: bind HITL escalation recipients to upstream tool outputs [ACTN-10480]#867
feat: bind HITL escalation recipients to upstream tool outputs [ACTN-10480]#867kunaluipath wants to merge 1 commit into
Conversation
2541dd2 to
bcc79f3
Compare
Adds support for resolving escalation recipients at runtime from the output of upstream tools, in addition to the existing literal / agent-input bindings. Works for User, Group, Workload, RoundRobin, and CustomAssignees criteria. - _extract_tool_output_value: walks state.messages backwards, finds the latest ToolMessage by name, parses content as JSON, extracts a top-level field (fail-loud on missing tool / missing path). - _build_tool_output_task_recipient: maps the extracted value to the appropriate TaskRecipient shape per criteria (list to Workload-style, string to single, CustomAssignees comma-split). - resolve_recipient_value: new ToolOutputRecipient branch. - resolve_channel_recipients: threads tool_messages through; tool-output takes precedence over CustomAssignees aggregation. - escalation_wrapper: captures state.messages into tool.metadata so escalation_tool_fn can read it without changing public signatures. - create_escalation_tool: auto-augments tool description with a hint listing the tool dependencies for the LLM to plan tool calls. Backwards-compatible: existing recipients without source parse and resolve identically. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
bcc79f3 to
04da4eb
Compare
|
There was a problem hiding this comment.
Pull request overview
This PR extends the escalation tool’s recipient resolution so escalation recipients can be dynamically derived from prior tool outputs (in addition to literal values and agent-input argument bindings), and threads message history through the tool wrapper to enable that resolution at runtime.
Changes:
- Added tool-output recipient binding support by extracting fields from the latest matching
ToolMessageand mapping that value intoTaskRecipient. - Introduced
resolve_channel_recipients()to correctly aggregate channel recipients (notablyCustomAssignees) and to give tool-output bindings precedence when configured. - Expanded test coverage for new recipient types (Workload, RoundRobin, CustomAssignees), tool-output extraction behavior, and description augmentation for upstream tool dependencies.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
tests/agent/tools/test_escalation_tool.py |
Adds tests for new recipient resolution paths (workload/round-robin/custom-assignees), tool-output extraction, channel aggregation, and tool description hints. |
src/uipath_langchain/agent/tools/escalation_tool.py |
Implements tool-output extraction and mapping, adds channel-level recipient resolution, threads message history via metadata, and augments tool descriptions with dependency hints. |
src/uipath_langchain/agent/guardrails/actions/escalate_action.py |
Updates assigned-to metadata handling for additional recipient model types used by guardrail escalation task creation. |
| for msg in reversed(tool_messages): | ||
| if isinstance(msg, ToolMessage) and getattr(msg, "name", None) == tool_name: | ||
| content = msg.content |
| if isinstance(value, list): | ||
| # Filter to truthy strings — tool outputs may contain nulls/empty entries. | ||
| emails = [str(v) for v in value if v] | ||
| if not emails: | ||
| raise ValueError( | ||
| f"Tool-output recipient resolved to an empty list for criteria " | ||
| f"{recipient_type.value}." | ||
| ) | ||
| return TaskRecipient( | ||
| value=emails[0], | ||
| values=emails, | ||
| type=TaskRecipientType.WORKLOAD, | ||
| ) |
|
tool.metadata["agent_messages"] = list(raw_messages or []) — full history This copies every message object (potentially large AIMessages, multi-modal tool.metadata["agent_messages"] = [m for m in (raw_messages or []) if ^ Claude mentioned this - worth checking if doable |


Adds support for resolving escalation recipients at runtime from the output of upstream tools, in addition to the existing literal / agent-input bindings. Works for User, Group, Workload, RoundRobin, and CustomAssignees criteria.
Backwards-compatible: existing recipients without source parse and resolve identically.