Inject a dummy tool for LiteLLM proxy compatibility. LiteLLM and some Anthropic proxies require the tools parameter to be present when message history contains tool calls, even if no tools are being used.
(
tools: &mut HashMap<String, ToolDefinition>,
messages: &[Message],
provider_id: &str,
)
| 1354 | /// LiteLLM and some Anthropic proxies require the tools parameter to be present |
| 1355 | /// when message history contains tool calls, even if no tools are being used. |
| 1356 | pub fn inject_litellm_dummy_tool( |
| 1357 | tools: &mut HashMap<String, ToolDefinition>, |
| 1358 | messages: &[Message], |
| 1359 | provider_id: &str, |
| 1360 | ) { |
| 1361 | // Check if this is a LiteLLM proxy |
| 1362 | let is_litellm = provider_id.to_lowercase().contains("litellm"); |
| 1363 | |
| 1364 | if !is_litellm { |
| 1365 | return; |
| 1366 | } |
| 1367 | |
| 1368 | // Only inject if tools is empty and messages contain tool calls |
| 1369 | if !tools.is_empty() { |
| 1370 | return; |
| 1371 | } |
| 1372 | |
| 1373 | if !LlmProcessor::has_tool_calls(messages) { |
| 1374 | return; |
| 1375 | } |
| 1376 | |
| 1377 | tracing::info!("Injecting LiteLLM dummy tool for proxy compatibility"); |
| 1378 | |
| 1379 | tools.insert( |
| 1380 | "_noop".to_string(), |
| 1381 | ToolDefinition { |
| 1382 | name: "_noop".to_string(), |
| 1383 | description: Some( |
| 1384 | "Placeholder for LiteLLM/Anthropic proxy compatibility - required when message history contains tool calls but no active tools are needed" |
| 1385 | .to_string(), |
| 1386 | ), |
| 1387 | parameters: serde_json::json!({ |
| 1388 | "type": "object", |
| 1389 | "properties": {} |
| 1390 | }), |
| 1391 | }, |
| 1392 | ); |
| 1393 | } |
| 1394 | |
| 1395 | /// Resolve tools with permission filtering. |
| 1396 | /// Removes tools that are disabled by the agent's permission configuration. |