{"record":{"id":"47132b3bb0a3a44b","repo":"crewAIInc/crewAI","slug":"the-llamaindex-tool-does-not-have-an-fn-schema-spe","errorCode":null,"errorMessage":"The LlamaIndex tool does not have an fn_schema specified.","messagePattern":"The LlamaIndex tool does not have an fn_schema specified\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"lib/crewai-tools/src/crewai_tools/tools/llamaindex_tool/llamaindex_tool.py","lineNumber":37,"sourceCode":"        \"\"\"Run tool.\"\"\"\n        tool = self.llama_index_tool\n\n        if self.result_as_answer:\n            return tool(*args, **kwargs).content\n\n        return tool(*args, **kwargs)\n\n    @classmethod\n    def from_tool(cls, tool: Any, **kwargs: Any) -> LlamaIndexTool:\n        from llama_index.core.tools import (  # type: ignore[import-not-found]\n            BaseTool as LlamaBaseTool,\n        )\n\n        if not isinstance(tool, LlamaBaseTool):\n            raise ValueError(f\"Expected a LlamaBaseTool, got {type(tool)}\")\n\n        if tool.metadata.fn_schema is None:\n            raise ValueError(\n                \"The LlamaIndex tool does not have an fn_schema specified.\"\n            )\n        args_schema = cast(type[BaseModel], tool.metadata.fn_schema)\n\n        return cls(\n            name=tool.metadata.name,\n            description=tool.metadata.description,\n            args_schema=args_schema,\n            llama_index_tool=tool,\n            **kwargs,\n        )\n\n    @classmethod\n    def from_query_engine(\n        cls,\n        query_engine: Any,\n        name: str | None = None,\n        description: str | None = None,","sourceCodeStart":19,"sourceCodeEnd":55,"githubUrl":"https://github.com/crewAIInc/crewAI/blob/754d7323beb2fd042e33444a115ea2d5a47193f0/lib/crewai-tools/src/crewai_tools/tools/llamaindex_tool/llamaindex_tool.py#L19-L55","documentation":"After confirming the object is a llama-index BaseTool, LlamaIndexTool.from_tool requires tool.metadata.fn_schema (the pydantic schema describing the tool's arguments) because CrewAI builds its args_schema from it. Tools created without a schema — e.g. FunctionTool.from_defaults(fn=...) without explicit fn_schema on some paths, or custom tools with metadata.fn_schema left None — fail here.","triggerScenarios":"Calling from_tool on a BaseTool whose ToolMetadata was constructed without fn_schema; passing tools built by older llama-index factory methods that infer schemas lazily; passing a tool whose fn_schema is dynamically None (e.g. async tools without schema).","commonSituations":"Wrapping hand-written llama-index tools; llama-index version drift where from_defaults no longer auto-generates fn_schema for the object you hold; wrapping tools that only define metadata at call time.","solutions":["Provide an explicit schema when building the llama-index tool: FunctionTool.from_defaults(fn=my_fn, fn_schema=MySchema) where MySchema is a pydantic BaseModel","Set tool.metadata.fn_schema manually before calling from_tool if you control the metadata","Upgrade llama-index so from_defaults reliably attaches DefaultToolFnSchema"],"exampleFix":"# before\nfrom llama_index.core.tools import FunctionTool\nt = FunctionTool.from_defaults(fn=lambda q: lookup(q))  # fn_schema may be None\ncrew_tool = LlamaIndexTool.from_tool(t)  # ValueError\n\n# after\nfrom pydantic import BaseModel, Field\nclass LookupSchema(BaseModel):\n    query: str = Field(..., description=\"Query string\")\nt = FunctionTool.from_defaults(fn=lookup, fn_schema=LookupSchema)\ncrew_tool = LlamaIndexTool.from_tool(t)","handlingStrategy":"validation","validationCode":"def tool_has_fn_schema(tool) -> bool:\n    meta = getattr(tool, \"metadata\", None)\n    return getattr(meta, \"fn_schema\", None) is not None","typeGuard":"def has_fn_schema(tool: Any) -> \"TypeGuard[Any]\":\n    return getattr(getattr(tool, \"metadata\", None), \"fn_schema\", None) is not None","tryCatchPattern":"try:\n    crew_tool = LlamaIndexTool.from_tool(tool)\nexcept ValueError as e:\n    if \"fn_schema\" in str(e):\n        from pydantic import BaseModel, Field\n        class Schema(BaseModel):\n            query: str = Field(...)\n        tool.metadata.fn_schema = Schema\n        crew_tool = LlamaIndexTool.from_tool(tool)\n    else:\n        raise","preventionTips":["Always build llama-index tools with an explicit fn_schema (pydantic BaseModel)","Check tool.metadata.fn_schema before wrapping","Write a unit test that wraps each llama-index tool you plan to expose to a crew"],"tags":["llamaindex","schema","validation","crewai-tools"],"backgroundTag":null,"analyzedSha":"754d7323beb2fd042e33444a115ea2d5a47193f0","analyzedAt":"2026-08-15T04:06:56.746Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}