agentscope-ai/agentscope · error · RuntimeError

{type(self).__name__} does not implement on_reply

Error message

{type(self).__name__} does not implement on_reply

What it means

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.

Source

Thrown at src/agentscope/middleware/_base.py:96

        ``Msg`` is only produced once the event escapes the whole chain.
        When swallowing an exceed-max-iters end, unblock the next round
        first (e.g. adjust ``cur_iter`` or ``max_iters``). Interrupted
        ends cannot be swallowed to continue the reply.

        Args:
            agent: The Agent instance executing this middleware
            input_kwargs: Dictionary containing:
                - inputs: Msg | list[Msg] | UserConfirmResultEvent |
                ExternalExecutionResultEvent | None — the unified inputs
                that trigger this reply (new message(s), a resumption
                event from a previous outside interaction, or None).
            next_handler: Callable that executes the next middleware or
             original method

        Yields:
            AgentEvent | Msg: Events from the reply process
        """
        raise RuntimeError(
            f"{type(self).__name__} does not implement on_reply",
        )
        yield  # pylint: disable=unreachable

    async def on_reasoning(
        self,
        agent: "Agent",
        input_kwargs: dict,
        next_handler: Callable[..., AsyncGenerator],
    ) -> AsyncGenerator:
        """Hook for intercepting the reasoning process.

        Args:
            agent: The Agent instance executing this middleware
            input_kwargs: Dictionary containing:
                - tool_choice: ToolChoice (default None)
            next_handler: Callable that executes the next middleware or
            original method

View on GitHub (pinned to e90f1c7592)

Solutions

  1. Implement async on_reply(self, agent, reply, next_handler) in your middleware, typically delegating via next_handler when passthrough behavior is desired
  2. If the hook is genuinely not needed, remove the middleware from the chain that invokes on_reply
  3. Ensure you don't call super().on_reply() in your override

Example fix

// before
class MyMiddleware(Middleware):
    async def on_acting(self, agent, tool_call, next_handler):
        ...
# registered in a chain that calls on_reply -> RuntimeError 233

// after
class MyMiddleware(Middleware):
    async def on_reply(self, agent, reply, next_handler):
        # passthrough
        async for ev in next_handler(reply):
            yield ev

    async def on_acting(self, agent, tool_call, next_handler):
        ...
Defensive patterns

Strategy: type-guard

Validate before calling

from agentscope.middleware import Middleware
assert type(mw).on_reply is not Middleware.on_reply, f"{type(mw).__name__} lacks on_reply"

Type guard

def implements_on_reply(mw) -> bool:
    from agentscope.middleware import Middleware
    return type(mw).on_reply is not Middleware.on_reply

Prevention

When it happens

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

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

Related errors


AI-assisted analysis of agentscope-ai/agentscope@e90f1c7592 (2026-08-28). Data as JSON: /api/errors/994b8f0dfacf144b. Report an issue: GitHub.