fix: catch RecursionError when converting tools to SPARC specs on Python 3.14

`PreToolValidationWrapper.convert_langchain_tools_to_sparc_tool_specs_format`
degrades to a minimal tool spec when a tool can't be introspected, but its
`except` tuple omitted `RuntimeError`. On Python 3.14 + langchain-core 1.4.7,
reading `tool.args` for a tool whose `args_schema` is not a usable model (e.g. a
`@property` that shadows the inherited Pydantic field) returns the raw property
object, so langchain's `get_all_basemodel_annotations` recurses on
`get_origin(<property>) -> None -> None -> ...` and raises `RecursionError` (a
`RuntimeError` subclass) -- which escaped the handler and crashed conversion
(surfaced by test_altk_agent_tool_conversion.py::test_error_handling).

Add `RuntimeError` to the caught tuple, matching the two sibling handlers in the
same module that already catch it. This restores the intended fall-back to a
minimal spec and hardens real agent runs against the same recursion.
This commit is contained in:
Eric Hare
2026-06-16 19:57:10 -07:00
parent a383f4d426
commit 88ed381cf0

View File

@ -390,7 +390,10 @@ class PreToolValidationWrapper(BaseToolWrapper):
tool_specs.append(tool_spec)
except (AttributeError, KeyError, TypeError, ValueError) as e:
except (AttributeError, KeyError, TypeError, ValueError, RuntimeError) as e:
# RuntimeError covers RecursionError, which langchain_core's
# get_all_basemodel_annotations can raise on Python 3.14 when a tool's
# args_schema is not a usable model (e.g. a shadowing property object).
logger.warning(f"Could not convert tool {getattr(tool, 'name', 'unknown')} to spec: {e}")
# Create minimal spec
minimal_spec = {