agentscope-ai/agentscope · error · NotImplementedError
{self.__class__.__name__} does not implement call
Error message
{self.__class__.__name__} does not implement call What it means
ToolBase.call() is abstract; subclasses that are not external tools must override it. Calling call() on a subclass that didn't override it raises NotImplementedError, naming the class.
Source
Thrown at src/agentscope/tool/_base.py:166
) -> ToolChunk | AsyncGenerator[ToolChunk, None]:
"""Execute the tool logic.
This is the new override point for tool implementations.
Subclasses should override this method instead of
:meth:`__call__`. The base implementation raises
:exc:`NotImplementedError` for non-external tools and
:exc:`RuntimeError` for external tools.
Args:
**kwargs: Tool input arguments.
Returns:
`ToolChunk | AsyncGenerator[ToolChunk, None]`:
A single :class:`~agentscope.tool.ToolChunk` or an
async generator that yields them.
"""
if not self.is_external_tool:
raise NotImplementedError(
f"{self.__class__.__name__} does not implement call",
)
raise RuntimeError(
f"{self.__class__.__name__} is an external tool and should not "
f"be called directly",
)
async def __call__(
self,
*args: Any,
**kwargs: Any,
) -> ToolChunk | AsyncGenerator[ToolChunk, None]:
"""Invoke the tool, layering any registered middlewares around
:meth:`call`.
Tools are always invoked with keyword arguments only. ``*args`` is
accepted in the signature solely to stay Liskov-compatible withView on GitHub (pinned to e90f1c7592)
Solutions
- Implement `async def call(...)` in your subclass returning ToolChunk or an async generator of them
- Check the exact expected signature in sibling builtin tools
- If it's an external (MCP) tool, mark it accordingly instead of implementing call
Example fix
# before
class MyTool(ToolBase):
async def run(self, x): ...
# after
class MyTool(ToolBase):
async def call(self, x) -> ToolChunk: ... Defensive patterns
Strategy: validation
Validate before calling
import inspect
assert ToolBase.call is not type(tool).call, f'{type(tool).__name__} must implement call()' Type guard
def tool_implements_call(tool) -> bool:
return type(tool).call is not ToolBase.call Try / catch
try:
await tool(**kwargs)
except NotImplementedError as e:
raise TypeError(f'misconfigured tool: {e}') from e Prevention
- Always implement async call() in custom Tool subclasses
- Add a smoke-test that calls each registered tool once
When it happens
Trigger: Defining a Tool subclass without implementing async call(), then invoking it (directly or via __call__/execute_chain in a toolkit run).
Common situations: Forgetting to implement call when creating a custom tool; renaming the method (e.g. run) so the abstract call is never overridden; instantiation succeeds and the failure only appears at invocation time.
Related errors
- This storage backend has no channel support.
- {type(self).__name__} does not implement list_chunks().
- {type(self).__name__} must be called with keyword arguments
- Ripgrep search timed out after {timeout} seconds. Try search
- ripgrep error (code {result.exit_code}): {error_msg}
AI-assisted analysis of agentscope-ai/agentscope@e90f1c7592 (2026-08-28).
Data as JSON: /api/errors/368268fe3d9a5708.
Report an issue: GitHub.