agentscope-ai/agentscope · error · RuntimeError

f"{type(self).__name__} does not implement on_model_call"

Error message

f"{type(self).__name__} does not implement on_model_call"

What it means

Middleware.on_model_call base stub raises RuntimeError when execute_chain dispatches a model call to a middleware that did not override on_model_call. Any middleware in the model-call chain must implement this hook to intercept or forward ChatResponse generation.

Source

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

            Awaitable["ChatResponse" | AsyncGenerator["ChatResponse", None]],
        ],
    ) -> "ChatResponse" | AsyncGenerator["ChatResponse", None]:
        """Hook for intercepting the model API call.

        Args:
            agent: The Agent instance executing this middleware
            input_kwargs: Dictionary containing:
                - messages: list[Msg]
                - tools: list[dict]
                - tool_choice: ToolChoice
                - current_model: The model instance used for this call
            next_handler: Callable that executes the next middleware or
            original method

        Returns:
            ChatResponse or AsyncGenerator[ChatResponse, None]
        """
        raise RuntimeError(
            f"{type(self).__name__} does not implement on_model_call",
        )

    async def on_compress_context(
        self,
        agent: "Agent",
        input_kwargs: dict,
        next_handler: Callable[..., Awaitable[None]],
    ) -> None:
        """Onion hook for `compress_context` function in `Agent` class

        Args:
            agent (`Agent`):
                The Agent instance executing this middleware
            input_kwargs (`dict`):
                Dictionary containing:
                - context_config: ContextConfig | None
                - instructions: HintBlock | None

View on GitHub (pinned to e90f1c7592)

Solutions

  1. Implement async on_model_call(self, agent, messages, next_handler) returning/forwarding next_handler(messages)
  2. Remove the middleware from model-call chains if it doesn't need to intercept them
  3. Match the signature to the installed agentscope version

Example fix

// before
class CacheMiddleware(Middleware):
    async def on_reply(self, agent, reply, next_handler):
        async for ev in next_handler(reply):
            yield ev
# model call chain -> RuntimeError 237

// after
class CacheMiddleware(Middleware):
    async def on_model_call(self, agent, messages, next_handler):
        key = hash(str(messages))
        if key in cache:
            return cache[key]
        resp = await next_handler(messages)
        cache[key] = resp
        return resp
Defensive patterns

Strategy: type-guard

Validate before calling

from agentscope.middleware import Middleware
assert type(mw).on_model_call is not Middleware.on_model_call

Type guard

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

Prevention

When it happens

Trigger: A middleware without on_model_call is placed in the model-call chain; or an override calls super().on_model_call(...). Raised on the agent's first LLM invocation with that chain.

Common situations: Writing a context-compression or logging middleware and forgetting the model-call passthrough; version upgrades changing the hook from optional to required in the chain; copy-paste middleware templates missing the method.

Related errors


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