Repository navigation
Description
What happened?
Summary
Per the A2A specification (Section 3.1.7, "Create Push Notification Config"), the id field of a push notification config is optional when creating one — the only required input is url, and the server assigns an ID if none is provided. The runtime request paths honor this, but the Java domain record TaskPushNotificationConfig enforces id as non-null, which contradicts the spec, the gRPC proto definition, and the store interface's own documented contract.
Spec reference
- A2A Protocol Spec — Create Push Notification Config:
idis not required on create; the server generates and returns the assigned ID.
What the code does
Consistent with the spec
spec-grpc/src/main/proto/a2a.proto(message TaskPushNotificationConfig, lines 466–480):string id = 2;is not marked(google.api.field_behavior) = REQUIRED; onlyurlis.- All request entry points (JSON-RPC
JSONRPCUtils.java:224-230, RESTRestHandler.java:376-385) parse the body into a proto builder first, so a missingidarrives as the protobuf default empty string"", andInMemoryPushNotificationConfigStore.setInfo(:51) defaults an empty id to the task ID (if (notificationConfig.id().isEmpty()) builder.id(taskId)). So a client omittingiddoes get a config back with an assigned ID.
Inconsistent with the spec
spec/src/main/java/org/a2aproject/sdk/spec/TaskPushNotificationConfig.java:- Compact constructor (line 48):
Assert.checkNotNullParam("id", id); Builder.build()(line 177):Assert.checkNotNullParam("id", id);
- Compact constructor (line 48):
This makes id required at the domain-API level, so:
TaskPushNotificationConfig.builder().url(...).build()throwsIllegalArgumentExceptionwhenidis omitted — but the spec saysidis optional and the server assigns it.PushNotificationConfigStore.setInfodocuments "IfnotificationConfig.id()is null or empty, it's set to the task ID" (PushNotificationConfigStore.java:91), but the null branch is dead code — a nullidcan never be constructed through the public API.InMemoryPushNotificationConfigStore.setInfo:51callsnotificationConfig.id().isEmpty(); if a nullidever reached it (as the Javadoc promises), it would NPE instead of defaulting.
The current "optional id works at runtime" behavior is load-bearing on the fact that the mapper TaskPushNotificationConfigMapper.fromProto does not apply emptyToNull to id (it does for taskId/token/tenant) — it only survives because proto yields "" rather than null.
Related (secondary) inconsistency
GetTaskPushNotificationConfigParams.java:31-32: the Javadoc describes id as "optional specific configuration ID to retrieve", but the constructor asserts checkNotNullParam("id", id) — so the default config cannot be retrieved without specifying an id.
Expected behavior
idshould be optional when constructing/creating aTaskPushNotificationConfig; the server assigns an ID (e.g., defaults to the task ID) when it is absent, and returns the config with the assigned ID.- Constructing
TaskPushNotificationConfig.builder().url(...).build()should succeed, mirroring the spec and the 0.3 compat recordPushNotificationConfig_v0_3(which only validatesurl).
Relevant log output
Code of Conduct
- I agree to follow this project's Code of Conduct
Activity
fix: allow omitted task push config id
fix: allow omitted task push config id (a2aproject#1092)