fix: tolerate malformed tool output schemas at agent startup [PC-4546]#983
fix: tolerate malformed tool output schemas at agent startup [PC-4546]#983UiPathPetruPopa wants to merge 8 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
This PR prevents agent startup failures on URT when a tool’s output JSON schema is malformed (e.g., dangling $ref from legacy Temporal/.NET runtime exports). Since tool output schemas are design-time only, the new behavior degrades output typing to an empty model with a warning instead of raising AGENT_STARTUP.INVALID_TOOL_CONFIG.
Changes:
- Added
create_output_model()to convert tool output schemas non-fatally, falling back to an empty schema and logging a warning. - Updated the 5 tool factories that convert output schemas (
process,escalation,integration,analyze_files,deeprag) to usecreate_output_model(). - Added coverage ensuring malformed output schemas don’t block tool creation; bumped package version to
0.14.6.
Reviewed changes
Copilot reviewed 8 out of 9 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
src/uipath_langchain/agent/react/jsonschema_pydantic_converter.py |
Adds non-fatal output-schema conversion with a safe empty-model fallback and warning logging. |
src/uipath_langchain/agent/tools/process_tool.py |
Uses create_output_model() for process tool output schema conversion. |
src/uipath_langchain/agent/tools/escalation_tool.py |
Uses create_output_model() for escalation channel output schema conversion. |
src/uipath_langchain/agent/tools/integration_tool.py |
Uses create_output_model() for integration tool output schema conversion (when present). |
src/uipath_langchain/agent/tools/internal_tools/analyze_files_tool.py |
Uses create_output_model() for internal analyze-files output schema conversion. |
src/uipath_langchain/agent/tools/internal_tools/deeprag_tool.py |
Uses create_output_model() for DeepRAG output schema conversion. |
tests/agent/tools/test_tool_factory.py |
Adds a regression test ensuring malformed output schemas are non-blocking across the 5 affected tool factories. |
pyproject.toml |
Bumps project version to 0.14.6. |
uv.lock |
Updates locked version to 0.14.6. |
andreitava-uip
left a comment
There was a problem hiding this comment.
We have to think of a different fallback, Ideally only remove the malformed parts and keep the rest of the fields?
513cc17 to
871a960
Compare
| except AgentStartupError as e: | ||
| # Last-resort net for a non-$ref failure we didn't neutralize. Intentionally | ||
| # narrow (AgentStartupError only): other errors are unexpected and should | ||
| # surface rather than be silently swallowed. | ||
| logger.warning( | ||
| "Tool %r output schema still unparseable after neutralizing dangling " | ||
| "refs; falling back to an empty model (non-blocking): %s", | ||
| tool_name, | ||
| e.error_info.detail, | ||
| ) | ||
| return create_model(_EMPTY_OUTPUT_SCHEMA) |
There was a problem hiding this comment.
I'd remove this last resort fallback. The dangling refs fix is good because it (mostly) preserves functionality such as file attachments and guardrails.
For more fatal issues, I'd rather throw up-front than run into obscure silent bugs at runtime.
Most malformed issues we discovered were such dangling refs. Until further notice I wouldn't add extra fallbacks.
There was a problem hiding this comment.
Removed last resort fallback.
|
| title="Invalid schema", | ||
| detail=( | ||
| f"Type '{type_name}' could not be resolved. " | ||
| f"Check that all $ref targets have matching entries in $defs." |
There was a problem hiding this comment.
nit: Is this message applicable here since this case is treated in the create_output_model method?



Agents that ran on the legacy Temporal/.NET runtime crash on URT at startup with
AGENT_STARTUP.INVALID_TOOL_CONFIGwhen a tool's output schema has a dangling$ref(e.g. a .NETdecimal?→Nullableofdecimalwith no$defs). URT eagerlyconverts every tool schema to Pydantic and throws; the old runtime never resolved
$refs. Output schemas are design-time only (guardrails + eval sims), never usedduring execution, so the crash is gratuitous.
create_output_model()injsonschema_pydantic_converter.py— falls backto an empty model (with a warning) instead of raising on an unparseable schema.
process,escalation,integration,analyze_files,deeprag.in
react/utils.py(used at runtime for terminate-node validation).