Skip to content

[Bug]: CreateTaskPushNotificationConfig on HTTP+JSON incorrectly requires the task ID in the request body #732

@jmesnil

Description

@jmesnil

What happened?

Summary

CreateTaskPushNotificationConfig on HTTP+JSON returns 422 because the SUT requires taskId in the request body instead of extracting it from the URL path /tasks/{id}/pushNotificationConfigs. Per the proto's body: "*" HTTP transcoding rule, fields bound to URL path variables (like task_id) are extracted from the path, and only the remaining fields belong in the request body.

Requirement

Specification

The CreatePushNotificationConfig operation MUST establish a webhook endpoint for task update notifications. When task updates occur, the agent will send HTTP POST requests to the configured webhook URL with StreamResponse payloads. The configuration MUST persist until task completion or explicit deletion.

The HTTP+JSON binding for this operation is defined as:

Operation HTTP+JSON
Create push notification config POST /tasks/{id}/pushNotificationConfigs

The proto definition uses body: "*" with task_id in the URL path, meaning task_id is extracted from the path, and only the remaining fields belong in the request body.

Expected behavior

A POST /tasks/{task_id}/pushNotificationConfigs request with the push notification config in the body (without taskId) should succeed and return the created configuration:

POST /tasks/914b1064-.../pushNotificationConfigs
Content-Type: application/json

{"id": "my-config-001", "url": "https://example.com/webhook"}

Response: 201 Created with the TaskPushNotificationConfig.

Actual behavior

The SUT returns 422 with error "taskId is required", indicating it expects taskId in the request body rather than extracting it from the URL path:

{"error": "io.a2a.spec.InvalidParamsError", "message": "taskId is required"}

When taskId is redundantly included in the body, the request succeeds (201), confirming the SUT does not extract the task ID from the URL path segment.

Note: This same operation works correctly on JSON-RPC and gRPC transports, where taskId is naturally part of the request parameters/message. The failure is isolated to HTTP+JSON.

Reproducer

# Step 1: Create a task via SendMessage
TASK_ID=$(curl -s -X POST http://localhost:9999/message:send \
  -H "Content-Type: application/json" \
  -d '{
    "message": {
      "role": "ROLE_USER",
      "parts": [{"text": "hello"}],
      "messageId": "msg-001"
    },
    "configuration": {
      "acceptedOutputModes": ["text"]
    }
  }' | python3 -c "import sys,json; print(json.load(sys.stdin)['task']['id'])")

echo "Task ID: $TASK_ID"

# Step 2: Create push notification config (FAILS with 422)
# Per spec, task_id comes from the URL path; body contains only the config fields
curl -s -w "\nHTTP %{http_code}" \
  -X POST "http://localhost:9999/tasks/${TASK_ID}/pushNotificationConfigs" \
  -H "Content-Type: application/json" \
  -d '{"id": "my-push-config", "url": "https://example.com/webhook"}'
# Expected: 201 with TaskPushNotificationConfig
# Actual:   422 {"error":"io.a2a.spec.InvalidParamsError","message":"taskId is required"}

# Step 3: With taskId in body (SUCCEEDS — confirms the bug)
curl -s -w "\nHTTP %{http_code}" \
  -X POST "http://localhost:9999/tasks/${TASK_ID}/pushNotificationConfigs" \
  -H "Content-Type: application/json" \
  -d "{\"taskId\": \"${TASK_ID}\", \"id\": \"my-push-config\", \"url\": \"https://example.com/webhook\"}"
# Returns: 201 (should work without taskId in body)

TCK tests

tests/compatibility/core_operations/test_push_notifications.py::TestPushNotificationCrud::test_create_push_config[grpc]
tests/compatibility/core_operations/test_push_notifications.py::TestPushNotificationCrud::test_create_push_config[http_json]
tests/compatibility/core_operations/test_push_notifications.py::TestPushNotificationCrud::test_create_push_config[jsonrpc]

Relevant log output

Code of Conduct

  • I agree to follow this project's Code of Conduct

Metadata

Metadata

Assignees

Labels

compatibilityIssue related to A2A compatibilityhttp+jsonIssue related to the HTTP+JSON transport

Type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions