Tool error propagation differs on a per tool basis
Observed behaviour
When create_merge_request returns
{"error": "Request failed (...): HTTP 403: ..."}, the OneOffComponent sets
execution_result to "success" and the flow continues to the supervisor
step with no MR created.
Root cause — string-parsing-based error detection
The ToolNodeWithErrorCorrection determines success or failure in two stages:
-
_execute_tool()— wrapstool.ainvoke()in a try/except. If an exception escapes, it is caught, formatted into a specific string, and returned. -
_extract_errors_from_responses()— scans the returned strings for regex patterns that match the formats produced by step 1:error_patterns = [ r"tool exception occurred due to", # _format_tool_exception r"execution failed due to", # _format_type_error_response r"raised validation error", # _format_validation_error r"runtime exception due to", # _format_execution_error r"tool \w+ not found", # tool-not-found case ]
The problem is that many tools — including CreateMergeRequest — catch
exceptions inside their own _execute() method and return a JSON error
payload instead of letting the exception propagate:
# CreateMergeRequest._execute()
try:
response = self._process_http_response(...) # raises ToolException on 403
return json.dumps({"created_merge_request": response})
except Exception as e:
return json.dumps({"error": str(e)}) # ← returned as a "normal" stringBecause the exception never reaches _execute_tool(), the tool node:
- Logs
WORKFLOW_TOOL_SUCCESS(incorrect) - Fires
on_tool_execution_successUI event (incorrect) - Returns the JSON error string as a normal tool response
Then _extract_errors_from_responses() scans the string
{"error": "Request failed ..."} against its regex patterns — none match —
and concludes the execution was successful.
This is a systemic issue. The same pattern exists in many tools:
CreateMergeRequest, CreateBranch, CreateMergeRequestNote, CiLinter,
UpdateMergeRequest, and others that use _process_http_response inside a
try/except in _execute().
Affected code
| File | What |
|---|---|
duo_workflow_service/agent_platform/v1/components/one_off/nodes/tool_node_with_error_correction.py |
_execute_tool(), _extract_errors_from_responses() |
duo_workflow_service/agent_platform/experimental/components/one_off/nodes/tool_node_with_error_correction.py |
Same (experimental copy) |
Desired Outcome
Tools are audited on whether they transparently propagate errors rather than having their own handling, and fixed accordingly.