Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 46 additions & 5 deletions core/src/main/java/com/google/adk/agents/BaseAgent.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import io.reactivex.rxjava3.core.Flowable;
import io.reactivex.rxjava3.core.Maybe;
import io.reactivex.rxjava3.core.Single;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.function.Function;
Expand Down Expand Up @@ -90,20 +91,30 @@ public BaseAgent(
this.name = name;
this.description = description;
this.parentAgent = null;
this.subAgents = subAgents == null ? ImmutableList.of() : ImmutableList.copyOf(subAgents);
this.subAgents = (subAgents != null) ? ImmutableList.copyOf(subAgents) : ImmutableList.of();
validateSubAgents(this.name, this.subAgents);
this.beforeAgentCallback =
beforeAgentCallback == null
? ImmutableList.of()
: ImmutableList.copyOf(beforeAgentCallback);
(beforeAgentCallback != null)
? ImmutableList.copyOf(beforeAgentCallback)
: ImmutableList.of();
this.afterAgentCallback =
afterAgentCallback == null ? ImmutableList.of() : ImmutableList.copyOf(afterAgentCallback);
(afterAgentCallback != null)
? ImmutableList.copyOf(afterAgentCallback)
: ImmutableList.of();

// Establish parent relationships for all sub-agents if needed.
for (BaseAgent subAgent : this.subAgents) {
subAgent.parentAgent(this);
}
}

/**
* Validates the agent name.
*
* @param name The agent name to validate.
* @throws IllegalArgumentException if the agent name is null, empty, or does not match the
* identifier pattern.
*/
private static void validateAgentName(String name) {
if (isNullOrEmpty(name)) {
throw new IllegalArgumentException("Agent name cannot be null or empty.");
Expand All @@ -118,6 +129,36 @@ private static void validateAgentName(String name) {
}
}

/**
* Validates the sub-agents.
*
* @param name The name of the parent agent.
* @param subAgents The list of sub-agents to validate.
* @throws IllegalArgumentException if the sub-agents have duplicate names.
*/
private static void validateSubAgents(
String name, @Nullable List<? extends BaseAgent> subAgents) {
if (subAgents == null) {
return;
}
HashSet<String> subAgentNames = new HashSet<>();
HashSet<String> duplicateSubAgentNames = new HashSet<>();
for (BaseAgent subAgent : subAgents) {
String subAgentName = subAgent.name();
// NOTE: Mocked agents have null names because BaseAgent.name() is a final method that
// cannot be mocked.
if (subAgentName != null && !subAgentNames.add(subAgentName)) {
duplicateSubAgentNames.add(subAgentName);
}
}
if (!duplicateSubAgentNames.isEmpty()) {
throw new IllegalArgumentException(
format(
"Agent named '%s' has sub-agents with duplicate names: %s. Sub-agents: %s",
name, duplicateSubAgentNames, subAgents));
}
}

/**
* Gets the agent's unique name.
*
Expand Down
11 changes: 11 additions & 0 deletions core/src/test/java/com/google/adk/agents/BaseAgentTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -351,4 +351,15 @@ public void constructor_userName_throwsIllegalArgumentException() {
IllegalArgumentException.class,
() -> new TestBaseAgent("user", "description", null, null, null));
}

@Test
public void constructor_duplicateSubAgentNames_throwsIllegalArgumentException() {
TestBaseAgent subAgent1 = new TestBaseAgent("subAgent", "subAgent1", null, null, null);
TestBaseAgent subAgent2 = new TestBaseAgent("subAgent", "subAgent2", null, null, null);
assertThrows(
IllegalArgumentException.class,
() ->
new TestBaseAgent(
"agent", "description", null, ImmutableList.of(subAgent1, subAgent2), null, null));
}
}