alibaba/spring-ai-alibaba · error · RuntimeException
Failed to execute agent tool '%s' (parentThreadId=%s, input=
Error message
Failed to execute agent tool '%s' (parentThreadId=%s, input=%s): sub-agent invocation failed:
What it means
AgentTool.executeAgent wraps any GraphRunnerException thrown while invoking the sub-agent (ReactAgent.invoke) into a RuntimeException with the message 'Failed to execute agent tool ...: sub-agent invocation failed: <cause>'. The framework rethrows sub-agent execution failures as tool-call failures so the parent LLM sees the tool error. The root cause is in the wrapped GraphRunnerException message.
Source
Thrown at spring-ai-alibaba-agent-framework/src/main/java/com/alibaba/cloud/ai/graph/agent/AgentTool.java:229
try {
if (parentConfigOpt.isPresent()) {
RunnableConfig parentConfig = parentConfigOpt.get();
RunnableConfig subConfig = RunnableConfig.builder(parentConfig)
.threadId(parentConfig.threadId()
.map(id -> id + "_" + agent.name())
.orElseGet(agent::name))
.nextNode(null)
.checkPointId(null)
.build();
subConfig.clearContext();
resultState = agent.invoke(Map.of("messages", messagesToAdd), subConfig);
}
else {
resultState = agent.invoke(Map.of("messages", messagesToAdd));
}
}
catch (GraphRunnerException e) {
throw buildExecutionException(actualInput, parentConfigOpt.orElse(null),
"sub-agent invocation failed: " + e.getMessage(), e);
}
catch (RuntimeException e) {
throw buildExecutionException(actualInput, parentConfigOpt.orElse(null),
"sub-agent invocation failed: " + e.getMessage(), e);
}
Optional<List> messages = resultState.flatMap(overAllState -> overAllState.value("messages", List.class));
if (messages.isPresent()) {
@SuppressWarnings("unchecked")
List<Message> messageList = (List<Message>) messages.get();
if (!messageList.isEmpty() && messageList.get(messageList.size() - 1) instanceof AssistantMessage assistantMessage) {
return assistantMessage;
}
throw buildExecutionException(actualInput, parentConfigOpt.orElse(null),
"sub-agent returned no assistant message. Last message type: "
+ (messageList.isEmpty() ? "<empty>" : messageList.get(messageList.size() - 1).getMessageType()),
null);View on GitHub (pinned to f82da0b50f)
Solutions
- Read the chained cause in the exception — fix the underlying GraphRunnerException (model auth, network, node error) it reports.
- Verify the sub-agent builds and runs standalone (agent.invoke with a fresh RunnableConfig) to isolate parent-context issues.
- Check checkpoint/persistence connectivity for the derived threadId '<parentThreadId>_<agentName>' and that the parent thread exists.
- Add retry/backoff on transient model or network failures inside the sub-agent's nodes, and validate model credentials before invoking.
Example fix
// before: no failure handling in node
String out = model.call(prompt);
// after: guard model call inside sub-agent node
String out;
try {
out = model.call(prompt);
}
catch (RuntimeException e) {
throw new GraphRunnerException("model call failed: " + e.getMessage(), e);
} Defensive patterns
Strategy: try-catch
Validate before calling
// verify the sub-agent works standalone before wiring it as a tool
OverAllState probe = reactAgent.invoke(Map.of("messages", List.of(new UserMessage("ping")))).orElse(null);
if (probe == null || probe.value("messages", List.class).isEmpty()) {
throw new IllegalStateException("Sub-agent " + reactAgent.name() + " not runnable");
} Type guard
null
Try / catch
try {
assistantMessage = agentToolCallback.call(toolInput);
}
catch (RuntimeException e) {
if (e.getMessage() != null && e.getMessage().contains("sub-agent invocation failed")) {
logger.warn("Sub-agent '{}' failed, falling back", agentName, e.getCause());
// retry once or degrade gracefully
} else {
throw e;
}
} Prevention
- Test each sub-agent standalone before composing it into a parent agent.
- Verify model credentials and connectivity with a smoke call at startup.
- Ensure the checkpoint store is reachable and the parent threadId is valid.
- Add retry/backoff inside nodes for transient model/network errors.
When it happens
Trigger: Calling a sub-agent as a tool from a parent agent and the sub-agent's graph run fails with a GraphRunnerException — e.g. graph compile/executor error, checkpoint/ state read failure, node execution exception, or an invalid RunnableConfig derived from the parent's config.
Common situations: Sub-agent's underlying model call fails (bad API key, network, timeout) and propagates as a GraphRunnerException; sub-graph node throws; persistence/checkpoint backend unavailable for the derived threadId (parentThreadId + '_' + agent.name()); parent invoked via streaming context with an incompatible config.
Related errors
- Failed to execute agent tool '%s' (parentThreadId=%s, input=
- Failed to execute agent tool '%s' (parentThreadId=%s, input=
- TOOL_PARAMS_MISSING
- TOOL_EXECUTION_ERROR
- BUILD_TOOL_RESULT_ERROR
AI-assisted analysis of alibaba/spring-ai-alibaba@f82da0b50f (2026-09-09).
Data as JSON: /api/errors/bbad6a2cf64d1423.
Report an issue: GitHub.