Skip to content

fix: revert deferred tool call [JAR-9208]#703

Open
JoshParkSJ wants to merge 16 commits intomainfrom
josh/cas-tc-fix
Open

fix: revert deferred tool call [JAR-9208]#703
JoshParkSJ wants to merge 16 commits intomainfrom
josh/cas-tc-fix

Conversation

@JoshParkSJ
Copy link
Copy Markdown
Contributor

@JoshParkSJ JoshParkSJ commented Mar 17, 2026

What changed?

Moves tool confirmation from the old interrupt-based flow to the new confirmToolCall event on startToolCall, with a clean rip-and-replace of all legacy code.

https://uipath.atlassian.net/browse/JAR-9208

Changes

hitl.py (HITL approval flow):

  • Removed import and usage of UiPathConversationToolCallConfirmationValue — the @durable_interrupt in ask_confirmation() now emits a plain dict instead of the old interrupt model
  • Removed legacy dual-payload parsing (the {"type": ..., "value": {...}} shape from endInterrupt). Resume payloads are now always the confirmToolCall shape: {"approved": bool, "input": ...}
  • Added ARGS_MODIFIED_MESSAGE constant, replacing the args_modified_by_user: True boolean with a human-readable message field in tool result metadata

messages.py (event mapper):

  • startToolCall is now always emitted for confirmation tools (previously skipped). CAS reads requireConfirmation and inputSchema from this event to render the confirmation UI.
  • map_tool_call_to_tool_call_start_event() accepts require_confirmation and input_schema kwargs

runtime.py:

  • Added _get_tool_confirmation_schemas() to extract JSON schemas from tools marked with require_conversational_confirmation, passed to the mapper as tool_confirmation_schemas

Why rip-and-replace instead of backward compatibility?

We evaluated maintaining backward compat with the old startInterrupt/endInterrupt flow and decided against it:

  1. Both sides break the old flow — backward compat is impossible at the system level. AgentInterfaces#899 removes the onInterruptStart handler from the frontend, so old interrupt events won't render. uipath-python#1558 removes emit_interrupt_event and endInterrupt handling from the bridge. Neither transition state (old Python + new CAS, or new Python + old CAS) produces a working confirmation flow — there is no graceful degradation in either direction.

  2. Zero production usage. App Insights telemetry over 90 days across both jarvis-prd-eus-ais and agents-prd-appins-ne-appins confirmed: ToolCallStart count equals ToolCallEnd count (332 each, no skipped starts indicating confirmation tools), zero InterruptStartEvent traces in CAS. The @requires_approval decorator ships in the package but no deployed agent exercises it.

  3. The backward compat was already dead code. The dual payload parsing in hitl.py handled the legacy {type, value} shape, but the bridge (the only thing delivering resume payloads for conversational agents) already only produces {approved, input} after uipath-python#1558. The legacy branch was unreachable.

  4. Deployment is coordinated. CAS deploys first, then Python. The feature is staging-only.

See also: AgentInterfaces#899, uipath-python#1558, uipath-runtime-python#99

Three fixes for coded agent tool confirmation:

1. hitl.py: @requires_approval now stamps REQUIRE_CONVERSATIONAL_CONFIRMATION
   metadata so the runtime can discover confirmation tools.

2. runtime.py: _get_tool_confirmation_info handles both graph shapes —
   UiPathToolNode (low-code, bound.tool) and LangGraph ToolNode
   (create_agent, bound.tools_by_name).

3. messages.py: seed chunk accumulator with an empty AIMessageChunk instead
   of the incoming message. Prevents self-merge on the first streaming chunk
   which doubled tool names (e.g. search_websearch_web) and broke the
   confirmation set lookup.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants