{"record":{"id":"6f9e22af52418213","repo":"alibaba/spring-ai-alibaba","slug":"routingagent-retry-attempt-previous-inva","errorCode":null,"errorMessage":"RoutingAgent {} retry attempt {}/{}. Previous invalid decision: {}","messagePattern":"RoutingAgent (.+?) retry attempt (.+?)/(.+?)\\. Previous invalid decision: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"spring-ai-alibaba-agent-framework/src/main/java/com/alibaba/cloud/ai/graph/agent/flow/node/RoutingEdgeAction.java","lineNumber":176,"sourceCode":"\t\tString lastInvalidDecision = null;\n\n\t\tfor (int attempt = 0; attempt <= maxRetries; attempt++) {\n\t\t\ttry {\n\t\t\t\tRoutingDecision decision;\n\n\t\t\t\tif (attempt == 0) {\n\t\t\t\t\t// First attempt: use original messages\n\t\t\t\t\tdecision = this.chatClient.prompt().messages(messages).call().entity(this.outputConverter);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t// Retry attempts: add error feedback to help the model correct its decision\n\t\t\t\t\tString errorFeedback = String.format(\n\t\t\t\t\t\t\t\"Previous attempt returned an invalid agent name '%s'. \" +\n\t\t\t\t\t\t\t\t\t\"Please choose from the available agents: %s.\",\n\t\t\t\t\t\t\tlastInvalidDecision,\n\t\t\t\t\t\t\tString.join(\", \", subAgents.stream().map(Agent::name).toList()));\n\n\t\t\t\t\tlogger.warn(\"RoutingAgent {} retry attempt {}/{}. Previous invalid decision: {}\",\n\t\t\t\t\t\t\trootAgent.name(), attempt, maxRetries, lastInvalidDecision);\n\n\t\t\t\t\t// Create a new message list with error feedback\n\t\t\t\t\t// Try to append to existing SystemMessage, otherwise use UserMessage\n\t\t\t\t\tjava.util.ArrayList<Message> messagesWithFeedback = new java.util.ArrayList<>();\n\t\t\t\t\tboolean systemMessageFound = false;\n\n\t\t\t\t\tfor (Message msg : messages) {\n\t\t\t\t\t\tif (msg instanceof SystemMessage && !systemMessageFound) {\n\t\t\t\t\t\t\t// Append error feedback to the first SystemMessage found\n\t\t\t\t\t\t\tString enhancedContent = msg.getText() + \"\\n\\n\" + errorFeedback;\n\t\t\t\t\t\t\tmessagesWithFeedback.add(new SystemMessage(enhancedContent));\n\t\t\t\t\t\t\tsystemMessageFound = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tmessagesWithFeedback.add(msg);\n\t\t\t\t\t\t}\n\t\t\t\t\t}","sourceCodeStart":158,"sourceCodeEnd":194,"githubUrl":"https://github.com/alibaba/spring-ai-alibaba/blob/f82da0b50f35744c13968191be2b1cd2452ef550/spring-ai-alibaba-agent-framework/src/main/java/com/alibaba/cloud/ai/graph/agent/flow/node/RoutingEdgeAction.java#L158-L194","documentation":"RoutingEdgeAction.getDecisionWithRetry asks the LLM to pick a sub-agent name; when a decision is invalid, it retries up to maxRetries, injecting error feedback into the prompt. This warning logs each retry attempt, showing the routing agent name, attempt count, and the previous invalid decision.","triggerScenarios":"decisionValue (via getDecisionWithRetry) receives from the LLM a string that is not one of subAgents' names; attempt < maxRetries, so the code formats error feedback listing valid agents and retries.","commonSituations":"Model outputs prose or a paraphrased agent name ('research assistant' vs 'researcher'); sub-agent names contain characters the model mangles; prompt lacks few-shot examples of valid names; LLM temperature too high.","solutions":["Rename sub-agents to simple, unambiguous lowercase identifiers","Strengthen the routing prompt to enumerate exact valid agent names and demand one verbatim","Lower temperature for routing calls","Add fuzzy matching of the decision against sub-agent names before declaring it invalid"],"exampleFix":"// before\nagent named 'Research-Team-Handler v2' // model returns 'research team'\n// after\nagent named 'research_team' // prompt lists: choose one of: research_team, writer_team","handlingStrategy":"retry","validationCode":"List<String> valid = subAgents.stream().map(Agent::name).toList();\nif (!valid.contains(decision)) { log.warn(\"Routing decision '{}' not in {}\", decision, valid); }","typeGuard":"static boolean isValidDecision(String d, List<Agent> agents) { return d != null && agents.stream().anyMatch(a -> a.name().equals(d)); }","tryCatchPattern":"try { String d = routingAction.decisionValue(state); } catch (Exception e) { /* all retries exhausted: route to default agent or END */ }","preventionTips":["Use simple snake_case sub-agent names the LLM can echo verbatim","Include the exact valid agent names in the routing prompt and few-shot examples","Lower temperature on routing model calls"],"tags":["routing","llm-output","retry"],"backgroundTag":"invalid-enum-value","analyzedSha":"f82da0b50f35744c13968191be2b1cd2452ef550","analyzedAt":"2026-09-09T15:32:42.421Z","contentChangedAt":"2026-09-09T15:32:42.421Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}