2222
2323import com .google .adk .agents .BaseAgent ;
2424import com .google .adk .agents .Callbacks ;
25- import com .google .adk .agents .LlmAgent ;
26- import com .google .adk .agents .LoopAgent ;
27- import com .google .adk .agents .ParallelAgent ;
28- import com .google .adk .agents .SequentialAgent ;
29- import com .google .adk .tools .AgentTool ;
3025import com .google .adk .tools .BaseTool ;
3126import com .google .adk .tools .BaseToolset ;
32- import com .google .adk .tools .ExampleTool ;
33- import com .google .adk .tools .ExitLoopTool ;
34- import com .google .adk .tools .GoogleMapsTool ;
35- import com .google .adk .tools .GoogleSearchTool ;
36- import com .google .adk .tools .LoadArtifactsTool ;
37- import com .google .adk .tools .LongRunningFunctionTool ;
38- import com .google .adk .tools .UrlContextTool ;
39- import com .google .adk .tools .mcp .McpToolset ;
27+ import com .google .common .collect .ImmutableMap ;
4028import java .util .Map ;
4129import java .util .Optional ;
4230import java .util .Set ;
4331import java .util .concurrent .ConcurrentHashMap ;
44- import javax .annotation .Nonnull ;
4532import org .slf4j .Logger ;
4633import org .slf4j .LoggerFactory ;
4734
9380public class ComponentRegistry {
9481
9582 private static final Logger logger = LoggerFactory .getLogger (ComponentRegistry .class );
83+ private static volatile ImmutableMap <String , Object > DEFAULT_REGISTRY ;
84+
9685 private static volatile ComponentRegistry instance = new ComponentRegistry ();
9786
9887 private final Map <String , Object > registry = new ConcurrentHashMap <>();
@@ -103,55 +92,80 @@ protected ComponentRegistry() {
10392
10493 /** Initializes the registry with base pre-wired ADK instances. */
10594 private void initializePreWiredEntries () {
106- registerAdkAgentClass (LlmAgent .class );
107- registerAdkAgentClass (LoopAgent .class );
108- registerAdkAgentClass (ParallelAgent .class );
109- registerAdkAgentClass (SequentialAgent .class );
110-
111- registerAdkToolInstance ("google_search" , GoogleSearchTool .INSTANCE );
112- registerAdkToolInstance ("load_artifacts" , LoadArtifactsTool .INSTANCE );
113- registerAdkToolInstance ("exit_loop" , ExitLoopTool .INSTANCE );
114- registerAdkToolInstance ("url_context" , UrlContextTool .INSTANCE );
115- registerAdkToolInstance ("google_maps_grounding" , GoogleMapsTool .INSTANCE );
116-
117- registerAdkToolClass (AgentTool .class );
118- registerAdkToolClass (LongRunningFunctionTool .class );
119- registerAdkToolClass (ExampleTool .class );
120-
121- registerAdkToolsetClass (McpToolset .class );
122- // TODO: add all python tools that also exist in Java.
123-
95+ if (DEFAULT_REGISTRY == null ) {
96+ synchronized (ComponentRegistry .class ) {
97+ if (DEFAULT_REGISTRY == null ) {
98+ registerAdkClassByName ("com.google.adk.agents.LlmAgent" );
99+ registerAdkClassByName ("com.google.adk.agents.LoopAgent" );
100+ registerAdkClassByName ("com.google.adk.agents.ParallelAgent" );
101+ registerAdkClassByName ("com.google.adk.agents.SequentialAgent" );
102+
103+ registerAdkToolInstance ("google_search" , "com.google.adk.tools.GoogleSearchTool" );
104+ registerAdkToolInstance ("load_artifacts" , "com.google.adk.tools.LoadArtifactsTool" );
105+ registerAdkToolInstance ("exit_loop" , "com.google.adk.tools.ExitLoopTool" );
106+ registerAdkToolInstance ("url_context" , "com.google.adk.tools.UrlContextTool" );
107+ registerAdkToolInstance ("google_maps_grounding" , "com.google.adk.tools.GoogleMapsTool" );
108+
109+ registerAdkClassByName ("com.google.adk.tools.AgentTool" );
110+ registerAdkClassByName ("com.google.adk.tools.LongRunningFunctionTool" );
111+ registerAdkClassByName ("com.google.adk.tools.ExampleTool" );
112+
113+ registerAdkClassByName ("com.google.adk.tools.mcp.McpToolset" );
114+ // TODO: add all python tools that also exist in Java.
115+
116+ DEFAULT_REGISTRY = ImmutableMap .copyOf (registry );
117+ return ;
118+ }
119+ }
120+ }
121+ registry .putAll (DEFAULT_REGISTRY );
124122 logger .debug ("Initialized base pre-wired entries in ComponentRegistry" );
125123 }
126124
127- private void registerAdkAgentClass (Class <? extends BaseAgent > agentClass ) {
128- registry .put (agentClass .getName (), agentClass );
129- // For python compatibility, also register the name used in ADK Python.
130- registry .put ("google.adk.agents." + agentClass .getSimpleName (), agentClass );
131- }
125+ private void registerAdkClassByName (String className ) {
126+ try {
127+ Class <?> clazz = Thread .currentThread ().getContextClassLoader ().loadClass (className );
128+ String standardPrefix ;
129+ if (BaseAgent .class .isAssignableFrom (clazz )) {
130+ standardPrefix = "google.adk.agents." ;
131+ } else if (BaseTool .class .isAssignableFrom (clazz )) {
132+ standardPrefix = "google.adk.tools." ;
133+ } else if (BaseToolset .class .isAssignableFrom (clazz )) {
134+ standardPrefix = "google.adk.tools." ;
135+ } else {
136+ throw new IllegalArgumentException (
137+ "Cannot determine standardPrefix for type " + clazz .getName ());
138+ }
132139
133- private void registerAdkToolInstance (String name , @ Nonnull Object toolInstance ) {
134- registry .put (name , toolInstance );
135- // For python compatibility, also register the name used in ADK Python.
136- registry .put ("google.adk.tools." + name , toolInstance );
137- }
140+ registry .put (clazz .getName (), clazz );
141+ // For python compatibility, also register the name used in ADK Python.
142+ registry .put (standardPrefix + clazz .getSimpleName (), clazz );
138143
139- private void registerAdkToolClass (@ Nonnull Class <?> toolClass ) {
140- registry .put (toolClass .getName (), toolClass );
141- // For python compatibility, also register the name used in ADK Python.
142- registry .put ("google.adk.tools." + toolClass .getSimpleName (), toolClass );
144+ if (BaseToolset .class .isAssignableFrom (clazz )) {
145+ registry .put (clazz .getSimpleName (), clazz );
146+ if (clazz .getSimpleName ().equals ("McpToolset" )) {
147+ registry .put ("mcp.McpToolset" , clazz );
148+ }
149+ }
150+ } catch (Exception e ) {
151+ logger .info (
152+ "{} not found, skipping registration: {}" ,
153+ className .substring (className .lastIndexOf ('.' ) + 1 ),
154+ e .getMessage ());
155+ }
143156 }
144157
145- private void registerAdkToolsetClass (@ Nonnull Class <? extends BaseToolset > toolsetClass ) {
146- registry .put (toolsetClass .getName (), toolsetClass );
147- // For python compatibility, also register the name used in ADK Python.
148- registry .put ("google.adk.tools." + toolsetClass .getSimpleName (), toolsetClass );
149- // Also register by simple class name
150- registry .put (toolsetClass .getSimpleName (), toolsetClass );
151- // Special support for toolsets with various naming conventions
152- String simpleName = toolsetClass .getSimpleName ();
153- if (simpleName .equals ("McpToolset" )) {
154- registry .put ("mcp.McpToolset" , toolsetClass );
158+ private void registerAdkToolInstance (String name , String toolClassName ) {
159+ try {
160+ Object toolInstance = Class .forName (toolClassName ).getField ("INSTANCE" ).get (null );
161+ registry .put (name , toolInstance );
162+ // For python compatibility, also register the name used in ADK Python.
163+ registry .put ("google.adk.tools." + name , toolInstance );
164+ } catch (Exception e ) {
165+ logger .info (
166+ "{} not found, skipping registration: {}" ,
167+ toolClassName .substring (toolClassName .lastIndexOf ('.' ) + 1 ),
168+ e .getMessage ());
155169 }
156170 }
157171
@@ -281,30 +295,31 @@ public static Optional<BaseAgent> resolveAgentInstance(String name) {
281295 */
282296 public static Class <? extends BaseAgent > resolveAgentClass (String agentClassName ) {
283297 // If no agent_class is specified, it will default to LlmAgent.
284- if (isNullOrEmpty (agentClassName )) {
285- return LlmAgent .class ;
286- }
298+ final String effectiveAgentClassName =
299+ isNullOrEmpty (agentClassName ) ? "com.google.adk.agents.LlmAgent" : agentClassName ;
287300
288301 Optional <Class <? extends BaseAgent >> agentClass ;
289302
290- if (agentClassName .contains ("." )) {
303+ if (effectiveAgentClassName .contains ("." )) {
291304 // If agentClassName contains '.', use it directly
292- agentClass = getType (agentClassName , BaseAgent .class );
305+ agentClass = getType (effectiveAgentClassName , BaseAgent .class );
293306 } else {
294307 // First try the simple name
295308 agentClass =
296- getType (agentClassName , BaseAgent .class )
309+ getType (effectiveAgentClassName , BaseAgent .class )
297310 // If not found, try with com.google.adk.agents prefix
298- .or (() -> getType ("com.google.adk.agents." + agentClassName , BaseAgent .class ))
311+ .or (
312+ () ->
313+ getType ("com.google.adk.agents." + effectiveAgentClassName , BaseAgent .class ))
299314 // For Python compatibility, also try with google.adk.agents prefix
300- .or (() -> getType ("google.adk.agents." + agentClassName , BaseAgent .class ));
315+ .or (() -> getType ("google.adk.agents." + effectiveAgentClassName , BaseAgent .class ));
301316 }
302317
303318 return agentClass .orElseThrow (
304319 () ->
305320 new IllegalArgumentException (
306321 "agentClass '"
307- + agentClassName
322+ + effectiveAgentClassName
308323 + "' is not in registry or not a subclass of BaseAgent." ));
309324 }
310325
0 commit comments