Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
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 @@
{
".": "1.7.0"
".": "1.7.1"
}
3 changes: 0 additions & 3 deletions AGENTS.md

This file was deleted.

13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
# Changelog

## [1.7.1](https://github.com/google/adk-java/compare/v1.7.0...v1.7.1) (2026-07-28)


### Bug Fixes

* **codeexecutors:** add opt-in strict sandbox to ContainerCodeExecutor ([8049f7e](https://github.com/google/adk-java/commit/8049f7e5362ca654bf3706ea465f8d1021ee0346))
* **core:** fallback to name when Agent description is missing ([233b83b](https://github.com/google/adk-java/commit/233b83bcacc39f7b6a1204a7644a1a5f13557a20))
* **events:** accumulate endOfAgent in EventActions.merge to preserve parallel stop requests ([03b04fa](https://github.com/google/adk-java/commit/03b04fa2b17b8b9fc508add4d1013e83a4975cfe))
* **mcp:** honor stdioServerParams in McpToolset.fromConfig ([cf71d7b](https://github.com/google/adk-java/commit/cf71d7bb07398d6fabd3a3ade24f31db98f9f36e))
* preserve all parallel function calls on the live (BIDI) connection ([edc330d](https://github.com/google/adk-java/commit/edc330d760d8194058610907e717f13425717d8b))
* **sessions:** apply afterTimestamp and numRecentEvents together in VertexAiSessionService ([24a4588](https://github.com/google/adk-java/commit/24a4588004228d6117d9ab4a45ce93be4c952d3c))
* **sessions:** apply numRecentEvents and afterTimestamp together in InMemorySessionService ([4d19f7d](https://github.com/google/adk-java/commit/4d19f7d92becff955de12e2a58bc6bb23f14492d))

## [1.7.0](https://github.com/google/adk-java/compare/v1.6.0...v1.7.0) (2026-07-17)


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>1.7.0</version>
<version>1.7.1</version>
</dependency>
<!-- Dev UI -->
<dependency>
<groupId>com.google.adk</groupId>
<artifactId>google-adk-dev</artifactId>
<version>1.7.0</version>
<version>1.7.1</version>
</dependency>
```

Expand Down
58 changes: 33 additions & 25 deletions a2a/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ projects that demonstrate how to expose that runtime over HTTP.
library and exposes the JSON-RPC endpoint.

### High‑Level Picture

```mermaid
graph LR
classDef client fill:#E8F0FE,stroke:#1A73E8,color:#202124;
Expand Down Expand Up @@ -114,45 +115,52 @@ transport-agnostic `a2a/src/...` tree described above.
All commands below assume you are in `google_adk`.

1. **Start the Spring webservice sample** (run in its own terminal)
```bash
lsof -ti :8081 | xargs -r kill
./mvnw -f contrib/samples/a2a_remote/pom.xml spring-boot:run \

```bash
lsof -ti :8081 | xargs -r kill
./mvnw -f contrib/samples/a2a_remote/pom.xml spring-boot:run \
-Dspring-boot.run.arguments=--server.port=8081
```
```

Background option:
```bash
nohup env GOOGLE_GENAI_USE_VERTEXAI=FALSE \
Background option:

```bash
nohup env GOOGLE_GENAI_USE_VERTEXAI=FALSE \
GOOGLE_API_KEY=your_api_key \
./mvnw -f contrib/samples/a2a_remote/pom.xml spring-boot:run \
-Dspring-boot.run.arguments=--server.port=8081 \
> /tmp/a2a_webservice.log 2>&1 & echo $!
```
The log can be found at /tmp/a2a_webservice.log.
```

The log can be found at /tmp/a2a_webservice.log.

2. **Run the basic client sample (`a2a_basic`)** (from another terminal)
```bash
GOOGLE_GENAI_USE_VERTEXAI=FALSE \
GOOGLE_API_KEY=your_api_key \
./mvnw -f contrib/samples/a2a_basic/pom.xml exec:java \

```bash
GOOGLE_GENAI_USE_VERTEXAI=FALSE \
GOOGLE_API_KEY=your_api_key \
./mvnw -f contrib/samples/a2a_basic/pom.xml exec:java \
-Dexec.args="http://localhost:8081/a2a/remote"
```
```

The client logs the outbound JSON-RPC payload and shows the remote agent’s
reply (for example, `4 is not a prime number.`).

The client logs the outbound JSON-RPC payload and shows the remote agent’s
reply (for example, `4 is not a prime number.`).
> The first run downloads dependencies from Maven Central. Configure a
> mirror in `~/.m2/settings.xml` if your environment restricts outbound
> traffic.

> The first run downloads dependencies from Maven Central. Configure a
> mirror in `~/.m2/settings.xml` if your environment restricts outbound traffic.
Background option:

Background option:
```bash
nohup env GOOGLE_GENAI_USE_VERTEXAI=FALSE \
```bash
nohup env GOOGLE_GENAI_USE_VERTEXAI=FALSE \
GOOGLE_API_KEY=your_api_key \
./mvnw -f contrib/samples/a2a_basic/pom.xml exec:java \
-Dexec.args="http://localhost:8081/a2a/remote" \
> /tmp/a2a_basic.log 2>&1 & echo $!
```
Tail `/tmp/a2a_basic.log` to observe subsequent turns.
```

Tail `/tmp/a2a_basic.log` to observe subsequent turns.

To build the runtime, Spring webservice, and both samples together, activate the
opt-in Maven profile:
Expand Down Expand Up @@ -204,15 +212,15 @@ Sample response:
"args": { "nums": [6] },
"name": "checkPrime"
},
"metadata": { "type": "function_call" },
"metadata": { "adk_type": "function_call" },
"kind": "data"
},
{
"data": {
"response": { "result": "No prime numbers found." },
"name": "checkPrime"
},
"metadata": { "type": "function_response" },
"metadata": { "adk_type": "function_response" },
"kind": "data"
},
{
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>1.7.1-SNAPSHOT</version><!-- {x-version-update:google-adk:current} -->
<version>1.7.2-SNAPSHOT</version><!-- {x-version-update:google-adk:current} -->
</parent>

<artifactId>google-adk-a2a</artifactId>
Expand Down
45 changes: 37 additions & 8 deletions a2a/src/main/java/com/google/adk/a2a/converters/PartConverter.java
Original file line number Diff line number Diff line change
Expand Up @@ -154,8 +154,7 @@ private static com.google.genai.types.Part convertDataPartToGenAiPart(DataPart d

String metadataType = metadata.getOrDefault(A2AMetadataKey.TYPE.getType(), "").toString();

if ((data.containsKey(NAME_KEY) && data.containsKey(ARGS_KEY))
|| metadataType.equals(A2ADataPartMetadataType.FUNCTION_CALL.getType())) {
if (metadataType.equals(A2ADataPartMetadataType.FUNCTION_CALL.getType())) {
String functionName = String.valueOf(data.getOrDefault(NAME_KEY, ""));
String functionId = String.valueOf(data.getOrDefault(ID_KEY, ""));
Map<String, Object> args = coerceToMap(data.get(ARGS_KEY));
Expand All @@ -169,8 +168,7 @@ private static com.google.genai.types.Part convertDataPartToGenAiPart(DataPart d
return builder.build();
}

if ((data.containsKey(NAME_KEY) && data.containsKey(RESPONSE_KEY))
|| metadataType.equals(A2ADataPartMetadataType.FUNCTION_RESPONSE.getType())) {
if (metadataType.equals(A2ADataPartMetadataType.FUNCTION_RESPONSE.getType())) {
String functionName = String.valueOf(data.getOrDefault(NAME_KEY, ""));
String functionId = String.valueOf(data.getOrDefault(ID_KEY, ""));
Map<String, Object> response = coerceToMap(data.get(RESPONSE_KEY));
Expand All @@ -188,8 +186,7 @@ private static com.google.genai.types.Part convertDataPartToGenAiPart(DataPart d
return builder.build();
}

if ((data.containsKey(CODE_KEY) && data.containsKey(LANGUAGE_KEY))
|| metadataType.equals(A2ADataPartMetadataType.EXECUTABLE_CODE.getType())) {
if (metadataType.equals(A2ADataPartMetadataType.EXECUTABLE_CODE.getType())) {
String code = String.valueOf(data.getOrDefault(CODE_KEY, ""));
String language =
String.valueOf(
Expand All @@ -204,8 +201,7 @@ private static com.google.genai.types.Part convertDataPartToGenAiPart(DataPart d
return builder.build();
}

if ((data.containsKey(OUTCOME_KEY) && data.containsKey(OUTPUT_KEY))
|| metadataType.equals(A2ADataPartMetadataType.CODE_EXECUTION_RESULT.getType())) {
if (metadataType.equals(A2ADataPartMetadataType.CODE_EXECUTION_RESULT.getType())) {
String outcome =
String.valueOf(data.getOrDefault(OUTCOME_KEY, Outcome.Known.OUTCOME_OK).toString());
String output = String.valueOf(data.getOrDefault(OUTPUT_KEY, ""));
Expand All @@ -222,6 +218,8 @@ private static com.google.genai.types.Part convertDataPartToGenAiPart(DataPart d
return builder.build();
}

logIfUnlabelledControlPayload(data, metadataType);

try {
String json = objectMapper.writeValueAsString(dataPart);
String wrappedJson = A2A_DATA_PART_START_TAG + json + A2A_DATA_PART_END_TAG;
Expand All @@ -239,6 +237,37 @@ private static com.google.genai.types.Part convertDataPartToGenAiPart(DataPart d
}
}

/**
* Warns when a DataPart carries a payload shaped like a control part but no {@code adk_type}
* label, so it is about to be carried through as generic data.
*
* <p>Conversion used to be inferred from this shape. A sender still relying on that - typically a
* non-ADK peer - now silently gets an inline JSON blob instead of a function call or response, so
* name the cause rather than leaving someone to bisect the converter.
*/
private static void logIfUnlabelledControlPayload(Map<String, Object> data, String metadataType) {
if (!metadataType.isEmpty() || !logger.isWarnEnabled()) {
return;
}
String inferredType = null;
if (data.containsKey(NAME_KEY) && data.containsKey(ARGS_KEY)) {
inferredType = A2ADataPartMetadataType.FUNCTION_CALL.getType();
} else if (data.containsKey(NAME_KEY) && data.containsKey(RESPONSE_KEY)) {
inferredType = A2ADataPartMetadataType.FUNCTION_RESPONSE.getType();
} else if (data.containsKey(CODE_KEY) && data.containsKey(LANGUAGE_KEY)) {
inferredType = A2ADataPartMetadataType.EXECUTABLE_CODE.getType();
} else if (data.containsKey(OUTCOME_KEY) && data.containsKey(OUTPUT_KEY)) {
inferredType = A2ADataPartMetadataType.CODE_EXECUTION_RESULT.getType();
}
if (inferredType != null) {
logger.warn(
"A2A DataPart looks like a '{}' but carries no '{}' metadata; treating it as generic"
+ " data. Senders must label control parts explicitly.",
inferredType,
A2AMetadataKey.TYPE.getType());
}
}

/**
* Converts an A2A Message to a Google GenAI Content object.
*
Expand Down
Loading
Loading