[Bug]: max_iterations=0 is silently replaced by the default 20
Bug Description
max_iterations=0 is silently replaced by the default of 20, so a run that asks for no iterations executes tools and answers normally. BaseWorkflowAgent._init_context reads the value with or:
# llama-index-core/llama_index/core/agent/workflow/base_agent.py:305-309
if not await ctx.store.get("max_iterations", default=None):
max_iterations = (
ev.get("max_iterations", default=None) or DEFAULT_MAX_ITERATIONS
)0 is falsy, so it never reaches the store. AgentWorkflow._init_context has the same line. Every other guard downstream is then comparing against 20, and the caller is given no signal.
Related but different: #23051 is the outer if not await ctx.store.get(...), which ignores the keyword when a Context is reused. This is the inner or, and it fires on a fresh Context.
Version
llama-index-core 0.14.25, measured at main 169e450.
Steps to Reproduce
# no network and no model: the mock counts the calls it is asked for
agent = FunctionAgent(name="agent", description="test", tools=[counting_tool], llm=mock_llm)
await agent.run(user_msg="test", max_iterations=0)The mock answers a tool call first and a final answer second.
Relevant Logs/Tracebacks
$ PYTHONPATH=llama-index-core llama-index-core/.venv/bin/python probe_boundary_cases.py # 169e450
C max_iterations=0, tool round then answer llm_calls=2 tool_runs=1 ok response='answer is 42'Two model calls and one tool run, under a limit of zero. The same agent at max_iterations=1 stops after one call, which is the guard working.
Either reading is defensible and the choice is yours: 0 means the run stops before the first model call, or 0 is invalid and .run() raises. Both are a one-line change from or to an is None check plus a validation. Would you like it as a pull request, and which of the two?
I used an AI assistant to write the probe. Every number above came from a local run, and I checked each one before filing.
Source: run-llama/llama_index