JuliusBrussee/caveman · error · TypeError

Expected a native Strands Model

Error message

Expected a native Strands Model

What it means

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.

Solutions

  1. Pass an instantiated native model, e.g. CavemanModel(BedrockModel(model_id="us.anthropic.claude-..."), runtime=..., scope=...)
  2. Build the underlying model via the strands provider classes before wrapping
  3. Validate with isinstance(model, Model) before constructing CavemanModel

Example fix

// before
model = CavemanModel("us.anthropic.claude-3-7-sonnet-20250219-v1:0", runtime=rt, scope=scope)
// after
from strands.models.bedrock import BedrockModel
model = CavemanModel(BedrockModel(model_id="us.anthropic.claude-3-7-sonnet-20250219-v1:0"), runtime=rt, scope=scope)
Defensive patterns

Strategy: type-guard

Validate before calling

from strands.models.model import Model
assert isinstance(model, Model), "CavemanModel needs a native strands Model instance"

Type guard

def is_strands_model(x) -> bool:
    return isinstance(x, Model)

Try / catch

try:
    model = CavemanModel(model_arg, runtime=rt, scope=scope)
except TypeError as e:
    if "native Strands Model" in str(e):
        model_arg = BedrockModel(model_id=str(model_arg))
        model = CavemanModel(model_arg, runtime=rt, scope=scope)
    else:
        raise

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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

Appendix: source

Thrown at packages/middleware/python/caveman_middleware/strands.py:37

from ._native import Attempt, manifest, owner, plain, replace_path
from ._versions import matches_framework
from ._usage import usage

ADAPTER = Adapter("strands", "0.1.0", "1.55.0", "strands-content-v1")


def _scope(source, state):
    scope = source if isinstance(source, Scope) else source(state or {})
    if not isinstance(scope, Scope):
        raise TypeError("Strands scope resolver must return a Caveman Scope")
    return scope


class CavemanModel(Model):
    """Public native model delegate. A model wrapper alone is recovery-free."""
    def __init__(self, model, *, runtime, scope):
        if not isinstance(model, Model):
            raise TypeError("Expected a native Strands Model")
        self.model = model
        self.runtime = runtime.as_async() if isinstance(runtime, MiddlewareRuntime) else runtime
        self.scope, self.registration = scope, None
        self.version_supported = matches_framework(("strands-agents", "1.55", "2"))
        if not self.version_supported and self.runtime.mode != "off":
            self.runtime.decline("unsupported_version")

    @property
    def stateful(self):
        return self.model.stateful

    def update_config(self, **model_config):
        return self.model.update_config(**model_config)

    def get_config(self):
        return self.model.get_config()

    async def count_tokens(self, *args, **kwargs):

View on GitHub (pinned to 3ee70a1026)