From 88ed381cf0fafdf4fa060ef61755dae47fea28d8 Mon Sep 17 00:00:00 2001 From: Eric Hare Date: Tue, 16 Jun 2026 19:57:10 -0700 Subject: [PATCH] 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() -> 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. --- src/lfx/src/lfx/base/agents/altk_tool_wrappers.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/lfx/src/lfx/base/agents/altk_tool_wrappers.py b/src/lfx/src/lfx/base/agents/altk_tool_wrappers.py index 2fb767313b..fb693fef81 100644 --- a/src/lfx/src/lfx/base/agents/altk_tool_wrappers.py +++ b/src/lfx/src/lfx/base/agents/altk_tool_wrappers.py @@ -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 = {