{"record":{"id":"63cf8831f6461433","repo":"alibaba/spring-ai-alibaba","slug":"shelltoolagenthook-no-shelltool2-injected-skippi","errorCode":null,"errorMessage":"ShellToolAgentHook: No ShellTool2 injected, skipping initialization","messagePattern":"ShellToolAgentHook: No ShellTool2 injected, skipping initialization","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"spring-ai-alibaba-agent-framework/src/main/java/com/alibaba/cloud/ai/graph/agent/hook/shelltool/ShellToolAgentHook.java","lineNumber":81,"sourceCode":"\t */\n\tprivate ShellToolAgentHook(ShellTool2 shellTool2, String shellToolName) {\n\t\tthis.shellTool2 = shellTool2;\n\t\tthis.shellToolName = shellToolName;\n\t}\n\n\t/**\n\t * Create a new builder instance.\n\t * @return a new Builder instance\n\t */\n\tpublic static Builder builder() {\n\t\treturn new Builder();\n\t}\n\n\t@Override\n\tpublic CompletableFuture<Map<String, Object>> beforeAgent(OverAllState state, RunnableConfig config) {\n\t\tShellSessionManager sessionManager = getSessionManager();\n\t\tif (sessionManager == null) {\n\t\t\tlog.warn(\"ShellToolAgentHook: No ShellTool2 injected, skipping initialization\");\n\t\t\treturn CompletableFuture.completedFuture(new HashMap<>());\n\t\t}\n\n\t\tlog.info(\"ShellToolAgentHook: Initializing shell session before agent execution\");\n\n\t\ttry {\n\t\t\tsessionManager.initialize(config);\n\t\t\tlog.info(\"Shell session initialized successfully\");\n\t\t} catch (Exception e) {\n\t\t\tlog.error(\"Failed to initialize shell session\", e);\n\t\t\tthrow new RuntimeException(\"Failed to initialize shell session\", e);\n\t\t}\n\n\t\treturn CompletableFuture.completedFuture(new HashMap<>());\n\t}\n\n\t@Override\n\tpublic CompletableFuture<Map<String, Object>> afterAgent(OverAllState state, RunnableConfig config) {","sourceCodeStart":63,"sourceCodeEnd":99,"githubUrl":"https://github.com/alibaba/spring-ai-alibaba/blob/f82da0b50f35744c13968191be2b1cd2452ef550/spring-ai-alibaba-agent-framework/src/main/java/com/alibaba/cloud/ai/graph/agent/hook/shelltool/ShellToolAgentHook.java#L63-L99","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Pass a ShellTool2 to the hook builder (ShellToolAgentHook.builder().shellTool2(shellTool2)) and re-register the hook with the agent","Verify the tool you registered is actually a ShellTool2 (or wraps one); injectTool only accepts ToolCallbacks whose delegate is ShellTool2","Check logs for the earlier 'Failed to extract ShellTool2 from tool' warning which indicates injection already failed","If shell tooling is intentionally absent, silence the hook by not registering it rather than leaving it half-configured"],"exampleFix":"// before\nShellToolAgentHook hook = ShellToolAgentHook.builder().build();\nagentBuilder.hooks(hook);\n// after\nShellTool2 shellTool2 = ShellTool2.builder().workDir(Path.of(\"/workspace\")).build();\nShellToolAgentHook hook = ShellToolAgentHook.builder().shellTool2(shellTool2).build();\nagentBuilder.hooks(hook);","handlingStrategy":"validation","validationCode":"if (hook.getShellTool2() == null) { throw new IllegalStateException(\"ShellToolAgentHook requires ShellTool2\"); }","typeGuard":"boolean isShellToolCallback(ToolCallback cb) {\n    return cb instanceof FunctionToolCallback fcb\n        && fcb.getToolDefinition() != null\n        && extractShellTool2(cb) != null;\n}","tryCatchPattern":null,"preventionTips":["Always build the hook with ShellToolAgentHook.builder().shellTool2(...)","Register the same ShellTool2 instance as both a tool and hook input","Watch for the companion 'skipping initialization' warning in startup logs","Write a smoke test asserting the hook's session manager is non-null before running the agent"],"tags":["shell","shelltool","hook","missing-dependency","configuration"],"backgroundTag":"missing-dependency","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"}