crewAIInc/crewAI · error · ValueError

Expected a LlamaBaseTool, got {type(tool)}

Error message

Expected a LlamaBaseTool, got {type(tool)}

What it means

LlamaIndexTool.from_tool type-checks its argument against llama_index.core.tools.BaseTool before wrapping it. Passing anything else — a function, a llama-index <0.9 legacy ToolMetadata object, or an object from an incompatible llama-index version — raises this ValueError because the wrapper relies on tool.metadata.fn_schema downstream.

Source

Thrown at lib/crewai-tools/src/crewai_tools/tools/llamaindex_tool/llamaindex_tool.py:34

        *args: Any,
        **kwargs: Any,
    ) -> Any:
        """Run tool."""
        tool = self.llama_index_tool

        if self.result_as_answer:
            return tool(*args, **kwargs).content

        return tool(*args, **kwargs)

    @classmethod
    def from_tool(cls, tool: Any, **kwargs: Any) -> LlamaIndexTool:
        from llama_index.core.tools import (  # type: ignore[import-not-found]
            BaseTool as LlamaBaseTool,
        )

        if not isinstance(tool, LlamaBaseTool):
            raise ValueError(f"Expected a LlamaBaseTool, got {type(tool)}")

        if tool.metadata.fn_schema is None:
            raise ValueError(
                "The LlamaIndex tool does not have an fn_schema specified."
            )
        args_schema = cast(type[BaseModel], tool.metadata.fn_schema)

        return cls(
            name=tool.metadata.name,
            description=tool.metadata.description,
            args_schema=args_schema,
            llama_index_tool=tool,
            **kwargs,
        )

    @classmethod
    def from_query_engine(
        cls,

View on GitHub (pinned to 754d7323be)

Solutions

  1. Wrap the object correctly: for functions use llama_index.core.tools.FunctionTool.from_defaults(fn=...), for query engines use LlamaIndexTool.from_query_engine(...)
  2. Align versions: upgrade llama-index so llama_index.core exists and matches the object being passed (pip install -U llama-index)
  3. Check for duplicate installs: `pip list | grep llama` and uninstall stragglers so isinstance uses one BaseTool class

Example fix

# before
from llama_index.core import VectorStoreIndex
engine = VectorStoreIndex.from_documents(docs).as_query_engine()
tool = LlamaIndexTool.from_tool(engine)  # ValueError

# after
tool = LlamaIndexTool.from_query_engine(engine, name="docs_qa", description="Answer questions over docs")
Defensive patterns

Strategy: type-guard

Validate before calling

def is_llama_base_tool(tool) -> bool:
    from llama_index.core.tools import BaseTool
    return isinstance(tool, BaseTool)

Type guard

from typing import Any

def is_llama_base_tool(tool: Any) -> "TypeGuard[Any]":
    try:
        from llama_index.core.tools import BaseTool
    except ImportError:
        return False
    return isinstance(tool, BaseTool)

Try / catch

try:
    crew_tool = LlamaIndexTool.from_tool(tool)
except ValueError as e:
    if "Expected a LlamaBaseTool" in str(e):
        from llama_index.core.tools import FunctionTool
        tool = FunctionTool.from_defaults(fn=tool)
        crew_tool = LlamaIndexTool.from_tool(tool)
    else:
        raise

Prevention

When it happens

Trigger: Calling LlamaIndexTool.from_tool(some_function); passing a llama-index v0.8/early-0.9-style tool object whose class no longer matches llama_index.core.tools.BaseTool; passing a QueryEngine instead of a wrapped tool (use from_query_engine for that); two llama-index copies installed so isinstance fails across module identities.

Common situations: Upgrading llama-index past 0.9 where the package moved from llama_index to llama_index.core; mixing llama-index versions in one env; confusion between from_tool (expects a BaseTool) and from_query_engine (expects a query engine).

Related errors


AI-assisted analysis of crewAIInc/crewAI@754d7323be (2026-08-15). Data as JSON: /api/errors/774fe400f0749151. Report an issue: GitHub.