{"record":{"id":"36ff53daf9e2fbdd","repo":"JuliusBrussee/caveman","slug":"synchronous-agno-calls-require-middlewareruntime","errorCode":null,"errorMessage":"Synchronous Agno calls require MiddlewareRuntime","messagePattern":"Synchronous Agno calls require MiddlewareRuntime","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/middleware/python/caveman_middleware/agno.py","lineNumber":365,"sourceCode":"\n    def _apply_prepared(self, messages, state, outcome):\n        attempt, paths, _, recheck = state\n        attempt.optimization = outcome if not outcome.replacements else None\n        if not recheck():\n            attempt.reason = \"recovery_unavailable\"\n            return messages\n        if any(item[\"segment_id\"] not in paths for item in outcome.replacements):\n            attempt.reason = \"invalid_plan\"\n            return messages\n        view = _apply(messages, outcome, paths)\n        attempt.optimization = outcome\n        return view\n\n    def invoke(self, messages, *args, **kwargs):\n        self._check_cancelled()\n        runtime = self.connection.sync\n        if runtime is None:\n            raise TypeError(\"Synchronous Agno calls require MiddlewareRuntime\")\n        state = self._prepare(\"invoke\", messages, args, kwargs, runtime)\n        attempt = None\n        if state:\n            attempt, _, options, _ = state\n            if options is not None:\n                messages = self._apply_prepared(messages, state, runtime.optimize(**options))\n        self._check_cancelled()\n        if attempt:\n            attempt.observe(\"dispatch_intent\")\n        token = owner.set(attempt) if attempt else None\n        try:\n            result = self.model.invoke(messages, *args, **kwargs)\n            if attempt:\n                attempt.observe(\"completed\", _usage(result))\n            return result\n        except BaseException:\n            if attempt:\n                attempt.observe(\"failed\")","sourceCodeStart":347,"sourceCodeEnd":383,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/3ee70a102609e550bd2e68004bf5990a9341c851/packages/middleware/python/caveman_middleware/agno.py#L347-L383","documentation":"The sync invoke path of the Agno middleware model requires a synchronous MiddlewareRuntime (self.connection.sync). When the adapter was configured only with an async runtime, sync model calls cannot be prepared/optimized, so a TypeError is raised before any LLM call.","triggerScenarios":"Calling model.invoke(...) on a CavemanMiddlewareModel whose connection has only an async runtime.","commonSituations":"An app configured with AsyncMiddlewareRuntime for async agents, but some agent/tool path calls the model synchronously; mixing sync Agno agents with an async-only middleware setup.","solutions":["Provide a sync MiddlewareRuntime to the adapter/connection","Switch the calling code to the async path (await model.ainvoke(...))","Use runtime.mode 'off' or a sync-capable runtime if sync calls are required"],"exampleFix":"# before\nmiddleware = CavemanAgno(async_runtime=AsyncMiddlewareRuntime(...))\nmodel.invoke(messages)  # TypeError\n# after\nawait model.ainvoke(messages)","handlingStrategy":"type-guard","validationCode":"if connection.sync is None:\n    raise RuntimeError('sync invoke needs a MiddlewareRuntime; use ainvoke')","typeGuard":"def supports_sync_invoke(model) -> bool:\n    return model.connection.sync is not None","tryCatchPattern":"try:\n    result = model.invoke(messages)\nexcept TypeError as e:\n    if 'MiddlewareRuntime' in str(e):\n        result = await model.ainvoke(messages)\n    else:\n        raise","preventionTips":["Keep sync and async runtimes paired in configuration","Route async-configured apps exclusively through ainvoke/ainvoke_stream","Assert runtime presence in app startup"],"tags":["python","sync-async","agno","typeerror"],"backgroundTag":"type-mismatch","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"}