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 | NoneView on GitHub (pinned to e90f1c7592)
Solutions
- Implement async on_model_call(self, agent, messages, next_handler) returning/forwarding next_handler(messages)
- Remove the middleware from model-call chains if it doesn't need to intercept them
- 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
- Give every middleware a default on_model_call that forwards next_handler
- Test middlewares with one end-to-end agent call before shipping
- Update middleware subclasses when upgrading agentscope versions
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
- {type(self).__name__} does not implement on_reply
- {type(self).__name__} does not implement on_reasoning
- {type(self).__name__} does not implement on_acting
- f"{type(self).__name__} does not implement on_check_permissi
- f"{type(self).__name__} does not implement on_compress_conte
AI-assisted analysis of agentscope-ai/agentscope@e90f1c7592 (2026-08-28).
Data as JSON: /api/errors/66ba181a8c192693.
Report an issue: GitHub.