diff --git a/core/src/main/java/com/google/adk/agents/LlmAgent.java b/core/src/main/java/com/google/adk/agents/LlmAgent.java index d326d8154..c2daeb177 100644 --- a/core/src/main/java/com/google/adk/agents/LlmAgent.java +++ b/core/src/main/java/com/google/adk/agents/LlmAgent.java @@ -45,8 +45,6 @@ import com.google.adk.agents.ConfigAgentUtils.ConfigurationException; import com.google.adk.codeexecutors.BaseCodeExecutor; import com.google.adk.events.Event; -import com.google.adk.examples.BaseExampleProvider; -import com.google.adk.examples.Example; import com.google.adk.flows.llmflows.AutoFlow; import com.google.adk.flows.llmflows.BaseLlmFlow; import com.google.adk.flows.llmflows.SingleFlow; @@ -97,8 +95,6 @@ public enum IncludeContents { private final List toolsUnion; private final ImmutableList toolsets; private final Optional generateContentConfig; - // TODO: Remove exampleProvider field - examples should only be provided via ExampleTool - private final Optional exampleProvider; private final IncludeContents includeContents; private final boolean planning; @@ -132,7 +128,6 @@ protected LlmAgent(Builder builder) { this.globalInstruction = requireNonNullElse(builder.globalInstruction, new Instruction.Static("")); this.generateContentConfig = Optional.ofNullable(builder.generateContentConfig); - this.exampleProvider = Optional.ofNullable(builder.exampleProvider); this.includeContents = requireNonNullElse(builder.includeContents, IncludeContents.DEFAULT); this.planning = builder.planning != null && builder.planning; this.maxSteps = Optional.ofNullable(builder.maxSteps); @@ -180,7 +175,6 @@ public static class Builder extends BaseAgent.Builder { private Instruction globalInstruction; private ImmutableList toolsUnion; private GenerateContentConfig generateContentConfig; - private BaseExampleProvider exampleProvider; private IncludeContents includeContents; private Boolean planning; private Integer maxSteps; @@ -253,26 +247,6 @@ public Builder generateContentConfig(GenerateContentConfig generateContentConfig return this; } - // TODO: Remove these example provider methods and only use ExampleTool for providing examples. - // Direct example methods should be deprecated in favor of using ExampleTool consistently. - @CanIgnoreReturnValue - public Builder exampleProvider(BaseExampleProvider exampleProvider) { - this.exampleProvider = exampleProvider; - return this; - } - - @CanIgnoreReturnValue - public Builder exampleProvider(List examples) { - this.exampleProvider = (unused) -> examples; - return this; - } - - @CanIgnoreReturnValue - public Builder exampleProvider(Example... examples) { - this.exampleProvider = (unused) -> ImmutableList.copyOf(examples); - return this; - } - @CanIgnoreReturnValue public Builder includeContents(IncludeContents includeContents) { this.includeContents = includeContents; @@ -640,10 +614,24 @@ protected void validate() { + " transfer."); } if (this.toolsUnion != null && !this.toolsUnion.isEmpty()) { - throw new IllegalArgumentException( - "Invalid config for agent " - + this.name - + ": if outputSchema is set, tools must be empty."); + boolean hasOtherTools = + this.toolsUnion.stream() + .anyMatch( + tool -> { + if (tool instanceof BaseToolset) { + return true; + } + if (tool instanceof BaseTool) { + return !((BaseTool) tool).name().equals("example_tool"); + } + return true; + }); + if (hasOtherTools) { + throw new IllegalArgumentException( + "Invalid config for agent " + + this.name + + ": if outputSchema is set, tools must be empty."); + } } } } @@ -812,11 +800,6 @@ public Optional generateContentConfig() { return generateContentConfig; } - // TODO: Remove this getter - examples should only be provided via ExampleTool - public Optional exampleProvider() { - return exampleProvider; - } - public IncludeContents includeContents() { return includeContents; } diff --git a/core/src/main/java/com/google/adk/examples/ExampleUtils.java b/core/src/main/java/com/google/adk/examples/ExampleUtils.java index 9cce535dc..2f3927ece 100644 --- a/core/src/main/java/com/google/adk/examples/ExampleUtils.java +++ b/core/src/main/java/com/google/adk/examples/ExampleUtils.java @@ -64,6 +64,9 @@ public final class ExampleUtils { * @return string representation of the examples block. */ private static String convertExamplesToText(List examples) { + if (examples.isEmpty()) { + return ""; + } StringBuilder examplesStr = new StringBuilder(); // super header diff --git a/core/src/main/java/com/google/adk/flows/llmflows/Examples.java b/core/src/main/java/com/google/adk/flows/llmflows/Examples.java deleted file mode 100644 index d9cee5fa0..000000000 --- a/core/src/main/java/com/google/adk/flows/llmflows/Examples.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2025 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.adk.flows.llmflows; - -import com.google.adk.agents.InvocationContext; -import com.google.adk.agents.LlmAgent; -import com.google.adk.examples.ExampleUtils; -import com.google.adk.models.LlmRequest; -import com.google.common.collect.ImmutableList; -import com.google.genai.types.Content; -import io.reactivex.rxjava3.core.Single; - -/** {@link RequestProcessor} that populates examples in LLM request. */ -public final class Examples implements RequestProcessor { - - public Examples() {} - - @Override - public Single processRequest( - InvocationContext context, LlmRequest request) { - if (!(context.agent() instanceof LlmAgent)) { - throw new IllegalArgumentException("Agent in InvocationContext is not an instance of Agent."); - } - LlmAgent agent = (LlmAgent) context.agent(); - LlmRequest.Builder builder = request.toBuilder(); - - String query = - context - .userContent() - .flatMap(Content::parts) - .filter(parts -> !parts.isEmpty()) - .map(parts -> parts.get(0).text().orElse("")) - .orElse(""); - agent - .exampleProvider() - .ifPresent( - exampleProvider -> - builder.appendInstructions( - ImmutableList.of(ExampleUtils.buildExampleSi(exampleProvider, query)))); - return Single.just( - RequestProcessor.RequestProcessingResult.create(builder.build(), ImmutableList.of())); - } -} diff --git a/core/src/main/java/com/google/adk/flows/llmflows/SingleFlow.java b/core/src/main/java/com/google/adk/flows/llmflows/SingleFlow.java index de45ba702..f56cc61c3 100644 --- a/core/src/main/java/com/google/adk/flows/llmflows/SingleFlow.java +++ b/core/src/main/java/com/google/adk/flows/llmflows/SingleFlow.java @@ -32,7 +32,6 @@ public class SingleFlow extends BaseLlmFlow { new Identity(), new Compaction(), new Contents(), - new Examples(), CodeExecution.requestProcessor); protected static final ImmutableList RESPONSE_PROCESSORS = diff --git a/core/src/main/java/com/google/adk/tools/ExampleTool.java b/core/src/main/java/com/google/adk/tools/ExampleTool.java index d08481532..d03c2e4f1 100644 --- a/core/src/main/java/com/google/adk/tools/ExampleTool.java +++ b/core/src/main/java/com/google/adk/tools/ExampleTool.java @@ -85,7 +85,9 @@ public Completable processLlmRequest( return Completable.complete(); } - llmRequestBuilder.appendInstructions(ImmutableList.of(examplesBlock)); + if (!examplesBlock.isEmpty()) { + llmRequestBuilder.appendInstructions(ImmutableList.of(examplesBlock)); + } // Delegate to BaseTool to keep any declaration bookkeeping (none for this tool) return super.processLlmRequest(llmRequestBuilder, toolContext); } diff --git a/core/src/test/java/com/google/adk/examples/ExampleUtilsTest.java b/core/src/test/java/com/google/adk/examples/ExampleUtilsTest.java index 4a1dcf8e3..423f806f5 100644 --- a/core/src/test/java/com/google/adk/examples/ExampleUtilsTest.java +++ b/core/src/test/java/com/google/adk/examples/ExampleUtilsTest.java @@ -49,17 +49,7 @@ public List getExamples(String query) { @Test public void buildFewShotFewShot_noExamples() { TestExampleProvider exampleProvider = new TestExampleProvider(ImmutableList.of()); - String expected = - """ - - Begin few-shot - The following are examples of user queries and model responses using the available tools. - - End few-shot - Now, try to follow these examples and complete the following conversation - \ - """; - assertThat(ExampleUtils.buildExampleSi(exampleProvider, "test query")).isEqualTo(expected); + assertThat(ExampleUtils.buildExampleSi(exampleProvider, "test query")).isEqualTo(""); } @Test diff --git a/core/src/test/java/com/google/adk/flows/llmflows/ExamplesTest.java b/core/src/test/java/com/google/adk/flows/llmflows/ExamplesTest.java deleted file mode 100644 index 7d1615dc2..000000000 --- a/core/src/test/java/com/google/adk/flows/llmflows/ExamplesTest.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2026 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.adk.flows.llmflows; - -import static com.google.common.truth.Truth.assertThat; - -import com.google.adk.agents.InvocationContext; -import com.google.adk.agents.LlmAgent; -import com.google.adk.agents.RunConfig; -import com.google.adk.examples.BaseExampleProvider; -import com.google.adk.examples.Example; -import com.google.adk.models.LlmRequest; -import com.google.adk.sessions.InMemorySessionService; -import com.google.adk.sessions.Session; -import com.google.common.collect.ImmutableList; -import com.google.genai.types.Content; -import com.google.genai.types.Part; -import java.util.List; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public final class ExamplesTest { - - private static final InMemorySessionService sessionService = new InMemorySessionService(); - - private static class TestExampleProvider implements BaseExampleProvider { - @Override - public List getExamples(String query) { - return ImmutableList.of( - Example.builder() - .input(Content.fromParts(Part.fromText("input1"))) - .output( - ImmutableList.of( - Content.builder().parts(Part.fromText("output1")).role("model").build())) - .build()); - } - } - - @Test - public void processRequest_withExampleProvider_addsExamplesToInstructions() { - LlmAgent agent = - LlmAgent.builder().name("test-agent").exampleProvider(new TestExampleProvider()).build(); - InvocationContext context = - InvocationContext.builder() - .invocationId("invocation1") - .session(Session.builder("session1").build()) - .sessionService(sessionService) - .agent(agent) - .userContent(Content.fromParts(Part.fromText("what is up?"))) - .runConfig(RunConfig.builder().build()) - .build(); - LlmRequest request = LlmRequest.builder().build(); - Examples examplesProcessor = new Examples(); - - RequestProcessor.RequestProcessingResult result = - examplesProcessor.processRequest(context, request).blockingGet(); - - assertThat(result.updatedRequest().getSystemInstructions()).isNotEmpty(); - assertThat(result.updatedRequest().getSystemInstructions().get(0)) - .contains("[user]\ninput1\n\n[model]\noutput1\n"); - } - - @Test - public void processRequest_withoutExampleProvider_doesNotAddExamplesToInstructions() { - LlmAgent agent = LlmAgent.builder().name("test-agent").build(); - InvocationContext context = - InvocationContext.builder() - .invocationId("invocation1") - .session(Session.builder("session1").build()) - .sessionService(sessionService) - .agent(agent) - .userContent(Content.fromParts(Part.fromText("what is up?"))) - .runConfig(RunConfig.builder().build()) - .build(); - LlmRequest request = LlmRequest.builder().build(); - Examples examplesProcessor = new Examples(); - - RequestProcessor.RequestProcessingResult result = - examplesProcessor.processRequest(context, request).blockingGet(); - - assertThat(result.updatedRequest().getSystemInstructions()).isEmpty(); - } -}