You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix: copy extra_kwargs to prevent litellm from polluting metadata (#1610)
When using LiteLLM with agents framework, the agent run pollutes
metadata with non-string values (like hidden_params dict), causing
subsequent dataclasses.replace() calls to fail with Pydantic validation
errors.
This happens because:
1. Agent.reset_tool_choice defaults to True
2. After tool usage, maybe_reset_tool_choice() calls
dataclasses.replace()
3. LiteLLM adds hidden_params (dict) to ModelSettings.metadata
4. ModelSettings expects metadata: dict[str, str] but gets dict[str,
Any]
```python
#!/usr/bin/env python3
"""
Reproduce script for agents framework bug with LiteLLM metadata pollution.
"""
import asyncio
from agents import Agent, ModelSettings, Runner, function_tool, set_tracing_disabled
from agents.extensions.models.litellm_model import LitellmModel
set_tracing_disabled(disabled=True)
API_KEY = "xxx"
BASE_URL = "xxx"
# Create a simple tool that the agent can call
@function_tool
def get_time() -> str:
"""Get the current time."""
from datetime import datetime
return f"Current time: {datetime.now().strftime('%H:%M:%S')}"
async def main():
print("=== Reproducing LiteLLM metadata pollution bug ===")
agent = Agent[str](
name="test_agent",
model=LitellmModel(model="gpt-4o-mini", base_url=BASE_URL, api_key=API_KEY),
instructions="You are a helpful assistant. Use the get_time tool when asked about time.",
tools=[get_time], # Add the tool to trigger reset_tool_choice behavior
reset_tool_choice=True, # This is the default, triggers maybe_reset_tool_choice()
)
print(f"Agent reset_tool_choice: {agent.reset_tool_choice}")
print(f"Agent tools: {[tool.name for tool in agent.tools]}")
print("\n--- First run: Agent calls tool without metadata ---")
try:
result1 = await Runner.run(
starting_agent=agent,
input="What time is it?", # This should trigger the get_time tool
max_turns=3,
)
print(f"✓ First run successful")
print(f"Result: {result1.final_output}")
except Exception as e:
print(f"✗ Run failed: {e}")
return
metadata = {
"version": "1.0.0",
"user_id": "test_user",
"session_id": "test_session",
}
model_settings = ModelSettings(metadata=metadata)
agent = Agent[str](
name="test_agent",
model=LitellmModel(model="gpt-4o-mini", base_url=BASE_URL, api_key=API_KEY),
instructions="You are a helpful assistant. Use the get_time tool when asked about time.",
tools=[get_time], # Add the tool to trigger reset_tool_choice behavior
model_settings=model_settings,
reset_tool_choice=True, # This is the default, triggers maybe_reset_tool_choice()
)
print(f"Initial metadata: {list(model_settings.metadata.keys()) if model_settings.metadata else None}")
print(f"Agent reset_tool_choice: {agent.reset_tool_choice}")
print(f"Agent tools: {[tool.name for tool in agent.tools]}")
print("\n--- Second run: Agent calls tool with metadata ---")
try:
result1 = await Runner.run(
starting_agent=agent,
input="What time is it?", # This should trigger the get_time tool
max_turns=3,
)
print(f"✓ Second run successful")
print(f"Result: {result1.final_output}")
# Check metadata pollution
if agent.model_settings.metadata:
print(f"Metadata keys after second run: {list(agent.model_settings.metadata.keys())}")
# Show the problematic hidden_params
if "hidden_params" in agent.model_settings.metadata:
hidden_params = agent.model_settings.metadata["hidden_params"]
print(
f"✓ hidden_params added: {type(hidden_params)} with {len(hidden_params) if isinstance(hidden_params, dict) else 'N/A'} items"
)
print(f" This violates ModelSettings.metadata: dict[str, str] constraint")
except Exception as e:
import traceback
print(f"✗ Run failed:\n{e}")
print(f"Traceback:\n{traceback.format_exc()}")
return
if __name__ == "__main__":
asyncio.run(main())
```
output
```text
=== Reproducing LiteLLM metadata pollution bug ===
Agent reset_tool_choice: True
Agent tools: ['get_time']
--- First run: Agent calls tool without metadata ---
✓ First run successful
Result: The current time is 14:18:47.
Initial metadata: ['version', 'user_id', 'session_id']
Agent reset_tool_choice: True
Agent tools: ['get_time']
--- Second run: Agent calls tool with metadata ---
✗ Run failed:
1 validation error for ModelSettings
metadata.hidden_params
Input should be a valid string [type=string_type, input_value={'custom_llm_provider': '...'_response_ms': 797.449}, input_type=dict]
For further information visit https://errors.pydantic.dev/2.11/v/string_type
"""
```
0 commit comments