huggingface/smolagents · error · ValueError
JSON is invalid: you probably tried to provide multiple tool
Error message
JSON is invalid: you probably tried to provide multiple tool calls in one action. PROVIDE ONLY ONE TOOL CALL.
What it means
A special case of JSON parsing failure in parse_json_blob: json.loads failed at a position where the blob contains '},\n', i.e., two adjacent JSON objects. smolagents allows only ONE tool call per action, so this pattern is detected and reported with a targeted message.
Source
Thrown at src/smolagents/utils.py:179
else:
# For any other type, convert to string
return str(obj)
def parse_json_blob(json_blob: str) -> tuple[dict[str, str], str]:
"Extracts the JSON blob from the input and returns the JSON data and the rest of the input."
try:
first_accolade_index = json_blob.find("{")
last_accolade_index = [a.start() for a in list(re.finditer("}", json_blob))][-1]
json_str = json_blob[first_accolade_index : last_accolade_index + 1]
json_data = json.loads(json_str, strict=False)
return json_data, json_blob[:first_accolade_index]
except IndexError:
raise ValueError("The model output does not contain any JSON blob.")
except json.JSONDecodeError as e:
place = e.pos
if json_blob[place - 1 : place + 2] == "},\n":
raise ValueError(
"JSON is invalid: you probably tried to provide multiple tool calls in one action. PROVIDE ONLY ONE TOOL CALL."
)
raise ValueError(
f"The JSON blob you used is invalid due to the following error: {e}.\n"
f"JSON blob was: {json_blob}, decoding failed on that specific part of the blob:\n"
f"'{json_blob[place - 4 : place + 5]}'."
)
def extract_code_from_text(text: str, code_block_tags: tuple[str, str]) -> str | None:
"""Extract code from the LLM's output."""
pattern = rf"{code_block_tags[0]}(.*?){code_block_tags[1]}"
matches = re.findall(pattern, text, re.DOTALL)
if matches:
return "\n\n".join(match.strip() for match in matches)
return None
View on GitHub (pinned to 30bb116109)
Solutions
- Adjust the prompt/system template to demand exactly one tool call per step (the error text is designed to be fed back to the model)
- Retry the step — the agent loop resubmits with this error as feedback
- Use a model/template pairing known to comply with smolagents' one-call-per-step protocol
Example fix
# before (model output)
{"name": "search", "arguments": {...}},
{"name": "visit", "arguments": {...}}
# after (one call per step)
{"name": "search", "arguments": {...}} Defensive patterns
Strategy: retry
Validate before calling
def single_action_only(text: str) -> bool:
import re
return not re.search(r'\}\s*,\s*\{', text) Type guard
def is_single_json_object(text: str) -> bool:
import json, re
m = re.search(r'\{.*\}', text, re.DOTALL)
if not m:
return False
try:
obj = json.loads(m.group(0))
return isinstance(obj, dict)
except json.JSONDecodeError:
return False Try / catch
try:
parse_json_blob(text)
except ValueError as e:
if 'PROVIDE ONLY ONE TOOL CALL' in str(e):
# return error to agent so model retries with one call
raise Prevention
- Prompt: 'provide exactly one tool call per step'
- Avoid few-shot examples showing multiple actions per turn
- Prefer native function-calling models for multi-tool tasks
When it happens
Trigger: Model output contains multiple JSON action objects separated by a comma and newline, e.g. '{"action": ...},\n{"action": ...}'; typically with models eager to parallelize tool calls.
Common situations: Strong models trying to batch several tool calls per step; prompts encouraging 'do everything at once'; few-shot examples accidentally showing multiple calls per action.
Related errors
- Error while parsing tool call from model output: {e}
- The model output does not contain any JSON blob.
- The JSON blob you used is invalid due to the following error
- If you want to return an answer, please do not perform any o
- You returned multiple final answers. Please return only one
AI-assisted analysis of huggingface/smolagents@30bb116109 (2026-08-28).
Data as JSON: /api/errors/b38e4bc71e642961.
Report an issue: GitHub.