{"record":{"id":"994b8f0dfacf144b","repo":"agentscope-ai/agentscope","slug":"type-self-name-does-not-implement-on-reply","errorCode":null,"errorMessage":"{type(self).__name__} does not implement on_reply","messagePattern":"(.+?) does not implement on_reply","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"src/agentscope/middleware/_base.py","lineNumber":96,"sourceCode":"        ``Msg`` is only produced once the event escapes the whole chain.\n        When swallowing an exceed-max-iters end, unblock the next round\n        first (e.g. adjust ``cur_iter`` or ``max_iters``). Interrupted\n        ends cannot be swallowed to continue the reply.\n\n        Args:\n            agent: The Agent instance executing this middleware\n            input_kwargs: Dictionary containing:\n                - inputs: Msg | list[Msg] | UserConfirmResultEvent |\n                ExternalExecutionResultEvent | None — the unified inputs\n                that trigger this reply (new message(s), a resumption\n                event from a previous outside interaction, or None).\n            next_handler: Callable that executes the next middleware or\n             original method\n\n        Yields:\n            AgentEvent | Msg: Events from the reply process\n        \"\"\"\n        raise RuntimeError(\n            f\"{type(self).__name__} does not implement on_reply\",\n        )\n        yield  # pylint: disable=unreachable\n\n    async def on_reasoning(\n        self,\n        agent: \"Agent\",\n        input_kwargs: dict,\n        next_handler: Callable[..., AsyncGenerator],\n    ) -> AsyncGenerator:\n        \"\"\"Hook for intercepting the reasoning process.\n\n        Args:\n            agent: The Agent instance executing this middleware\n            input_kwargs: Dictionary containing:\n                - tool_choice: ToolChoice (default None)\n            next_handler: Callable that executes the next middleware or\n            original method","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/agentscope-ai/agentscope/blob/e90f1c7592896cc95f6e5ee506194f533378247d/src/agentscope/middleware/_base.py#L78-L114","documentation":"Middleware.on_reply is an optional override point: the base class implementation raises RuntimeError if invoked. A middleware that does not implement on_reply was placed into a reply-related hook chain, and the chain dispatched to the base stub.","triggerScenarios":"Registering a middleware that only implements, say, on_acting, in a position where the framework calls on_reply on it (e.g. wrapping the agent's reply method with a middleware chain that requires on_reply), or calling super().on_reply(...) without overriding.","commonSituations":"Copying a middleware subclass template and deleting the method you thought was unused; middleware base classes where some hooks are optional per the docs but the specific chain requires them; calling next_handler incorrectly so control falls to the base stub.","solutions":["Implement async on_reply(self, agent, reply, next_handler) in your middleware, typically delegating via next_handler when passthrough behavior is desired","If the hook is genuinely not needed, remove the middleware from the chain that invokes on_reply","Ensure you don't call super().on_reply() in your override"],"exampleFix":"// before\nclass MyMiddleware(Middleware):\n    async def on_acting(self, agent, tool_call, next_handler):\n        ...\n# registered in a chain that calls on_reply -> RuntimeError 233\n\n// after\nclass MyMiddleware(Middleware):\n    async def on_reply(self, agent, reply, next_handler):\n        # passthrough\n        async for ev in next_handler(reply):\n            yield ev\n\n    async def on_acting(self, agent, tool_call, next_handler):\n        ...","handlingStrategy":"type-guard","validationCode":"from agentscope.middleware import Middleware\nassert type(mw).on_reply is not Middleware.on_reply, f\"{type(mw).__name__} lacks on_reply\"","typeGuard":"def implements_on_reply(mw) -> bool:\n    from agentscope.middleware import Middleware\n    return type(mw).on_reply is not Middleware.on_reply","tryCatchPattern":null,"preventionTips":["Always implement required-chain hooks, defaulting to passthrough via next_handler","Write a registration helper that checks which hooks each middleware implements","Never call super().on_reply() in overrides"],"tags":["middleware","hook-not-implemented","agent-pipeline"],"backgroundTag":"abstract-method-not-implemented","analyzedSha":"e90f1c7592896cc95f6e5ee506194f533378247d","analyzedAt":"2026-08-28T18:24:12.087Z","schemaVersion":2},"datasetVersion":"2026-08-28T21:17:43.275Z"}