|
| 1 | +--- |
| 2 | +layout: post |
| 3 | +title: 'A2A Java SDK 1.5.0.Final Released' |
| 4 | +date: 2026-11-03 |
| 5 | +tags: ai a2a |
| 6 | +synopsis: 'A2A Java SDK 1.5.0.Final brings unified HTTP client configuration, a first phase of expanded OpenTelemetry support, and improvements to authorized task listings.' |
| 7 | +author: kkhan |
| 8 | +image: announce.jpg |
| 9 | +--- |
| 10 | + |
| 11 | +image::announce.jpg[A2A Java SDK 1.5.0.Final announcement] |
| 12 | + |
| 13 | +We're happy to announce link:https://github.com/a2aproject/a2a-java/releases/tag/v1.5.0.Final[A2A Java SDK 1.5.0.Final]! This release brings unified HTTP client configuration, a first phase of expanded OpenTelemetry support, and improvements to authorized task listings, alongside fixes across JSON-RPC, REST, and gRPC. |
| 14 | + |
| 15 | +NOTE: This release contains *breaking changes*: custom HTTP client configurations may need adjustment, JPA task stores require a schema migration, and custom server integrations must adapt to changes in the validation SPI. Programmatically built handlers also have corrected blocking timeout defaults. See <<_upgrading_from_14x,Upgrading from 1.4.x>> for affected configurations and practical upgrade examples. Ordinary `AgentExecutor` implementations and applications using the reference servers do not need the server SPI adaptations. |
| 16 | + |
| 17 | +== HTTP Client Configuration in One Place |
| 18 | + |
| 19 | +The new `A2AHttpClientConfiguration` brings provider selection, SSE parser settings, and redirect header policies together: |
| 20 | + |
| 21 | +[source,java] |
| 22 | +---- |
| 23 | +A2AHttpClientConfiguration configuration = |
| 24 | + A2AHttpClientConfiguration.builder() |
| 25 | + .excludedProviderNames(List.of("cdi")) |
| 26 | + .sseParserConfig(SSEParserConfig.builder() |
| 27 | + .maxLineLength(64 * 1024) |
| 28 | + .build()) |
| 29 | + .build(); |
| 30 | +
|
| 31 | +A2AHttpClient client = A2AHttpClientFactory.create(configuration); |
| 32 | +---- |
| 33 | + |
| 34 | +Providers that cannot honor explicitly requested settings are skipped, so custom SSE limits are no longer silently ignored. Existing factory methods remain available and are deprecated in favor of the configuration API (link:https://github.com/a2aproject/a2a-java/pull/1255[\#1255]). |
| 35 | + |
| 36 | +Redirect handling is now configurable for synchronous GET requests as well as POST requests, with a shared policy across the built-in HTTP clients. Agent card discovery automatically enables one-hop GET redirects; JSON-RPC and REST transport configuration expose an opt-in setting for non-streaming POST requests. SSE requests do not follow redirects (link:https://github.com/a2aproject/a2a-java/pull/1257[\#1257]). |
| 37 | + |
| 38 | +== First Phase of Expanded OpenTelemetry Support |
| 39 | + |
| 40 | +This release delivers an initial expansion of OpenTelemetry support. Streaming lifecycle instrumentation adds linked spans for events and termination, helping correlate the initial request with later stream activity. It also adds the client operation duration histogram `gen_ai.client.operation.duration` and the server streaming duration histogram `gen_ai.agent.a2a.streaming.duration` (link:https://github.com/a2aproject/a2a-java/pull/1236[\#1236]). |
| 41 | + |
| 42 | +Push notification delivery gains tracing and W3C trace-context propagation. Delivery spans record the outcome and task ID for correlation; the HTTP client wrapper propagates trace context to outbound webhook requests while preserving custom HTTP client settings (link:https://github.com/a2aproject/a2a-java/pull/1229[\#1229]). |
| 43 | + |
| 44 | +With the client instrumentation module present, enable client metrics by passing both a `Tracer` under `OpenTelemetryClientTransportWrapper.OTEL_TRACER_KEY` and a `Meter` under `OpenTelemetryClientTransportWrapper.OTEL_METER_KEY` in the transport configuration parameters. The server instrumentation uses a CDI `Meter` bean for its streaming histogram. Without a `Meter`, the corresponding histogram is skipped. See the link:https://a2aproject.github.io/a2a-java/1_5_0_Final/extra/opentelemetry/[versioned OpenTelemetry documentation] for dependencies and configuration examples. These additions are a first phase, and OpenTelemetry support is not yet complete. |
| 45 | + |
| 46 | +== Task Listings That Respect Authorization Before Pagination |
| 47 | + |
| 48 | +Task listings now apply authorization before selecting a page. Page contents, continuation tokens, and totals therefore describe the same set of readable tasks. This improves pagination when authorized and unauthorized tasks are interspersed in storage (link:https://github.com/a2aproject/a2a-java/pull/1258[\#1258]). |
| 49 | + |
| 50 | +For database deployments, the JPA task store can use authorization capabilities to filter count and page queries directly in the database. A new, explicitly selected `JpaTaskAuthorizationProvider` persists task ownership and supplies owner-based read scopes. Existing authorization providers retain a bounded scanning fallback (link:https://github.com/a2aproject/a2a-java/pull/1259[\#1259]). |
| 51 | + |
| 52 | +== Spring Boot Integration Documentation |
| 53 | + |
| 54 | +The server documentation now covers the community link:https://github.com/soheilqalamkari/a2a-spring[a2a-spring integration], which provides Spring MVC JSON-RPC hosting for the SDK (link:https://github.com/a2aproject/a2a-java/pull/1201[\#1201]). See link:https://a2aproject.github.io/a2a-java/1_5_0_Final/server/#server-integrations[Server Integrations] for the available runtime integrations and manual wiring guidance. |
| 55 | + |
| 56 | +== Selected Fixes |
| 57 | + |
| 58 | +This release also addresses several interoperability and reliability issues: |
| 59 | + |
| 60 | +* *JSON-RPC* -- handles omitted parameters and non-object request bodies more reliably (link:https://github.com/a2aproject/a2a-java/pull/1198[\#1198]), and avoids repeated number-parsing exceptions for string request IDs (link:https://github.com/a2aproject/a2a-java/pull/1254[\#1254]). |
| 61 | +* *REST* -- correctly formats single-digit history lengths (link:https://github.com/a2aproject/a2a-java/pull/1200[\#1200]) and includes missing query parameters in task and push notification configuration listings (link:https://github.com/a2aproject/a2a-java/pull/1239[\#1239]). |
| 62 | +* *gRPC* -- task listing works without a tenant (link:https://github.com/a2aproject/a2a-java/pull/1240[\#1240]). |
| 63 | +* *Event queues* -- gracefully closed child queues receive awaited final events (link:https://github.com/a2aproject/a2a-java/pull/1227[\#1227]). |
| 64 | +* *JSON serialization* -- explicit nulls are preserved in data and metadata (link:https://github.com/a2aproject/a2a-java/pull/1261[\#1261]). |
| 65 | +* *Task listings* -- responses with fewer tasks than the requested page size are accepted (link:https://github.com/a2aproject/a2a-java/pull/1273[\#1273]). |
| 66 | +* *Push notification configuration IDs* -- retrieving a configuration with an omitted or empty ID now falls back to the task ID instead of rejecting the request (link:https://github.com/a2aproject/a2a-java/pull/1242[\#1242]). |
| 67 | +* *Programmatic handler timeouts* -- builder defaults now match the documented 30/5/1 seconds, replacing 5/2/1 seconds. New setters let manually wired applications override each timeout (link:https://github.com/a2aproject/a2a-java/pull/1249[\#1249]); see <<_programmatically_built_handler_timeouts,Programmatically Built Handler Timeouts>> to preserve the previous values. |
| 68 | + |
| 69 | +The link:https://github.com/a2aproject/a2a-java/compare/v1.4.0.Final...v1.5.0.Final[full changelog] includes all fixes, dependency updates, and testing improvements. |
| 70 | + |
| 71 | +== Upgrading from 1.4.x |
| 72 | + |
| 73 | +Update your SDK BOM to `1.5.0.Final`: |
| 74 | + |
| 75 | +[source,xml] |
| 76 | +---- |
| 77 | +<dependencyManagement> |
| 78 | + <dependencies> |
| 79 | + <dependency> |
| 80 | + <groupId>org.a2aproject.sdk</groupId> |
| 81 | + <artifactId>a2a-java-sdk-bom</artifactId> |
| 82 | + <version>1.5.0.Final</version> |
| 83 | + <type>pom</type> |
| 84 | + <scope>import</scope> |
| 85 | + </dependency> |
| 86 | + </dependencies> |
| 87 | +</dependencyManagement> |
| 88 | +---- |
| 89 | + |
| 90 | +=== Custom JDK HTTP Clients and Redirects |
| 91 | + |
| 92 | +If you wrap your own `java.net.http.HttpClient`, native redirect policies such as `NORMAL` or `ALWAYS` now cause an `IOException` when SDK-managed redirect following is enabled. This also affects agent card discovery, which enables GET redirects automatically. |
| 93 | + |
| 94 | +Build the supplied JDK client with `HttpClient.Redirect.NEVER` and let the SDK handle redirects: |
| 95 | + |
| 96 | +[source,java] |
| 97 | +---- |
| 98 | +import java.net.http.HttpClient; |
| 99 | +
|
| 100 | +import org.a2aproject.sdk.client.http.JdkA2AHttpClient; |
| 101 | +import org.a2aproject.sdk.client.transport.jsonrpc.JSONRPCTransportConfig; |
| 102 | +import org.a2aproject.sdk.client.transport.rest.RestTransportConfig; |
| 103 | +
|
| 104 | +HttpClient jdkClient = HttpClient.newBuilder() |
| 105 | + .followRedirects(HttpClient.Redirect.NEVER) |
| 106 | + // Keep your existing TLS, proxy, and timeout settings here. |
| 107 | + .build(); |
| 108 | +
|
| 109 | +JdkA2AHttpClient httpClient = new JdkA2AHttpClient(jdkClient); |
| 110 | +
|
| 111 | +// Enable one-hop redirects for non-streaming POST requests if needed. |
| 112 | +JSONRPCTransportConfig jsonrpcConfig = |
| 113 | + new JSONRPCTransportConfig(httpClient, true); |
| 114 | +RestTransportConfig restConfig = |
| 115 | + new RestTransportConfig(httpClient, true); |
| 116 | +---- |
| 117 | + |
| 118 | +Use the configuration for your chosen transport. If you issue HTTP requests directly, call `.followRedirects(true)` on the GET or POST builder instead. The default SDK-created JDK client already disables native redirects. |
| 119 | + |
| 120 | +The shared policy follows at most one hop and filters cross-origin headers. If an endpoint requires a redirect the policy does not follow, configure the final endpoint URL directly; this is also necessary for SSE streaming. See the link:https://a2aproject.github.io/a2a-java/1_5_0_Final/security/[redirect policy documentation] for supported redirects and trusted-origin header configuration. |
| 121 | + |
| 122 | +=== Explicit SSE Settings Must Be Supported |
| 123 | + |
| 124 | +Previously, if no provider supported a requested `SSEParserConfig`, the factory could fall back to a provider that ignored it. It now skips unsupported providers and throws `IllegalStateException` if no eligible provider can create a client. |
| 125 | + |
| 126 | +If this affects your provider setup, use a client that applies the requested limits. For example, select the built-in JDK implementation directly and pass it to your transport: |
| 127 | + |
| 128 | +[source,java] |
| 129 | +---- |
| 130 | +JdkA2AHttpClient httpClient = JdkA2AHttpClient.withSseConfig( |
| 131 | + SSEParserConfig.builder() |
| 132 | + .maxLineLength(64 * 1024) |
| 133 | + .build()); |
| 134 | +
|
| 135 | +JSONRPCTransportConfig config = new JSONRPCTransportConfig(httpClient); |
| 136 | +---- |
| 137 | + |
| 138 | +Use `RestTransportConfig(httpClient)` for REST. If you maintain a custom provider, implement `createWithSseConfig(...)` to apply the settings and return `true` from `supportsSseConfig()`. Existing factory entry points such as `create()` and `createWithSseConfig(...)` remain available; moving to `create(A2AHttpClientConfiguration)` is recommended but is not required to keep them compiling. |
| 139 | + |
| 140 | +=== JPA Task Store Schema and Ownership |
| 141 | + |
| 142 | +The updated JPA store cleans up ownership records when deleting tasks, so the ownership table is required even if you keep your existing authorization provider. Before deploying, add the table and index through your database migration tool. For PostgreSQL: |
| 143 | + |
| 144 | +[source,sql] |
| 145 | +---- |
| 146 | +CREATE TABLE a2a_task_owners ( |
| 147 | + task_id VARCHAR(255) PRIMARY KEY, |
| 148 | + subject_key BYTEA NOT NULL |
| 149 | +); |
| 150 | +CREATE INDEX a2a_task_owner_subject |
| 151 | + ON a2a_task_owners (subject_key, task_id); |
| 152 | +---- |
| 153 | + |
| 154 | +For MySQL 8, use `VARBINARY(1024)` for `subject_key` instead of `BYTEA`. Subject keys must preserve the exact UTF-8 bytes of the authenticated username. Check your existing task table against the link:https://a2aproject.github.io/a2a-java/1_5_0_Final/extra/storage/[storage documentation] as part of the migration. |
| 155 | + |
| 156 | +If your `persistence.xml` lists entities explicitly, register both in the same `a2a-java` persistence unit: |
| 157 | + |
| 158 | +[source,xml] |
| 159 | +---- |
| 160 | +<class>org.a2aproject.sdk.extras.taskstore.database.jpa.JpaTask</class> |
| 161 | +<class>org.a2aproject.sdk.extras.taskstore.database.jpa.JpaTaskOwner</class> |
| 162 | +---- |
| 163 | + |
| 164 | +Quarkus deployments scanning the JPA module's package discover both entities automatically. You can keep your existing `TaskAuthorizationProvider`; the new ownership provider is optional. To select it in Quarkus: |
| 165 | + |
| 166 | +[source,properties] |
| 167 | +---- |
| 168 | +quarkus.arc.selected-alternatives=org.a2aproject.sdk.extras.taskstore.database.jpa.JpaTaskAuthorizationProvider |
| 169 | +---- |
| 170 | + |
| 171 | +When switching to this provider, backfill ownership for existing tasks from a trusted source before enabling it. Tasks without an ownership record are denied. Use authenticated usernames that uniquely identify users across your deployment, including across tenants or identity providers. The link:https://a2aproject.github.io/a2a-java/1_5_0_Final/extra/storage/[storage documentation] also covers portable CDI and programmatic setup. |
| 172 | + |
| 173 | +Task listings with an existing custom authorization provider may use the bounded scan fallback. If a JPA listing exceeds the default 10,000-candidate limit, narrow the listing filters or increase `a2a.max-scanned-tasks` to a suitable positive value after assessing the scan cost. The new ownership provider supports filtering directly in the database and avoids that fallback limit for its supported policy. |
| 174 | + |
| 175 | +=== Programmatically Built Handler Timeouts |
| 176 | + |
| 177 | +`DefaultRequestHandler.builder()` now defaults to 30 seconds for agent execution, 5 seconds for event consumption, and 1 second for TaskStore reconciliation. Previously, manually built handlers used 5/2/1 seconds, so blocking calls may now wait longer. To retain those previous values, configure the new setters on your handler builder: |
| 178 | + |
| 179 | +[source,java] |
| 180 | +---- |
| 181 | +DefaultRequestHandler.Builder builder = DefaultRequestHandler.builder() |
| 182 | + .agentCompletionTimeoutSeconds(5) |
| 183 | + .consumptionCompletionTimeoutSeconds(2) |
| 184 | + .reconciliationTimeoutSeconds(1); |
| 185 | +
|
| 186 | +// Configure your executor, stores, and remaining dependencies before build(). |
| 187 | +---- |
| 188 | + |
| 189 | +The `a2a.blocking.*` configuration properties apply to CDI-managed handlers; manually wired handlers use these builder setters. See link:https://github.com/a2aproject/a2a-java/pull/1249[\#1249] for the correction. |
| 190 | + |
| 191 | +=== Custom Server Integrations (SPI) |
| 192 | + |
| 193 | +Server validation is now centralized. Integrations calling the transport handlers or removed `AgentCardValidator` resolution helpers must adapt. For example, a custom REST route must pass the raw `historyLength` query string to `RestHandler.getTask`, leaving parsing and validation to the handler. |
| 194 | + |
| 195 | +Before (1.4.x): |
| 196 | + |
| 197 | +[source,java] |
| 198 | +---- |
| 199 | +String historyLength = routingContext.request().getParam("historyLength"); |
| 200 | +restHandler.getTask(context, tenant, taskId, |
| 201 | + historyLength == null ? null : Integer.valueOf(historyLength)); |
| 202 | +---- |
| 203 | + |
| 204 | +After (1.5.0): |
| 205 | + |
| 206 | +[source,java] |
| 207 | +---- |
| 208 | +String historyLength = routingContext.request().getParam("historyLength"); |
| 209 | +restHandler.getTask(context, tenant, taskId, historyLength); |
| 210 | +---- |
| 211 | + |
| 212 | +REST push configuration listing similarly accepts a raw `pageSize` string. Card resolution helpers move to `AgentCardResolver`, request preflight to `AgentCardRequestPolicy`, and cached transport validation to `CachingAgentCardTransportValidator`. Follow the updated reference integration in link:https://github.com/a2aproject/a2a-java/pull/1213[\#1213]. Ordinary `AgentExecutor` implementations and applications using the reference servers do not need these SPI adaptations. |
| 213 | + |
| 214 | +== Also Released: 0.3.4 |
| 215 | + |
| 216 | +For users on the 0.3.x branch, link:https://github.com/a2aproject/a2a-java/releases/tag/v0.3.4.Final[0.3.4] is also available. It includes Gson serialization, structured SSE parsing, push notification webhook authentication support, and an in-memory queue fix. |
| 217 | + |
| 218 | +Although its GitHub tag is `v0.3.4.Final`, the published Maven version is *`0.3.4`*, under the `io.github.a2asdk` group. |
| 219 | + |
| 220 | +== Contributors |
| 221 | + |
| 222 | +Thank you to everyone who contributed code, tests, documentation, and reports for this release, and welcome to our new contributors! |
| 223 | + |
| 224 | +link:https://github.com/ehsavoie[@ehsavoie], link:https://github.com/kabir[@kabir], link:https://github.com/Zhuoxi2000[@Zhuoxi2000], link:https://github.com/014-code[@014-code], link:https://github.com/Kudwa-Abhishek[@Kudwa-Abhishek], link:https://github.com/misysin[@misysin], link:https://github.com/Emryswu[@Emryswu], link:https://github.com/sumitvairagar[@sumitvairagar], link:https://github.com/soheilqalamkari[@soheilqalamkari], link:https://github.com/jeroenbellen[@jeroenbellen], link:https://github.com/prachisinghal-1[@prachisinghal-1], link:https://github.com/RaphaelFakhri[@RaphaelFakhri], link:https://github.com/SashaMIT[@SashaMIT] |
| 225 | + |
| 226 | +== Resources |
| 227 | + |
| 228 | +* link:https://github.com/a2aproject/a2a-java/releases/tag/v1.5.0.Final[Release Notes on GitHub] |
| 229 | +* link:https://central.sonatype.com/artifact/org.a2aproject.sdk/a2a-java-sdk-parent/1.5.0.Final[Maven Central] |
| 230 | +* link:https://javadoc.io/doc/org.a2aproject.sdk/[JavaDoc] |
| 231 | +* link:https://a2a-protocol.org/v1.0.0/specification/[A2A Specification] |
| 232 | +* link:https://a2aproject.github.io/a2a-java/[Project Website] |
| 233 | +* link:https://github.com/a2aproject/a2a-java/tree/main/examples[Examples] |
| 234 | + |
| 235 | +== Come Join Us |
| 236 | + |
| 237 | +We value your feedback a lot so please report bugs, ask for improvements etc. Let's build something great together! |
| 238 | + |
| 239 | +If you are an A2A Java SDK user or just curious, don't be shy and join our welcoming community: |
| 240 | + |
| 241 | +* provide feedback on link:https://github.com/a2aproject/a2a-java/issues[GitHub]; |
| 242 | +* craft some code and link:https://github.com/a2aproject/a2a-java/pulls[push a PR]; |
| 243 | +* discuss with us in the `#a2a-java` channel on link:https://discord.gg/jTtSkJB74Q[Discord]; |
0 commit comments