huggingface/smolagents · error · ValueError
step_callbacks must be a list or a dict
Error message
step_callbacks must be a list or a dict
What it means
The step_callbacks parameter of an agent must be either a list (applied to all step types) or a dict mapping step classes to callback(s). Anything else (a string, a bare function, a tuple, None passed explicitly with wrong type) raises ValueError('step_callbacks must be a list or a dict').
Source
Thrown at src/smolagents/agents.py:432
)
def _setup_step_callbacks(self, step_callbacks):
# Initialize step callbacks registry
self.step_callbacks = CallbackRegistry()
if step_callbacks:
# Register callbacks list only for ActionStep for backward compatibility
if isinstance(step_callbacks, list):
for callback in step_callbacks:
self.step_callbacks.register(ActionStep, callback)
# Register callbacks dict for specific step classes
elif isinstance(step_callbacks, dict):
for step_cls, callbacks in step_callbacks.items():
if not isinstance(callbacks, list):
callbacks = [callbacks]
for callback in callbacks:
self.step_callbacks.register(step_cls, callback)
else:
raise ValueError("step_callbacks must be a list or a dict")
# Register monitor update_metrics only for ActionStep for backward compatibility
self.step_callbacks.register(ActionStep, self.monitor.update_metrics)
def run(
self,
task: str,
stream: bool = False,
reset: bool = True,
images: list["PIL.Image.Image"] | None = None,
additional_args: dict | None = None,
max_steps: int | None = None,
return_full_result: bool | None = None,
) -> Any | RunResult:
"""
Run the agent for the given task.
Args:
task (`str`): Task to perform.View on GitHub (pinned to 30bb116109)
Solutions
- Wrap a single callback in a list: step_callbacks=[my_callback]
- For per-step-type callbacks use a dict: {ActionStep: [cb1], PlanningStep: cb2}
- If building callbacks dynamically, verify isinstance(cb, (list, dict)) before construction
Example fix
# before agent = CodeAgent(tools=[], llm_engine=llm, step_callbacks=my_callback) # after agent = CodeAgent(tools=[], llm_engine=llm, step_callbacks=[my_callback])
Defensive patterns
Strategy: type-guard
Validate before calling
cb = my_callback if isinstance(my_callback, (list, dict)) else [my_callback] agent = CodeAgent(tools=[], llm_engine=llm, step_callbacks=cb)
Type guard
def normalize_step_callbacks(cb):
if isinstance(cb, dict):
return {k: (v if isinstance(v, list) else [v]) for k, v in cb.items()}
if callable(cb):
return [cb]
if isinstance(cb, list):
return cb
raise TypeError("step_callbacks must be a list or a dict") Prevention
- Always wrap single callbacks in [ ]
- Don't pass tuples; use a list literal
When it happens
Trigger: Passing step_callbacks=some_function or step_callbacks=(cb1, cb2) or step_callbacks="callback" instead of a list/dict; a single callable is not accepted and must be wrapped in a list.
Common situations: Intuitively passing one callback function directly; passing a tuple because other libraries accept iterables; migrating code that previously used the older single-callback signature.
Related errors
- Cannot specify both 'messages' and 'steps' parameters. Use '
- Agent name '{name}' must be a valid Python identifier and no
- Each tool or managed_agent should have a unique name! You pa
- Input '{input_name}': type must be a string or list of strin
- Argument {key} has type '{actual_type}' but should be '{tool
AI-assisted analysis of huggingface/smolagents@30bb116109 (2026-08-28).
Data as JSON: /api/errors/f0035839cdbf2632.
Report an issue: GitHub.