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 737058039..46b0b1f50 100644 --- a/core/src/main/java/com/google/adk/agents/LlmAgent.java +++ b/core/src/main/java/com/google/adk/agents/LlmAgent.java @@ -622,6 +622,12 @@ protected BaseLlmFlow determineLlmFlow() { } private void maybeSaveOutputToState(Event event) { + // Events from another agent, e.g. a transfer target, must not overwrite this agent's output. + if (!name().equals(event.author())) { + logger.debug( + "Skipping output save for agent {}: event authored by {}", name(), event.author()); + return; + } if (outputKey().isEmpty() || !event.finalResponse() || event.content().isEmpty()) { return; } diff --git a/core/src/test/java/com/google/adk/agents/LlmAgentTest.java b/core/src/test/java/com/google/adk/agents/LlmAgentTest.java index d017860ce..ffe581bef 100644 --- a/core/src/test/java/com/google/adk/agents/LlmAgentTest.java +++ b/core/src/test/java/com/google/adk/agents/LlmAgentTest.java @@ -25,6 +25,7 @@ import static com.google.adk.testing.TestUtils.createTestLlm; import static com.google.adk.testing.TestUtils.createTextLlmResponse; import static com.google.adk.testing.TestUtils.simplifyEvents; +import static com.google.common.collect.Iterables.getLast; import static com.google.common.collect.Iterables.getOnlyElement; import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertEquals; @@ -177,6 +178,33 @@ public void testRun_withOutputKey_savesState_ignoresThoughts() { assertThat(events.get(0).actions().stateDelta()).containsEntry("myOutput", "Saved output"); } + @Test + public void testRun_withOutputKey_doesNotSaveTheOutputOfATransferredToAgent() { + LlmAgent subAgent = + createTestAgentBuilder(createTestLlm(createTextLlmResponse("Sub-agent answer"))) + .name("sub_agent") + .outputKey("subAgentOutput") + .build(); + Content transferCall = + Content.fromParts( + Part.fromFunctionCall("transfer_to_agent", ImmutableMap.of("agent_name", "sub_agent"))); + LlmAgent agent = + createTestAgentBuilder(createTestLlm(createLlmResponse(transferCall))) + .outputKey("myOutput") + .subAgents(subAgent) + .build(); + InvocationContext invocationContext = createInvocationContext(agent); + + List events = agent.runAsync(invocationContext).toList().blockingGet(); + + Event subAgentAnswer = getLast(events); + assertThat(subAgentAnswer.author()).isEqualTo("sub_agent"); + assertThat(subAgentAnswer.finalResponse()).isTrue(); + assertThat(subAgentAnswer.actions().stateDelta()).doesNotContainKey("myOutput"); + assertThat(subAgentAnswer.actions().stateDelta()) + .containsEntry("subAgentOutput", "Sub-agent answer"); + } + @Test public void testRun_withoutOutputKey_doesNotSaveState() { Content modelContent = Content.fromParts(Part.fromText("Some output"));