Describe the bug
When the LLM calls a function that isn't registered in the tool context, the voice path in generation.py silently skips the function call with continue, without adding an error result to tool_output.output. This causes the agent to stop responding entirely, leaving the user waiting indefinitely with no feedback.
This contrasts with llm/utils.py which correctly returns a FunctionCallResult with is_error=True that feeds back to the LLM.
To Reproduce
- Create an agent with tools registered
- Have instructions that reference a tool name that isn't actually registered (e.g., typo, or conditional tool that wasn't included)
- When the LLM calls the unregistered tool, the agent silently stops without saying anything
Expected behavior
The agent should return an error result to the LLM (similar to llm/utils.py), allowing the LLM to recover gracefully - either by retrying with a different approach or informing the user.
Code Analysis
Current behavior in generation.py (lines ~488-495):
if (function_tool := tool_ctx.function_tools.get(fnc_call.name)) is None:
logger.warning(
f"unknown AI function `{fnc_call.name}`",
extra={"function": fnc_call.name, "speech_id": speech_handle.id},
)
continue # ← Silently skips, nothing added to tool_output.output
Better behavior in llm/utils.py (lines ~20-30):
if function_tool is None:
logger.warning(f"unknown AI function `{tool_call.name}`")
return FunctionCallResult(
fnc_call=fnc_call,
fnc_call_out=FunctionCallOutput(
name=tool_call.name,
call_id=tool_call.call_id,
output=f"Unknown function: {tool_call.name}",
is_error=True, # ← This feeds back to the LLM!
),
...
)
The downstream effect in agent_activity.py (line ~2182):
if len(tool_output.output) > 0:
# Only triggers LLM retry if there are tool outputs
# When unknown function is skipped, this block is never entered
Suggested fix
In generation.py, instead of continue, add an error output:
if (function_tool := tool_ctx.function_tools.get(fnc_call.name)) is None:
logger.warning(...)
_tool_completed(make_tool_output(
fnc_call=fnc_call,
output=f"Unknown function: {fnc_call.name}",
exception=ValueError(f"Unknown function: {fnc_call.name}")
))
continue
Environment
- livekit-agents version: 1.4.2
- Python version: 3.13
Impact
This is a significant UX issue - the user is left hanging with no response and no indication of what went wrong. It can happen when:
- Tool registration is conditional and a code path misses adding a tool
- Instructions reference tools that were renamed/removed
- LLM hallucinates a tool name
Describe the bug
When the LLM calls a function that isn't registered in the tool context, the voice path in
generation.pysilently skips the function call withcontinue, without adding an error result totool_output.output. This causes the agent to stop responding entirely, leaving the user waiting indefinitely with no feedback.This contrasts with
llm/utils.pywhich correctly returns aFunctionCallResultwithis_error=Truethat feeds back to the LLM.To Reproduce
Expected behavior
The agent should return an error result to the LLM (similar to
llm/utils.py), allowing the LLM to recover gracefully - either by retrying with a different approach or informing the user.Code Analysis
Current behavior in
generation.py(lines ~488-495):Better behavior in
llm/utils.py(lines ~20-30):The downstream effect in
agent_activity.py(line ~2182):Suggested fix
In
generation.py, instead ofcontinue, add an error output:Environment
Impact
This is a significant UX issue - the user is left hanging with no response and no indication of what went wrong. It can happen when: