{"record":{"id":"ad226e720c483d12","repo":"alibaba/spring-ai-alibaba","slug":"routing-sub-agents-must-be-baseagent-for-merge-sup","errorCode":null,"errorMessage":"Routing sub-agents must be BaseAgent for merge support","messagePattern":"Routing sub-agents must be BaseAgent for merge support","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"spring-ai-alibaba-agent-framework/src/main/java/com/alibaba/cloud/ai/graph/agent/flow/strategy/RoutingGraphBuildingStrategy.java","lineNumber":84,"sourceCode":"\t\tString firstBeforeModelNode = routingNodeName;\n\t\tif (!beforeModelHooks.isEmpty()) {\n\t\t\tfirstBeforeModelNode = connectBeforeModelHookEdges(graph, routingNodeName, beforeModelHooks);\n\t\t}\n\t\tgraph.addEdge(rootAgent.name(), firstBeforeModelNode);\n\n\t\t// Step 3: Connect afterModel hooks after routing node (if any)\n\t\t// The hook nodes are already added by parent class, we just need to connect edges\n\t\tString routingExitNode = routingNodeName;\n\t\tif (!afterModelHooks.isEmpty()) {\n\t\t\troutingExitNode = connectAfterModelHookEdges(graph, routingNodeName, afterModelHooks);\n\t\t}\n\n\t\t// Step 4: Add merge node for result synthesis\n\t\tString mergeNodeName = rootAgent.name() + \"_merge\";\n\t\tList<BaseAgent> baseAgentList = new ArrayList<>(config.getSubAgents().size());\n\t\tfor (Agent subAgent : config.getSubAgents()) {\n\t\t\tif (!(subAgent instanceof BaseAgent)) {\n\t\t\t\tthrow new IllegalArgumentException(\"Routing sub-agents must be BaseAgent for merge support\");\n\t\t\t}\n\t\t\tbaseAgentList.add((BaseAgent) subAgent);\n\t\t}\n\t\tgraph.addNode(mergeNodeName, node_async(new RoutingMergeNode(config.getChatModel(), baseAgentList)));\n\n\t\t// Step 5: Process sub-agents for routing\n\t\tMap<String, String> edgeRoutingMap = new HashMap<>();\n\t\tfor (Agent subAgent : config.getSubAgents()) {\n\t\t\t// Add the current sub-agent as a node\n\t\t\tFlowGraphBuildingStrategy.addSubAgentNode(subAgent, graph);\n\t\t\tedgeRoutingMap.put(subAgent.name(), subAgent.name());\n\t\t\t// Connect sub-agents to merge node (dedicated node for result merging)\n\t\t\tgraph.addEdge(subAgent.name(), mergeNodeName);\n\t\t}\n\t\tgraph.addEdge(mergeNodeName, this.exitNode);\n\n\t\t// Step 6: Add parallel conditional edges for routing\n\t\t// This allows routing to one or multiple sub-agents in parallel","sourceCodeStart":66,"sourceCodeEnd":102,"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/strategy/RoutingGraphBuildingStrategy.java#L66-L102","documentation":"RoutingGraphBuildingStrategy adds a merge node that needs BaseAgent instances (RoutingMergeNode operates on List<BaseAgent>). Throwing IllegalArgumentException when any sub-agent in the routing config is not a BaseAgent.","triggerScenarios":"Calling buildCoreGraph for a routing flow where one or more entries of config.getSubAgents() are Agent implementations that do not extend BaseAgent (e.g. wrapping composite or custom agents).","commonSituations":"Mixing flow/composite agents with leaf agents in a routing branch list; using a custom Agent implementation as a routing branch; API changes where subAgents accepts Agent but the strategy narrows to BaseAgent.","solutions":["Ensure every routing sub-agent extends BaseAgent","Wrap non-BaseAgent logic in a BaseAgent implementation","Move composite/flow agents out of the routing branch list"],"exampleFix":"// before\nList<Agent> branches = List.of(new MyCustomAgent(\"a\"), someFlowAgent);\n// after\nList<BaseAgent> branches = List.of(new LlmAgent(\"a\", model), new LlmAgent(\"b\", model));","handlingStrategy":"type-guard","validationCode":"for (Agent a : config.getSubAgents()) {\n    if (!(a instanceof BaseAgent)) {\n        throw new IllegalArgumentException(\"Routing branch not BaseAgent: \" + a.getClass().getName());\n    }\n}","typeGuard":"static boolean allBaseAgents(List<? extends Agent> agents) { return agents.stream().allMatch(a -> a instanceof BaseAgent); }","tryCatchPattern":null,"preventionTips":["Only add BaseAgent (leaf) agents as routing branches","Keep composite/flow agents out of routing branch lists","Add a builder-time assertion in tests for branch types"],"tags":["java","agent-framework","routing","type-mismatch"],"backgroundTag":"type-mismatch","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"}