{"record":{"id":"321ac5b7716ae5d3","repo":"JuliusBrussee/caveman","slug":"expected-a-native-strands-model","errorCode":null,"errorMessage":"Expected a native Strands Model","messagePattern":"Expected a native Strands Model","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/middleware/python/caveman_middleware/strands.py","lineNumber":37,"sourceCode":"from ._native import Attempt, manifest, owner, plain, replace_path\nfrom ._versions import matches_framework\nfrom ._usage import usage\n\nADAPTER = Adapter(\"strands\", \"0.1.0\", \"1.55.0\", \"strands-content-v1\")\n\n\ndef _scope(source, state):\n    scope = source if isinstance(source, Scope) else source(state or {})\n    if not isinstance(scope, Scope):\n        raise TypeError(\"Strands scope resolver must return a Caveman Scope\")\n    return scope\n\n\nclass CavemanModel(Model):\n    \"\"\"Public native model delegate. A model wrapper alone is recovery-free.\"\"\"\n    def __init__(self, model, *, runtime, scope):\n        if not isinstance(model, Model):\n            raise TypeError(\"Expected a native Strands Model\")\n        self.model = model\n        self.runtime = runtime.as_async() if isinstance(runtime, MiddlewareRuntime) else runtime\n        self.scope, self.registration = scope, None\n        self.version_supported = matches_framework((\"strands-agents\", \"1.55\", \"2\"))\n        if not self.version_supported and self.runtime.mode != \"off\":\n            self.runtime.decline(\"unsupported_version\")\n\n    @property\n    def stateful(self):\n        return self.model.stateful\n\n    def update_config(self, **model_config):\n        return self.model.update_config(**model_config)\n\n    def get_config(self):\n        return self.model.get_config()\n\n    async def count_tokens(self, *args, **kwargs):","sourceCodeStart":19,"sourceCodeEnd":55,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/3ee70a102609e550bd2e68004bf5990a9341c851/packages/middleware/python/caveman_middleware/strands.py#L19-L55","documentation":"CavemanModel for Strands delegates stream/structured calls to a native strands Model instance. The constructor type-checks the model argument; passing anything else (a model id string, a Bedrock client, None) is rejected with a TypeError.","triggerScenarios":"Calling CavemanModel(\"us.anthropic.claude-...\") with a model ID string; passing a boto3 client or a config dict instead of a strands.models.model.Model instance.","commonSituations":"Confusing Bedrock model identifiers with instantiated Strands Model objects; refactoring from another framework where models were referenced by name; mocks in tests that do not subclass strands Model.","solutions":["Pass an instantiated native model, e.g. CavemanModel(BedrockModel(model_id=\"us.anthropic.claude-...\"), runtime=..., scope=...)","Build the underlying model via the strands provider classes before wrapping","Validate with isinstance(model, Model) before constructing CavemanModel"],"exampleFix":"// before\nmodel = CavemanModel(\"us.anthropic.claude-3-7-sonnet-20250219-v1:0\", runtime=rt, scope=scope)\n// after\nfrom strands.models.bedrock import BedrockModel\nmodel = CavemanModel(BedrockModel(model_id=\"us.anthropic.claude-3-7-sonnet-20250219-v1:0\"), runtime=rt, scope=scope)","handlingStrategy":"type-guard","validationCode":"from strands.models.model import Model\nassert isinstance(model, Model), \"CavemanModel needs a native strands Model instance\"","typeGuard":"def is_strands_model(x) -> bool:\n    return isinstance(x, Model)","tryCatchPattern":"try:\n    model = CavemanModel(model_arg, runtime=rt, scope=scope)\nexcept TypeError as e:\n    if \"native Strands Model\" in str(e):\n        model_arg = BedrockModel(model_id=str(model_arg))\n        model = CavemanModel(model_arg, runtime=rt, scope=scope)\n    else:\n        raise","preventionTips":["Build the model with strands provider classes (BedrockModel, AnthropicModel, ...) before wrapping","Never pass model-id strings or raw cloud clients to CavemanModel","Validate isinstance(x, Model) at configuration load time","Use real Model instances in tests rather than plain mocks"],"tags":["python","strands","constructor","type-error"],"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"}