{"record":{"id":"a017dd5e6b6fd558","repo":"JuliusBrussee/caveman","slug":"expected-an-existing-native-agno-model","errorCode":null,"errorMessage":"Expected an existing native Agno Model","messagePattern":"Expected an existing native Agno Model","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/middleware/python/caveman_middleware/agno.py","lineNumber":220,"sourceCode":"            overhead = json.dumps({\"type\": \"function\", \"function\": actual}, ensure_ascii=False, separators=(\",\", \":\"))\n        attempt = Attempt(runtime, scope, str(uuid.uuid4()), str(uuid.uuid4()), adapter=ADAPTER.id)\n        recheck = lambda: binding is None or (runtime.owns_binding(binding, scope) and self.binding_details(frame, options) is not None)\n        runtime_options = dict(scope=scope, adapter=ADAPTER, manifest=context, candidates=candidates, binding=binding,\n            model={\"provider\": model.provider or type(model).__name__, \"id\": model.id, \"protocol\": \"agno\"}, recovery_overhead_text=overhead,\n            logical_call_id=attempt.logical_call_id, attempt_id=attempt.attempt_id)\n        return attempt, paths, runtime_options, recheck\n\n\nclass CavemanModel(Model):\n    \"\"\"Native Agno Model delegate. Model-only use has no recovery executor.\n\n    Agno's Model.response methods retain orchestration. Only invoke/ainvoke and\n    their streaming equivalents receive a separate model-facing Message view.\n    The caller owns both its existing provider clients and the shared runtime.\n    \"\"\"\n    def __init__(self, model: Model, *, runtime=None, scope=None, connection=None):\n        if not isinstance(model, Model):\n            raise TypeError(\"Expected an existing native Agno Model\")\n        super().__init__(**{item.name: getattr(model, item.name) for item in fields(Model) if not item.name.startswith(\"_\")})\n        self.model = model\n        self.connection = connection or _Connection(runtime, scope)\n        self.signatures = {name: inspect.signature(getattr(model, name)) for name in (\"invoke\", \"ainvoke\", \"invoke_stream\", \"ainvoke_stream\")}\n\n    def get_provider(self):\n        return self.model.get_provider()\n\n    def to_dict(self):\n        return self.model.to_dict()\n\n    def count_tokens(self, *args, **kwargs):\n        return self.model.count_tokens(*args, **kwargs)\n\n    async def acount_tokens(self, *args, **kwargs):\n        return await self.model.acount_tokens(*args, **kwargs)\n\n    def get_system_message_for_model(self, tools=None):","sourceCodeStart":202,"sourceCodeEnd":238,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/3ee70a102609e550bd2e68004bf5990a9341c851/packages/middleware/python/caveman_middleware/agno.py#L202-L238","documentation":"CavemanMiddlewareModel is a wrapper around an existing native Agno Model instance; it copies the wrapped model's fields and delegates to it. Passing anything that is not an agno Model instance (a class, a string model id, or None) cannot be wrapped, so __init__ raises TypeError.","triggerScenarios":"Passing a model identifier string (e.g. 'gpt-4o') instead of a constructed agno Model; passing the Model class rather than an instance; passing None because the model was built conditionally.","commonSituations":"Migrating code where a plain model name was previously accepted; confusion with providers that accept string model ids; instantiating the wrapper before creating the underlying provider model.","solutions":["Construct the native Agno model first and pass the instance to CavemanMiddlewareModel","Verify imports: Model should be the agno models base class and your instance its subclass","Ensure the model variable is not None due to failed conditional construction"],"exampleFix":"// before\nmodel = CavemanMiddlewareModel(\"gpt-4o\")\n// after\nfrom agno.models.openai import OpenAIChat\nmodel = CavemanMiddlewareModel(OpenAIChat(id=\"gpt-4o\"), runtime=runtime)","handlingStrategy":"type-guard","validationCode":"from agno.models.base import Model as AgnoModel\nif not isinstance(candidate, AgnoModel):\n    raise TypeError('pass a constructed agno Model instance')","typeGuard":"def is_agno_model(obj) -> bool:\n    from agno.models.base import Model as AgnoModel\n    return isinstance(obj, AgnoModel)","tryCatchPattern":"try:\n    wrapped = CavemanMiddlewareModel(model, runtime=runtime)\nexcept TypeError:\n    wrapped = CavemanMiddlewareModel(construct_model(model_id), runtime=runtime)","preventionTips":["Always build the provider model instance before wrapping","Wrap in a factory that constructs Model from a string id","Add unit tests constructing the wrapper with real model instances"],"tags":["python","agno","constructor","typeerror"],"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"}