huggingface/smolagents · critical · NotImplementedError
This method should be implemented in child classes
Error message
This method should be implemented in child classes
What it means
MultiStepAgent is an abstract base class: its _step_stream method just raises NotImplementedError('This method should be implemented in child classes'). Each concrete agent (ToolCallingAgent, CodeAgent) overrides it to define its ReAct step behavior.
Source
Thrown at src/smolagents/agents.py:780
"""
Reads past llm_outputs, actions, and observations or errors from the memory into a series of messages
that can be used as input to the LLM. Adds a number of keywords (such as PLAN, error, etc) to help
the LLM.
"""
messages = self.memory.system_prompt.to_messages(summary_mode=summary_mode)
for memory_step in self.memory.steps:
messages.extend(memory_step.to_messages(summary_mode=summary_mode))
return messages
def _step_stream(
self, memory_step: ActionStep
) -> Generator[ChatMessageStreamDelta | ToolCall | ToolOutput | ActionOutput]:
"""
Perform one step in the ReAct framework: the agent thinks, acts, and observes the result.
Yields ChatMessageStreamDelta during the run if streaming is enabled.
At the end, yields either None if the step is not final, or the final answer.
"""
raise NotImplementedError("This method should be implemented in child classes")
def step(self, memory_step: ActionStep) -> Any:
"""
Perform one step in the ReAct framework: the agent thinks, acts, and observes the result.
Returns either None if the step is not final, or the final answer.
"""
return list(self._step_stream(memory_step))[-1]
def extract_action(self, model_output: str, split_token: str) -> tuple[str, str]:
"""
Parse action from the LLM output
Args:
model_output (`str`): Output of the LLM
split_token (`str`): Separator for the action. Should match the example in the system prompt.
"""
try:
split = model_output.split(split_token)View on GitHub (pinned to 30bb116109)
Solutions
- Don't instantiate MultiStepAgent directly; use CodeAgent or ToolCallingAgent
- In your subclass, implement _step_stream as a generator yielding ChatMessageStreamDelta/ToolCall/ToolOutput and finally an ActionOutput
- Model your subclass on ToolCallingAgent's implementation or delegate by composition instead of inheritance
Example fix
# before
class MyAgent(MultiStepAgent):
def _do_step(self): ... # wrong name; _step_stream left abstract
# after
class MyAgent(MultiStepAgent):
def _step_stream(self):
# think / act / observe logic
yield ActionOutput(output=result, is_final_answer=done) Defensive patterns
Strategy: validation
Validate before calling
import inspect
def assert_concrete(agent_cls):
if inspect.isabstract(agent_cls) or agent_cls._step_stream is MultiStepAgent._step_stream:
raise TypeError(f"{agent_cls.__name__} must implement _step_stream") Type guard
def implements_step_stream(cls) -> bool:
return '_step_stream' in cls.__dict__ or any('_step_stream' in c.__dict__ for c in cls.__mro__[1:-1]) and cls.__dict__.get('_step_stream') is not None Prevention
- Prefer instantiating CodeAgent/ToolCallingAgent over subclassing MultiStepAgent
- When subclassing, copy method signatures from ToolCallingAgent exactly
When it happens
Trigger: Instantiating MultiStepAgent directly and calling run()/step(), or subclassing MultiStepAgent without overriding _step_stream; also calling super()._step_stream(...) from a subclass override.
Common situations: Creating a custom agent type by extending MultiStepAgent and forgetting to implement the step logic; refactorings that rename the override or accidentally call the parent implementation.
Related errors
- Write this method in your subclass of `Tool`.
- Error during jinja template rendering: {type(e).__name__}: {
- Cannot specify both 'messages' and 'steps' parameters. Use '
- The 'system_prompt' property is read-only. Use 'self.prompt_
- Agent name '{name}' must be a valid Python identifier and no
AI-assisted analysis of huggingface/smolagents@30bb116109 (2026-08-28).
Data as JSON: /api/errors/9bf52f63db6d5ae1.
Report an issue: GitHub.