alibaba/spring-ai-alibaba · warning

ShellToolAgentHook: No ShellTool2 injected, skipping initial

Error message

ShellToolAgentHook: No ShellTool2 injected, skipping initialization

What it means

ShellToolAgentHook.beforeAgent logs this warning and skips initialization when getSessionManager() returns null, i.e. no ShellTool2 instance was injected into the hook. The hook relies on ShellTool2 to create/manage shell sessions before the agent runs; without it there is nothing to initialize, so the hook degrades to a no-op and the agent runs without shell session management.

Source

Thrown at spring-ai-alibaba-agent-framework/src/main/java/com/alibaba/cloud/ai/graph/agent/hook/shelltool/ShellToolAgentHook.java:81

	 */
	private ShellToolAgentHook(ShellTool2 shellTool2, String shellToolName) {
		this.shellTool2 = shellTool2;
		this.shellToolName = shellToolName;
	}

	/**
	 * Create a new builder instance.
	 * @return a new Builder instance
	 */
	public static Builder builder() {
		return new Builder();
	}

	@Override
	public CompletableFuture<Map<String, Object>> beforeAgent(OverAllState state, RunnableConfig config) {
		ShellSessionManager sessionManager = getSessionManager();
		if (sessionManager == null) {
			log.warn("ShellToolAgentHook: No ShellTool2 injected, skipping initialization");
			return CompletableFuture.completedFuture(new HashMap<>());
		}

		log.info("ShellToolAgentHook: Initializing shell session before agent execution");

		try {
			sessionManager.initialize(config);
			log.info("Shell session initialized successfully");
		} catch (Exception e) {
			log.error("Failed to initialize shell session", e);
			throw new RuntimeException("Failed to initialize shell session", e);
		}

		return CompletableFuture.completedFuture(new HashMap<>());
	}

	@Override
	public CompletableFuture<Map<String, Object>> afterAgent(OverAllState state, RunnableConfig config) {

View on GitHub (pinned to f82da0b50f)

Solutions

  1. Pass a ShellTool2 to the hook builder (ShellToolAgentHook.builder().shellTool2(shellTool2)) and re-register the hook with the agent
  2. Verify the tool you registered is actually a ShellTool2 (or wraps one); injectTool only accepts ToolCallbacks whose delegate is ShellTool2
  3. Check logs for the earlier 'Failed to extract ShellTool2 from tool' warning which indicates injection already failed
  4. If shell tooling is intentionally absent, silence the hook by not registering it rather than leaving it half-configured

Example fix

// before
ShellToolAgentHook hook = ShellToolAgentHook.builder().build();
agentBuilder.hooks(hook);
// after
ShellTool2 shellTool2 = ShellTool2.builder().workDir(Path.of("/workspace")).build();
ShellToolAgentHook hook = ShellToolAgentHook.builder().shellTool2(shellTool2).build();
agentBuilder.hooks(hook);
Defensive patterns

Strategy: validation

Validate before calling

if (hook.getShellTool2() == null) { throw new IllegalStateException("ShellToolAgentHook requires ShellTool2"); }

Type guard

boolean isShellToolCallback(ToolCallback cb) {
    return cb instanceof FunctionToolCallback fcb
        && fcb.getToolDefinition() != null
        && extractShellTool2(cb) != null;
}

Prevention

When it happens

Trigger: The hook was registered on an agent but injectTool() was never called (or failed) with a ShellTool2/ToolCallback containing a ShellTool2, so the lazy getSessionManager() resolves to null when beforeAgent fires.

Common situations: Adding the hook via builder config but forgetting shellTool2(); passing a plain FunctionToolCallback that is not a ShellTool2; constructing ShellToolAgentHook manually with the default constructor instead of the builder; a refactor/renamed builder method silently dropping the tool.

Understand the failure class

Background: "not installed", "pip install", "required for": how missing-dependency errors surface across open-source libraries — this error's family across 34 libraries.

Related errors


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