feat(tool): support auto tool scan and registration from Spring Context#1192
feat(tool): support auto tool scan and registration from Spring Context#1192jujn wants to merge 5 commits intoagentscope-ai:mainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
This PR adds Spring Boot integration to automatically discover and register @Tool-annotated Spring Bean methods into an AgentScope Toolkit, and refactors the core tool invocation/registration path to work correctly with Spring AOP proxies by separating “metadata methods” from “executable methods”.
Changes:
- Add a Spring Boot
SmartInitializingSingletonregistrar that scans the ApplicationContext for@Toolmethods and registers them into a global Toolkit template. - Refactor
Toolkitregistration andToolMethodInvokerinvocation to support proxy-safe annotation/metadata extraction while still invoking through proxy methods for AOP. - Add Spring Boot starter properties, tests, and update EN/ZH documentation for auto-scan behavior and configuration.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| docs/zh/task/tool.md | Documents Spring Boot auto-scan usage/config and behavior notes (ZH). |
| docs/en/task/tool.md | Documents Spring Boot auto-scan usage/config and behavior notes (EN). |
| agentscope-extensions/.../AgentscopeToolAutoScanTest.java | Adds coverage for auto-scan enablement, proxies, lazy beans, prototype filtering, duplicates, inheritance. |
| agentscope-extensions/.../AgentscopeAutoConfigurationTest.java | Updates expectations for new Toolkit bean arrangement. |
| agentscope-extensions/.../AgentscopeToolRegistrar.java | Implements Spring context scanning + registration into a Toolkit. |
| agentscope-extensions/.../ToolProperties.java | Adds agentscope.tool.auto-scan.enabled property model (default enabled). |
| agentscope-extensions/.../AgentscopeProperties.java | Wires ToolProperties under agentscope.tool. |
| agentscope-extensions/.../AgentscopeAutoConfiguration.java | Introduces global template Toolkit + prototype cloned Toolkit; wires registrar. |
| agentscope-core/.../ToolMethodInvoker*.java | Updates invoker API to accept both original/executable methods; adjusts tests. |
| agentscope-core/.../Toolkit.java | Adds targetClass-aware registration and passes original/executable methods to invoker. |
...spring-boot-starter/src/main/java/io/agentscope/spring/boot/AgentscopeAutoConfiguration.java
Show resolved
Hide resolved
| // Build the complete class hierarchy tree (including all superclasses and | ||
| // interfaces) | ||
| Set<Class<?>> hierarchy = new LinkedHashSet<>(); | ||
| Class<?> current = originalClass; | ||
| while (current != null && current != Object.class) { | ||
| hierarchy.add(current); | ||
| current = current.getSuperclass(); | ||
| } | ||
| hierarchy.addAll(ClassUtils.getAllInterfacesForClassAsSet(originalClass)); | ||
|
|
||
| // Filter the hierarchy to find ONLY the classes/interfaces declaring @Tool. | ||
| Set<Class<?>> classesToScan = new LinkedHashSet<>(); | ||
| for (Class<?> clazz : hierarchy) { | ||
| // Skip Java and Spring internal interfaces | ||
| if (clazz.getName().startsWith("java.") | ||
| || clazz.getName().startsWith("org.springframework.")) { | ||
| continue; | ||
| } | ||
|
|
||
| // Inspect the declared methods to verify if this class/interface contains | ||
| // tools | ||
| for (Method m : clazz.getDeclaredMethods()) { | ||
| if (m.isAnnotationPresent(Tool.class)) { | ||
| classesToScan.add(clazz); | ||
| break; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| for (Class<?> clazzToScan : classesToScan) { | ||
| // Pass both the proxy instance (bean) and the specific declaring | ||
| // class/interface (clazzToScan). | ||
| // This ensures AgentScope extracts metadata (like @Tool) from the exact | ||
| // interface/superclass, | ||
| // while still routing actual method executions through the proxy to | ||
| // preserve Spring AOP aspects. | ||
| toolkit.registration().tool(bean, clazzToScan).apply(); | ||
| } |
There was a problem hiding this comment.
The registrar registers tools once per clazzToScan in the hierarchy. If the same tool method is annotated in multiple hierarchy elements (e.g., both an interface and the implementing class, or a superclass and subclass), this will attempt to register the same tool name multiple times; ToolRegistry overwrites silently, and the earlier duplicate-name fail-fast check may not catch this case. Consider deduplicating by tool name per bean (and defining a clear precedence order, e.g., most-specific class wins over interfaces/superclasses) before calling toolkit.registration().tool(...).apply().
...spring-boot-starter/src/main/java/io/agentscope/spring/boot/AgentscopeAutoConfiguration.java
Show resolved
Hide resolved
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
Description
Close #821
This PR enables automatic discovery of Spring Beans annotated with
@Tool, significantly reducing manual configuration. It also refactors the core tool invocation logic to ensure compatibility with Spring AOP proxies (e.g.,@Transactional,@Async).Key Changes
1. Core Package Enhancements
Toolkit.java: Enhanced the registration API to accept a
targetClassalongside the tool instance. This allows the toolkit to scan for annotations on the unproxied class while executing calls on the proxy instance.ToolMethodInvoker.java: Refactored
invokeAsyncto separate metadata extraction (originalMethod) from actual reflection execution (executableMethod). This prevents annotation loss typically caused by CGLIB or JDK dynamic proxies.2. Spring Boot Starter Integration
AgentscopeToolRegistrar: Implemented aSmartInitializingSingletonto scan the ApplicationContext safely after all beans are initialized.MethodIntrospectorand hierarchy traversal to support tools defined in interfaces or superclasses.@Lazybeans that require early initialization and filters out non-singleton beans to prevent memory leaks.AgentscopeAutoConfiguration:AgentscopeProperties: Centralized tool configuration underagentscope.tool.auto-scan, allowing users to easily toggle the feature.3. Testing & Documentation