{"record":{"id":"c0fac66717606e0a","repo":"JuliusBrussee/caveman","slug":"expected-an-installed-crewai-basellm","errorCode":null,"errorMessage":"Expected an installed CrewAI BaseLLM","messagePattern":"Expected an installed CrewAI BaseLLM","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/middleware/python/caveman_middleware/crewai.py","lineNumber":111,"sourceCode":"\n    Use ``with_caveman_agent`` to register the matching recovery BaseTool.\n    Register before creating the Agent, whose executor snapshots native hooks.\n    ``close`` removes only this delegate's registrations. The application keeps\n    ownership of the native provider client and the Caveman runtime.\n    \"\"\"\n    llm_type: str = \"caveman\"\n    delegate: BaseLLM = Field(exclude=True, repr=False)\n    runtime: Any = Field(exclude=True, repr=False)\n    scope: Scope\n    closed: bool = Field(default=False, exclude=True)\n    _context: Any = PrivateAttr()\n    _hook: Any = PrivateAttr(default=None)\n    _completed: Any = PrivateAttr(default=None)\n    _recovery: Any = PrivateAttr(default=None)\n\n    def __init__(self, delegate, *, runtime, scope):\n        if not isinstance(delegate, BaseLLM):\n            raise TypeError(\"Expected an installed CrewAI BaseLLM\")\n        if not isinstance(runtime, MiddlewareRuntime) or not isinstance(scope, Scope):\n            raise TypeError(\"CrewAI requires a MiddlewareRuntime and a stable Scope per agent context\")\n        super().__init__(delegate=delegate, runtime=runtime, scope=scope, model=delegate.model,\n                         provider=delegate.provider, stream=delegate.stream, stop=list(delegate.stop),\n                         is_litellm=delegate.is_litellm)\n        self._context = contextvars.ContextVar(f\"caveman_crewai_context_{id(self)}\", default=None)\n        supported = matches_framework((\"crewai\", \"1.15\", \"2\"))\n        if not supported and runtime.mode != \"off\":\n            runtime.decline(\"unsupported_version\")\n        if not supported or runtime.mode == \"off\":\n            return\n        reference = weakref.ref(self)\n\n        @on(InterceptionPoint.PRE_MODEL_CALL)\n        def before(context):\n            model = reference()\n            if model is not None and not model.closed and context.llm is model:\n                # Store only a weak executor reference. Aborted hooks and stale","sourceCodeStart":93,"sourceCodeEnd":129,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/3ee70a102609e550bd2e68004bf5990a9341c851/packages/middleware/python/caveman_middleware/crewai.py#L93-L129","documentation":"CavemanLLM (the CrewAI middleware LLM wrapper) is a pydantic-model wrapper around a native CrewAI BaseLLM instance. Its __init__ type-checks the delegate and raises TypeError if the object passed as delegate is not an instance of crewai BaseLLM, because all delegation (model, provider, stream, stop, is_litellm) relies on BaseLLM attributes.","triggerScenarios":"Passing a non-BaseLLM object as the first positional argument to CavemanLLM's __init__ — e.g. a raw litellm/openai client, a string model name, a Crew (agent) object, or a None value instead of the constructed LLM.","commonSituations":"Constructing the wrapper before building the actual CrewAI LLM; confusing the model name string with the LLM instance; passing an already-wrapped CavemanLLM back in (double wrapping); older CrewAI versions with different LLM base classes so isinstance fails.","solutions":["Pass an instantiated crewai BaseLLM (e.g. from crewai.llms import LLM; LLM(model=...)) as the delegate.","Check isinstance(delegate, BaseLLM) before constructing the wrapper.","If on an older/newer CrewAI where the base class moved, verify the import 'from crewai.llms.base_llm import BaseLLM' resolves and use that class."],"exampleFix":"// before\nwrapped = CavemanLLM(\"gpt-4o\", runtime=runtime, scope=scope)\n// after\nfrom crewai.llms import LLM\nwrapped = CavemanLLM(LLM(model=\"gpt-4o\"), runtime=runtime, scope=scope)","handlingStrategy":"type-guard","validationCode":"from crewai.llms.base_llm import BaseLLM\nif not isinstance(delegate, BaseLLM):\n    raise TypeError(\"delegate must be a crewai BaseLLM instance\")","typeGuard":"def is_valid_delegate(obj) -> bool:\n    from crewai.llms.base_llm import BaseLLM\n    return isinstance(obj, BaseLLM)","tryCatchPattern":"try:\n    wrapped = CavemanLLM(delegate, runtime=runtime, scope=scope)\nexcept TypeError as e:\n    if \"BaseLLM\" in str(e):\n        delegate = LLM(model=delegate) if isinstance(delegate, str) else None\n        wrapped = CavemanLLM(delegate, runtime=runtime, scope=scope)\n    else:\n        raise","preventionTips":["Always instantiate the CrewAI LLM before wrapping it.","Never pass a model-name string where an LLM instance is expected.","Avoid double-wrapping: check isinstance(obj, CavemanLLM) before wrapping.","Pin crewai to a supported version so BaseLLM's import path is stable."],"tags":["crewai","type-check","constructor","basellm"],"backgroundTag":"invalid-constructor-argument","analyzedSha":"3ee70a102609e550bd2e68004bf5990a9341c851","analyzedAt":"2026-09-20T15:53:39.229Z","contentChangedAt":"2026-09-20T15:53:39.229Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}