diff --git a/lib/crewai/src/crewai/cli/utils.py b/lib/crewai/src/crewai/cli/utils.py index f9a3912f5..a23bdc85a 100644 --- a/lib/crewai/src/crewai/cli/utils.py +++ b/lib/crewai/src/crewai/cli/utils.py @@ -850,6 +850,19 @@ def _extract_env_vars(env_vars_field: dict[str, Any] | None) -> list[dict[str, A if not env_vars_field: return [] + schema = env_vars_field.get("schema", {}) + default = schema.get("default") + if default is None: + default_factory = schema.get("default_factory") + if callable(default_factory): + try: + default = default_factory() + except Exception: + default = [] + + if not isinstance(default, list): + return [] + return [ { "name": env_var.name, @@ -857,6 +870,6 @@ def _extract_env_vars(env_vars_field: dict[str, Any] | None) -> list[dict[str, A "required": env_var.required, "default": env_var.default, } - for env_var in env_vars_field.get("schema", {}).get("default", []) + for env_var in default if isinstance(env_var, EnvVar) ] diff --git a/lib/crewai/tests/cli/test_utils.py b/lib/crewai/tests/cli/test_utils.py index 40e5048c7..fc006a417 100644 --- a/lib/crewai/tests/cli/test_utils.py +++ b/lib/crewai/tests/cli/test_utils.py @@ -476,6 +476,35 @@ __all__ = ['MyTool'] assert env_vars[1]["default"] == "default_value" +def test_extract_tools_metadata_with_env_vars_field_default_factory(temp_project_dir): + """Test that extract_tools_metadata extracts env_vars declared with Field(default_factory=...).""" + create_init_file( + temp_project_dir, + """from crewai.tools import BaseTool +from crewai.tools.base_tool import EnvVar +from pydantic import Field + +class MyTool(BaseTool): + name: str = "my_tool" + description: str = "A test tool" + env_vars: list[EnvVar] = Field( + default_factory=lambda: [ + EnvVar(name="MY_TOOL_API", description="API token for my tool", required=True), + ] + ) + +__all__ = ['MyTool'] +""", + ) + metadata = utils.extract_tools_metadata(dir_path=str(temp_project_dir)) + assert len(metadata) == 1 + env_vars = metadata[0]["env_vars"] + assert len(env_vars) == 1 + assert env_vars[0]["name"] == "MY_TOOL_API" + assert env_vars[0]["description"] == "API token for my tool" + assert env_vars[0]["required"] is True + + def test_extract_tools_metadata_with_custom_init_params(temp_project_dir): """Test that extract_tools_metadata extracts init_params_schema with custom params.""" create_init_file(