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

  1. Read the chained cause in the exception — fix the underlying GraphRunnerException (model auth, network, node error) it reports.
  2. Verify the sub-agent builds and runs standalone (agent.invoke with a fresh RunnableConfig) to isolate parent-context issues.
  3. Check checkpoint/persistence connectivity for the derived threadId '<parentThreadId>_<agentName>' and that the parent thread exists.
  4. 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

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


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