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
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "0.7.0"
".": "0.8.0"
}
44 changes: 44 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,49 @@
# Changelog

## [0.8.0](https://github.com/google/adk-java/compare/v0.7.0...v0.8.0) (2026-03-06)


### ⚠ BREAKING CHANGES

* remove methods with Optional params from LiveRequest.Builder
* remove deprecated methods accepting Optional params in InvocationContext
* remove deprecated BaseToolset.isToolSelected method
* remove Optional parameters from LlmResponse.Builder's methods
* remove support for legacy `transferToAgent`, superseded by `transfer_to_agent`

### Features

* add callbacks functionality to the agent executor ([7e8f9dc](https://github.com/google/adk-java/commit/7e8f9dcf82fe7e62aee625fbfaa8673d238ff184))
* add example on how to expose agent via A2A protocol ([e3ea378](https://github.com/google/adk-java/commit/e3ea378051e5c4e5e5031657467145779e42db55))
* Adding a Builder for EventsCompactionConfig ([05fbcfc](https://github.com/google/adk-java/commit/05fbcfc933923ae711cd12e7fc9e587fd8e2685c))
* Adding a SessionKey for typeSafety ([d899f6f](https://github.com/google/adk-java/commit/d899f6f4ad52c84cb4ac8c90d0dc88c22487029c))
* Adding plugin(Plugin... p) helper methods on App and Runner builders ([dc1a192](https://github.com/google/adk-java/commit/dc1a192a81a92870aa5a4af27a9dc90e81cdaf67))
* implement partial event aggregation in RemoteA2AAgent ([e064067](https://github.com/google/adk-java/commit/e0640673d212b9849d312953f192f8da51fae85b))
* remove deprecated BaseToolset.isToolSelected method ([d2f1145](https://github.com/google/adk-java/commit/d2f11456c3a99edd43b3dc0d04743ae7e9390ded))
* remove deprecated methods accepting Optional params in InvocationContext ([88153c8](https://github.com/google/adk-java/commit/88153c833697a9b9c6ec735a69f48a92cbdfc54b))
* remove methods with Optional params from LiveRequest.Builder ([84c62a4](https://github.com/google/adk-java/commit/84c62a48ef7b62641722824fe5ba1200606b7b17))
* remove Optional parameters from LlmResponse.Builder's methods ([a3ac436](https://github.com/google/adk-java/commit/a3ac436bcfa241e90c07485e5da918ec8dbc2b4a))


### Bug Fixes

* Allow injecting ObjectMapper in FunctionTool, default to ObjectMapper (re. [#473](https://github.com/google/adk-java/issues/473)) ([71b1070](https://github.com/google/adk-java/commit/71b10701e753bddaa96d5e6579b759d2b9bb3e92))
* downgrade otel.version to 1.51.0 ([117fedf](https://github.com/google/adk-java/commit/117fedf672bb67c4b078ac75ee81a7710452c5b5))
* Ensure Gemini 3.1 models have events correctly buffered ([acffdb9](https://github.com/google/adk-java/commit/acffdb96bcd8133af99cb0b9426665ba73a83bbc))
* Exit from rearrangeEventsForLatestFunctionResponse if size of events is less than 2 ([5bc3ef8](https://github.com/google/adk-java/commit/5bc3ef89e62eb3f32ba7e45657c9e40c88c3a5e9))
* Fixed issue where events were marked empty if the first part had an empty text; now checks all parts for meaningful content ([a0cba25](https://github.com/google/adk-java/commit/a0cba25d691f4be72bea22b0649ecf2d2c110736))
* prepare JSON serialization for Jackson 2.20.2 and Spring Boot 4.0.2 upgrades ([8c6591b](https://github.com/google/adk-java/commit/8c6591bc4ad86c376cdd70e1bb64f359fbf22fe9))


### Miscellaneous Chores

* revert: switch release please secret to use adk-java-releases-bot's token ([7eafd1b](https://github.com/google/adk-java/commit/7eafd1bd9b16e9ed83dfbc3d0983cfc415c0aaec))


### Code Refactoring

* remove support for legacy `transferToAgent`, superseded by `transfer_to_agent` ([c1ccb2e](https://github.com/google/adk-java/commit/c1ccb2e9d375fedcd7dbb594300e66a1a0488a91))

## [0.7.0](https://github.com/google/adk-java/compare/v0.6.0...v0.7.0) (2026-02-27)


Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,13 @@ If you're using Maven, add the following to your dependencies:
<dependency>
<groupId>com.google.adk</groupId>
<artifactId>google-adk</artifactId>
<version>0.7.0</version>
<version>0.8.0</version>
</dependency>
<!-- Dev UI -->
<dependency>
<groupId>com.google.adk</groupId>
<artifactId>google-adk-dev</artifactId>
<version>0.7.0</version>
<version>0.8.0</version>
</dependency>
```

Expand Down
2 changes: 1 addition & 1 deletion a2a/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<groupId>com.google.adk</groupId>
<artifactId>google-adk-parent</artifactId>
<version>0.7.1-SNAPSHOT</version><!-- {x-version-update:google-adk:current} -->
<version>0.8.1-SNAPSHOT</version><!-- {x-version-update:google-adk:current} -->
</parent>

<artifactId>google-adk-a2a</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.google.adk.a2a.common;

/** Exception thrown when the the genai class has an empty field. */
public class GenAiFieldMissingException extends RuntimeException {
public GenAiFieldMissingException(String message) {
super(message);
}

public GenAiFieldMissingException(String message, Throwable cause) {
super(message, cause);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.google.adk.a2a.converters;

/** Enum for the type of A2A DataPart metadata. */
public enum A2ADataPartMetadataType {
FUNCTION_RESPONSE("function_response"),
FUNCTION_CALL("function_call"),
CODE_EXECUTION_RESULT("code_execution_result"),
EXECUTABLE_CODE("executable_code");

private final String type;

private A2ADataPartMetadataType(String type) {
this.type = type;
}

public String getType() {
return type;
}
}

This file was deleted.

93 changes: 26 additions & 67 deletions a2a/src/main/java/com/google/adk/a2a/converters/EventConverter.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,11 @@
import static com.google.common.collect.ImmutableList.toImmutableList;

import com.google.adk.agents.InvocationContext;
import com.google.adk.events.Event;
import com.google.common.collect.ImmutableList;
import com.google.genai.types.Content;
import com.google.genai.types.Part;
import io.a2a.spec.Message;
import io.a2a.spec.TextPart;
import java.util.ArrayList;
import java.util.List;
import io.a2a.spec.Part;
import java.util.Collection;
import java.util.Optional;
import java.util.UUID;
import org.slf4j.Logger;
Expand All @@ -28,47 +25,35 @@ public final class EventConverter {
private EventConverter() {}

/**
* Aggregation mode for converting events to A2A messages.
* Converts an ADK InvocationContext to an A2A Message.
*
* <p>AS_IS: Parts are aggregated as-is.
* <p>It combines all the events in the session, plus the user content, converted into A2A Parts,
* into a single A2A Message.
*
* <p>EXTERNAL_HANDOFF: Parts are aggregated as-is, except for function responses, which are
* converted to text parts with the function name and response map.
* <p>If the context has no events, or no suitable content to build the message, an empty optional
* is returned.
*
* @param context The ADK InvocationContext to convert.
* @return The converted A2A Message.
*/
public enum AggregationMode {
AS_IS,
EXTERNAL_HANDOFF
}

public static ImmutableList<io.a2a.spec.Part<?>> contentToParts(Optional<Content> content) {
if (content.isPresent() && content.get().parts().isPresent()) {
return content.get().parts().get().stream()
.map(PartConverter::fromGenaiPart)
.flatMap(Optional::stream)
.collect(toImmutableList());
}
return ImmutableList.of();
}

public static Optional<Message> convertEventsToA2AMessage(InvocationContext context) {
return convertEventsToA2AMessage(context, AggregationMode.AS_IS);
}

public static Optional<Message> convertEventsToA2AMessage(
InvocationContext context, AggregationMode mode) {
if (context.session().events().isEmpty()) {
logger.warn("No events in session, cannot convert to A2A message.");
return Optional.empty();
}

List<io.a2a.spec.Part<?>> parts = new ArrayList<>();
for (Event event : context.session().events()) {
appendContentParts(event.content(), mode, parts);
}
ImmutableList.Builder<Part<?>> partsBuilder = ImmutableList.builder();

context
.userContent()
.ifPresent(content -> appendContentParts(Optional.of(content), mode, parts));
.session()
.events()
.forEach(
event ->
partsBuilder.addAll(
contentToParts(event.content(), event.partial().orElse(false))));
partsBuilder.addAll(contentToParts(context.userContent(), false));

ImmutableList<Part<?>> parts = partsBuilder.build();

if (parts.isEmpty()) {
logger.warn("No suitable content found to build A2A request message.");
Expand All @@ -83,37 +68,11 @@ public static Optional<Message> convertEventsToA2AMessage(
.build());
}

private static void appendContentParts(
Optional<Content> contentOpt, AggregationMode mode, List<io.a2a.spec.Part<?>> target) {
if (contentOpt.isEmpty() || contentOpt.get().parts().isEmpty()) {
return;
}

for (Part part : contentOpt.get().parts().get()) {
if (part.text().isPresent()) {
target.add(new TextPart(part.text().get()));
continue;
}

if (part.functionCall().isPresent()) {
if (mode == AggregationMode.AS_IS) {
PartConverter.convertGenaiPartToA2aPart(part).ifPresent(target::add);
}
continue;
}

if (part.functionResponse().isPresent()) {
if (mode == AggregationMode.AS_IS) {
PartConverter.convertGenaiPartToA2aPart(part).ifPresent(target::add);
} else {
String name = part.functionResponse().get().name().orElse("");
String mapStr = String.valueOf(part.functionResponse().get().response().orElse(null));
target.add(new TextPart(String.format("%s response: %s", name, mapStr)));
}
continue;
}

PartConverter.fromGenaiPart(part).ifPresent(target::add);
}
public static ImmutableList<Part<?>> contentToParts(
Optional<Content> content, boolean isPartial) {
return content.flatMap(Content::parts).stream()
.flatMap(Collection::stream)
.map(part -> PartConverter.fromGenaiPart(part, isPartial))
.collect(toImmutableList());
}
}
Loading
Loading