alibaba/spring-ai-alibaba · warning

Tool selection failed, using all tools: {}

Error message

Tool selection failed, using all tools: {}

What it means

ToolSelectionInterceptor asks an LLM to pick a subset of available tools; selectTools wraps that selection in a broad catch, and on any failure it logs this warning and falls back to passing ALL tools to the model. The workflow continues, but the model sees the full tool set, which can degrade selection quality and increase token usage.

Source

Thrown at spring-ai-alibaba-agent-framework/src/main/java/com/alibaba/cloud/ai/graph/agent/interceptor/toolselection/ToolSelectionInterceptor.java:176

			String responseText = response.getResult().getOutput().getText();

			// Parse JSON response
			Set<String> selected = parseToolSelection(responseText);

			// Add always-include tools
			selected.addAll(alwaysInclude);

			// Limit to maxTools if specified
			if (maxTools != null && selected.size() > maxTools) {
				List<String> selectedList = new ArrayList<>(selected);
				selected = new HashSet<>(selectedList.subList(0, maxTools));
			}

			return selected;

		}
		catch (Exception e) {
			log.warn("Tool selection failed, using all tools: {}", e.getMessage());
			return new HashSet<>(toolNames);
		}
	}

	private Set<String> parseToolSelection(String responseText) {
		try {
			// Try to parse as JSON
			ToolSelectionResponse response = objectMapper.readValue(responseText, ToolSelectionResponse.class);
			return new HashSet<>(response.tools);
		}
		catch (Exception e) {
			// Fallback: extract tool names from text
			log.debug("Failed to parse JSON, using fallback extraction");
			return new HashSet<>();
		}
	}

	@Override

View on GitHub (pinned to f82da0b50f)

Solutions

  1. Inspect the selection model's raw response (logged context) and strengthen the selection prompt with explicit output-format instructions and an example.
  2. Make parseToolSelection more tolerant: strip markdown fences, trim whitespace, and ignore unknown tool names instead of failing.
  3. Use a more capable model for tool selection.
  4. If the fallback is acceptable, silence the noise by fixing the common parse failure case; if not, tighten validation of the selection response.

Example fix

// before (brittle parser)
Set<String> names = new HashSet<>(List.of(responseText.split(",")));
// after
String json = responseText.replaceAll("^```(json)?|```$", "").trim();
Set<String> names = parseNames(json, toolNames); // ignore unknown names
Defensive patterns

Strategy: fallback

Validate before calling

static boolean isParsableSelection(String responseText) {
    if (responseText == null) return false;
    String s = responseText.replaceAll("```(json)?", "").trim();
    return s.startsWith("[") || s.startsWith("{") || !s.isEmpty();
}

Try / catch

try {
    selected = selectionModel.call(selectionPrompt);
} catch (Exception e) {
    log.warn("Tool selection failed, using all tools: {}", e.getMessage());
    return new HashSet<>(toolNames);
}

Prevention

When it happens

Trigger: selectTools throws inside the selection flow — typically when parseToolSelection cannot parse the model's responseText into a valid tool-name set (malformed JSON, hallucinated tool names, empty response), or the selection model call itself errors.

Common situations: 1) The selection LLM returns prose or fenced markdown instead of the expected JSON/name list. 2) The selection model names tools that don't exist in toolNames. 3) A small/weak selection model (e.g. a cheap endpoint) that frequently produces unparseable output. 4) Selection prompt template misconfigured so instructions don't match the parser.

Related errors


AI-assisted analysis of alibaba/spring-ai-alibaba@f82da0b50f (2026-09-09). Data as JSON: /api/errors/9d8b96d759107eea. Report an issue: GitHub.