Skip to content

SDK CreateTaskPushNotificationConfig uses TaskPushNotificationConfig (flat) as request type; spec defines CreateTaskPushNotificationConfigRequest (nested config) #875

@zeroasterisk

Description

@zeroasterisk

Summary

The SDK maps CreateTaskPushNotificationConfig to TaskPushNotificationConfig as the JSON-RPC request type. The A2A v1.0 spec defines a distinct CreateTaskPushNotificationConfigRequest message that wraps the config in a nested config: PushNotificationConfig field. The SDK's flat mapping causes a protocol-level divergence from the spec.

Spec Reference

File: specification/a2a.proto

message CreateTaskPushNotificationConfigRequest {
  string tenant = 1;
  string task_id = 2 [(google.api.field_behavior) = REQUIRED];
  PushNotificationConfig config = 3 [(google.api.field_behavior) = REQUIRED];  // NESTED
}

SDK Implementation

# a2a/server/apps/jsonrpc/jsonrpc_app.py
METHOD_TO_MODEL: dict[str, type] = {
    ...
    'CreateTaskPushNotificationConfig': TaskPushNotificationConfig,  # Wrong type!
    ...
}

The SDK uses TaskPushNotificationConfig (a response/storage type) as the request deserialization target, instead of CreateTaskPushNotificationConfigRequest. The TaskPushNotificationConfig has flat fields {id, task_id, url, token, authentication} while the spec's request type has {task_id, config: PushNotificationConfig{id, url, token}}.

Impact

The SDK accepts a flat {"taskId": "...", "id": "cfg-1", "url": "..."} format, but per spec the correct wire format is {"taskId": "...", "config": {"id": "cfg-1", "url": "..."}}. This means:

  1. Spec-compliant clients sending the nested format get -32602
  2. The TCK (which sends configId at the wrong level) also gets -32602

Reproduction

# Start any a2a-sdk 1.0.0a0 agent with push notifications capability
TASK_ID=$(curl -s http://localhost:9996 ... | extract_task_id)

# Spec-correct nested format (FAILS with SDK):
curl -X POST http://localhost:9996 -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","method":"CreateTaskPushNotificationConfig","params":{"taskId":"'"$TASK_ID"'","config":{"id":"cfg-1","url":"https://example.com/hook"}},"id":"2"}'
# => -32602: 'config' is not a valid field in TaskPushNotificationConfig

# SDK's flat format (WORKS but not per spec):
curl -X POST http://localhost:9996 -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","method":"CreateTaskPushNotificationConfig","params":{"taskId":"'"$TASK_ID"'","id":"cfg-1","url":"https://example.com/hook"},"id":"2"}'
# => {"result": {"id": "cfg-1", "taskId": "...", "url": "..."}}

Expected vs Actual

  • Spec defines: CreateTaskPushNotificationConfig request type = CreateTaskPushNotificationConfigRequest
  • SDK uses: TaskPushNotificationConfig (flat, wrong)
  • Effect: The SDK JSON-RPC layer doesn't match the v1.0 proto definition for this method

Fix

In jsonrpc_app.py, change the method mapping to use the correct request type and update the handler to extract the nested config from the request:

from a2a.types.a2a_pb2 import CreateTaskPushNotificationConfigRequest
METHOD_TO_MODEL = {
    ...
    'CreateTaskPushNotificationConfig': CreateTaskPushNotificationConfigRequest,
    ...
}

And update set_push_notification_config handler to accept CreateTaskPushNotificationConfigRequest and convert to TaskPushNotificationConfig.

Classification

SDK bug: Wrong request type used for CreateTaskPushNotificationConfig. The SDK should parse CreateTaskPushNotificationConfigRequest (nested) not TaskPushNotificationConfig (flat).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions