JuliusBrussee/caveman · error · ImportError

Install caveman-middleware[crewai] to use the CrewAI adapter

Error message

Install caveman-middleware[crewai] to use the CrewAI adapter

What it means

The CrewAI adapter in caveman_middleware imports optional CrewAI dependencies (crewai.llms, crewai.tools, crewai.utilities) at module import time. If CrewAI is not installed, this ImportError is raised as the cause-chained error, telling you to install the optional extra instead of a raw ModuleNotFoundError.

Solutions

  1. Run pip install "caveman-middleware[crewai]" to install CrewAI with the supported version range.
  2. Add caveman-middleware[crewai] to your requirements/pyproject dependencies and reinstall.
  3. Verify crewai imports directly: python -c "import crewai.llms.base_llm"; if that fails, upgrade/reinstall crewai to a version providing those submodules.

Example fix

// before
pip install caveman-middleware
// after
pip install "caveman-middleware[crewai]"
Defensive patterns

Strategy: try-catch

Validate before calling

try:
    from crewai.llms.base_llm import BaseLLM
except ModuleNotFoundError:
    raise RuntimeError("Run: pip install 'caveman-middleware[crewai]'")

Type guard

def crewai_extra_installed() -> bool:
    import importlib.util
    return importlib.util.find_spec("crewai") is not None

Try / catch

try:
    from caveman_middleware import crewai as caveman_crewai
except ImportError as e:
    logging.error("Install the extra: pip install 'caveman-middleware[crewai]' (%s)", e)
    raise

Prevention

When it happens

Trigger: Importing caveman_middleware.crewai (or any code path that imports the CrewAI adapter) in an environment where the `crewai` package (or one of its imported submodules) is missing. Triggered during `import`, before any adapter API is used.

Common situations: Installing caveman-middleware without extras (pip install caveman-middleware instead of caveman-middleware[crewai]); deploying to an environment where the extra was omitted from requirements; a CrewAI version change renaming submodules like crewai.llms.base_llm.

Understand the failure class

Background: "X is not installed. Please install it with pip install Y": missing optional dependency errors — ImportError/ValueError raised when a library's optional extra was never installed — this error's family across 22 libraries.

Related errors


AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20). Data as JSON: /api/errors/a6789914dee17b48. Report an issue: GitHub.

Appendix: source

Thrown at packages/middleware/python/caveman_middleware/crewai.py:29

import threading
import uuid
import weakref
from contextlib import ExitStack
from dataclasses import dataclass, field
from importlib.metadata import version
from typing import Any

try:
    from crewai import BaseLLM
    from crewai.events import LLMCallCompletedEvent, crewai_event_bus
    from crewai.hooks import InterceptionPoint, on, unregister_hook
    from crewai.llms.base_llm import call_stop_override, call_stream_override
    from crewai.tools import BaseTool
    from crewai.utilities.agent_utils import convert_tools_to_openai_schema
    from crewai.utilities.string_utils import sanitize_tool_name
    from pydantic import BaseModel, ConfigDict, Field, PrivateAttr
except ModuleNotFoundError as error:
    raise ImportError("Install caveman-middleware[crewai] to use the CrewAI adapter") from error

from caveman_cloud.middleware import Adapter, Candidate, MiddlewareError, MiddlewareRuntime, Scope
from caveman_cloud.middleware.runtime import RECOVERY_DESCRIPTION
from ._native import Attempt, leaves, manifest, owner, plain, replace_path
from ._versions import matches_framework
from ._usage import usage

FRAMEWORK_VERSION = version("crewai")
ADAPTER = Adapter("crewai", "0.1.0", FRAMEWORK_VERSION, "crewai-messages-v1")
_call = contextvars.ContextVar("caveman_crewai_call", default=None)


class _RecoveryInput(BaseModel):
    model_config = ConfigDict(extra="forbid")
    handle: str = Field(pattern=r"^cmw_[a-f0-9]{48}$")
    offset: int = Field(default=0, ge=0)
    limit: int = Field(default=262144, ge=4, le=262144)
    query: str = Field(default="", max_length=1024)

View on GitHub (pinned to 3ee70a1026)