huggingface/smolagents · error · AgentError
Check {check_function.__name__} failed with error: {e}
Error message
Check {check_function.__name__} failed with error: {e} What it means
final_answer_checks are user-supplied validator functions run against the agent's final answer before it's accepted. If a check raises or its assert fails, _validate_final_answer wraps the failure as AgentError('Check <name> failed with error: ...') and the run aborts.
Source
Thrown at src/smolagents/agents.py:618
finally:
self._finalize_step(action_step)
self.memory.steps.append(action_step)
yield action_step
self.step_number += 1
if not returned_final_answer and self.step_number == max_steps + 1:
final_answer = self._handle_max_steps_reached(task)
yield action_step
final_answer_step = FinalAnswerStep(handle_agent_output_types(final_answer))
self._finalize_step(final_answer_step)
yield final_answer_step
def _validate_final_answer(self, final_answer: Any):
for check_function in self.final_answer_checks:
try:
assert check_function(final_answer, self.memory, agent=self)
except Exception as e:
raise AgentError(f"Check {check_function.__name__} failed with error: {e}", self.logger)
def _finalize_step(self, memory_step: ActionStep | PlanningStep | FinalAnswerStep):
if not isinstance(memory_step, FinalAnswerStep):
memory_step.timing.end_time = time.time()
self.step_callbacks.callback(memory_step, agent=self)
def _handle_max_steps_reached(self, task: str) -> Any:
action_step_start_time = time.time()
final_answer = self.provide_final_answer(task)
final_memory_step = ActionStep(
step_number=self.step_number,
error=AgentMaxStepsError("Reached max steps.", self.logger),
timing=Timing(start_time=action_step_start_time, end_time=time.time()),
token_usage=final_answer.token_usage,
)
final_memory_step.action_output = final_answer.content
self._finalize_step(final_memory_step)
self.memory.steps.append(final_memory_step)View on GitHub (pinned to 30bb116109)
Solutions
- Make the check defensive: validate the answer's type/shape first and raise a clear message
- If the answer format is unreliable, tighten the prompt or an answer schema so checks receive the expected type
- Re-run the task; if the check failure is transient (network inside the check), add retry inside the check itself
Example fix
# before
def check_json(answer, memory, agent=None):
assert "result" in answer # fails with TypeError/KeyError if answer is a plain string
# after
def check_json(answer, memory, agent=None):
if not isinstance(answer, dict):
raise ValueError("final answer must be a dict, got: " + repr(answer)[:200])
assert "result" in answer Defensive patterns
Strategy: try-catch
Validate before calling
def robust_check(answer, memory, agent=None):
if not isinstance(answer, (str, dict)):
return False # return False instead of raising so check failure is explicit
... Try / catch
from smolagents import AgentError
try:
agent.run(task)
except AgentError as e:
if str(e).startswith("Check "):
logger.warning("final answer failed validation: %s", e)
# optionally re-run with the failure appended to the task Prevention
- Make checks total functions: handle every expected answer type without raising
- Don't do network I/O inside final_answer_checks without try/except and timeout
When it happens
Trigger: Passing final_answer_checks=[my_check] to an agent where my_check raises (KeyError on the answer structure, assertion failure, TypeError on unexpected types) when the agent produces its final answer during run().
Common situations: Checks that expect a dict/JSON answer but the LLM returns plain text; checks calling external APIs (URL validation) that fail; brittle assertions on formatting that the model doesn't reliably satisfy.
Related errors
AI-assisted analysis of huggingface/smolagents@30bb116109 (2026-08-28).
Data as JSON: /api/errors/796e29ac0754405e.
Report an issue: GitHub.