run-llama/llama_index · error · ValueError

No tool calls found, cannot aggregate results.

Error message

No tool calls found, cannot aggregate results.

What it means

The aggregate_tool_results step expects the shared store key 'num_tool_calls' to be > 0 — it is set when the agent emits tool calls, and ctx.collect_events gathers that many ToolCallResult events. Reaching this step with num_tool_calls missing/0 means the internal event contract was broken (tool-call step skipped or events lost), so aggregation cannot proceed.

Source

Thrown at llama-index-core/llama_index/core/agent/workflow/multi_agent_workflow.py:688

        result_ev = ToolCallResult(
            tool_name=ev.tool_name,
            tool_kwargs=ev.tool_kwargs,
            tool_id=ev.tool_id,
            tool_output=result,
            return_direct=tool.metadata.return_direct if tool else False,
        )

        ctx.write_event_to_stream(result_ev)
        return result_ev

    @step
    async def aggregate_tool_results(
        self, ctx: Context, ev: ToolCallResult
    ) -> Union[AgentInput, StopEvent, None]:
        """Aggregate tool results and return the next agent input."""
        num_tool_calls = await ctx.store.get("num_tool_calls", default=0)
        if num_tool_calls == 0:
            raise ValueError("No tool calls found, cannot aggregate results.")

        tool_call_results: list[ToolCallResult] = ctx.collect_events(  # type: ignore
            ev, expected=[ToolCallResult] * num_tool_calls
        )
        if not tool_call_results:
            return None

        memory: BaseMemory = await ctx.store.get("memory")
        agent_name: str = await ctx.store.get("current_agent_name")
        agent: BaseWorkflowAgent = self.agents[agent_name]

        # track tool calls made during a .run() call
        cur_tool_calls: List[ToolCallResult] = await ctx.store.get(
            "current_tool_calls", default=[]
        )
        cur_tool_calls.extend(tool_call_results)
        await ctx.store.set("current_tool_calls", cur_tool_calls)

View on GitHub (pinned to afd0fef371)

Solutions

  1. If you subclass or emit custom events, ensure the agent's tool-call step runs first so num_tool_calls is set in ctx.store.
  2. Create a fresh workflow/Context per run; do not share Context between different workflow instances.
  3. If not customizing internals, upgrade llama-index-core to rule out a regression and report with a minimal reproducer.
Defensive patterns

Strategy: try-catch

Try / catch

try:
    result = await wf.run(user_msg=q)
except ValueError as e:
    if "No tool calls found" in str(e):
        # internal invariant break: report context instead of masking
        raise RuntimeError("workflow event contract broken") from e
    raise

Prevention

When it happens

Trigger: Not normally reachable from public API usage: it requires a ToolCallResult event to arrive while 'num_tool_calls' was never set — e.g. custom workflow steps injecting ToolCallResult events into an AgentWorkflow subclass, or a corrupted ctx.store between steps.

Common situations: Subclassing AgentWorkflow and emitting ToolCallResult manually; reusing a Context across workflows; version mismatches after upgrading llama-index-core mid-cache.

Related errors


AI-assisted analysis of run-llama/llama_index@afd0fef371 (2026-08-15). Data as JSON: /api/errors/8149f30ceef08a32. Report an issue: GitHub.