{"record":{"id":"bbe2af3e63c144e0","repo":"JuliusBrussee/caveman","slug":"crewai-requires-a-middlewareruntime-and-a-stable-scope-per","errorCode":null,"errorMessage":"CrewAI requires a MiddlewareRuntime and a stable Scope per agent context","messagePattern":"CrewAI requires a MiddlewareRuntime and a stable Scope per agent context","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/middleware/python/caveman_middleware/crewai.py","lineNumber":113,"sourceCode":"    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\n                # executor snapshots cannot retain complete message histories.\n                model._context.set(weakref.ref(context.executor) if context.executor is not None else None)","sourceCodeStart":95,"sourceCodeEnd":131,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/3ee70a102609e550bd2e68004bf5990a9341c851/packages/middleware/python/caveman_middleware/crewai.py#L95-L131","documentation":"CavemanLLM's __init__ validates that the keyword arguments runtime and scope are instances of MiddlewareRuntime and Scope respectively. The middleware requires a runtime for interception and a stable per-agent Scope so recovery and usage can be keyed consistently; passing anything else raises this TypeError.","triggerScenarios":"Calling CavemanLLM(delegate, runtime=<not a MiddlewareRuntime>, scope=<not a Scope>) — e.g. runtime as a plain config dict or string mode, scope as a string identifier, or either argument omitted/None.","commonSituations":"Hand-rolling the runtime instead of using the library's factory; passing a scope name string where a Scope object is required; reusing a single global scope across agents instead of a stable per-agent context; upgrading caveman-middleware and old positional/keyword shapes no longer match.","solutions":["Construct runtime with the library's MiddlewareRuntime factory and pass that instance.","Build a proper Scope object (one per agent context) rather than a string or dict.","Check isinstance(runtime, MiddlewareRuntime) and isinstance(scope, Scope) before constructing the wrapper."],"exampleFix":"// before\nwrapped = CavemanLLM(llm, runtime=\"on\", scope=\"agent-1\")\n// after\nfrom caveman_cloud.middleware import MiddlewareRuntime, Scope\nwrapped = CavemanLLM(llm, runtime=MiddlewareRuntime(...), scope=Scope(...))","handlingStrategy":"type-guard","validationCode":"from caveman_cloud.middleware import MiddlewareRuntime, Scope\nif not isinstance(runtime, MiddlewareRuntime) or not isinstance(scope, Scope):\n    raise TypeError(\"Pass MiddlewareRuntime and Scope instances\")","typeGuard":"def valid_runtime_scope(runtime, scope) -> bool:\n    from caveman_cloud.middleware import MiddlewareRuntime, Scope\n    return isinstance(runtime, MiddlewareRuntime) and isinstance(scope, Scope)","tryCatchPattern":"try:\n    wrapped = CavemanLLM(llm, runtime=runtime, scope=scope)\nexcept TypeError as e:\n    if \"MiddlewareRuntime\" in str(e):\n        raise ConfigError(\"Build runtime/scope with the caveman middleware factories\") from e\n    raise","preventionTips":["Create runtime and scope via the library's factories, never ad-hoc dicts/strings.","Give each agent context its own stable Scope instance.","Add a small factory function that constructs runtime+scope so call sites can't pass wrong types.","Assert types once at startup rather than per call."],"tags":["crewai","type-check","runtime","scope"],"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"}