-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Description
Description
When calling session.generate_reply(tool_choice="none") during agent initialization (e.g., in on_enter), the tool_choice setting appears to persist for all subsequent conversation turns, preventing tools from ever being called even when the user responds.
Expected Behavior
The tool_choice parameter passed to generate_reply() should only affect that specific generation, not subsequent turns. Tools should be callable on subsequent turns when the user responds.
Actual Behavior
After calling generate_reply(tool_choice="none") once, extraction/function tools are never called on subsequent user turns, even though tool_choice is not passed on those turns.
Reproduction Steps
- Create an agent with function tools (e.g., extraction tools)
- In the agent's
on_enteror initial greeting, call:self.session.generate_reply(tool_choice="none", allow_interruptions=True)
- User responds with information that should trigger tool extraction
- Observe that tools are never called on subsequent turns
Code Analysis
Looking at agent_activity.py, the logic at lines ~900-903 in _generate_reply:
model_settings=ModelSettings(
tool_choice=tool_choice
if utils.is_given(tool_choice) or self._tool_choice is None
else self._tool_choice
),This uses the persisted self._tool_choice when:
tool_choiceis NOT explicitly given, ANDself._tool_choicehas been previously set
The self._tool_choice is set via update_options() at line 352, but it's unclear how generate_reply() triggers this persistence path.
Environment
- livekit-agents version: 1.3.10
- Python version: 3.13
- LLM: OpenAI (non-realtime)
Workaround
Don't pass tool_choice="none" to generate_reply() even when you don't want tools called on the greeting. The worst case (LLM calls extraction tool on greeting before user responds) results in empty extraction with no side effects.
# Instead of:
if self.tools:
self.session.generate_reply(tool_choice="none", allow_interruptions=True)
else:
self.session.generate_reply(allow_interruptions=True)
# Use:
self.session.generate_reply(allow_interruptions=True)Related Issues
- Enhanced control over instructions and chat context in LLM interaction #3820 - Reports similar issues with
tool_choice='none'being ignored - llm.FallbackAdapter doesn't call tools #1207 - FallbackAdapter doesn't call tools