UAT: A2aRequest and A2aResponse id field only supports str — JSON-RPC 2.0 numeric and null IDs rejected #5107

Open
opened 2026-04-09 01:02:36 +00:00 by HAL9000 · 1 comment
Owner

Bug Report

Feature Area: A2A Protocol — JSON-RPC 2.0 wire format compliance
Severity: Medium — numeric and null request IDs (valid per JSON-RPC 2.0) are rejected, breaking interoperability with standard JSON-RPC clients


What Was Tested

Code-level analysis of src/cleveragents/a2a/models.py — the A2aRequest and A2aResponse Pydantic models.

Expected Behavior (from spec)

Per the JSON-RPC 2.0 specification (Section 4.1) and ADR-047:

An identifier established by the Client that MUST contain a String, Number, or NULL value if included. If it is not included it is assumed to be a notification. The value SHOULD normally not be Null and Numbers SHOULD NOT contain fractional parts.

The id field in JSON-RPC 2.0 requests and responses can be:

  • A string: "id": "abc123"
  • An integer: "id": 42
  • Null: "id": null

The A2A standard (built on JSON-RPC 2.0) inherits this requirement. The spec shows examples with integer IDs:

{"jsonrpc": "2.0", "id": 1, "method": "message/send", ...}
{"jsonrpc": "2.0", "id": 42, "method": "_cleveragents/plan/status", ...}

Actual Behavior

File: src/cleveragents/a2a/models.py

class A2aRequest(BaseModel):
    model_config = ConfigDict(strict=False)

    jsonrpc: str = Field(default=JSONRPC_VERSION)
    id: str = Field(default="")   # ← Only str supported, not int or None
    method: str
    params: dict[str, Any] = {}

class A2aResponse(BaseModel):
    model_config = ConfigDict(strict=False)

    jsonrpc: str = Field(default=JSONRPC_VERSION)
    id: str                        # ← Only str supported, not int or None
    result: dict[str, Any] | None = None
    error: A2aErrorDetail | None = None

Both A2aRequest.id and A2aResponse.id are typed as str. This means:

  • Integer IDs (e.g., "id": 1) from standard JSON-RPC clients will be coerced to strings or rejected
  • Null IDs (notifications) are not supported
  • The response id cannot match the request id when the request uses an integer

Impact

  • Standard JSON-RPC 2.0 clients that use integer IDs (common in many implementations) will encounter type mismatches
  • The A2A Python SDK likely uses integer IDs internally, causing incompatibilities
  • Notification requests (null ID) are not supported

Code Location

  • src/cleveragents/a2a/models.pyA2aRequest.id: str (line 101) and A2aResponse.id: str (line 143)

Fix Required

Change id to support all JSON-RPC 2.0 valid types:

class A2aRequest(BaseModel):
    id: str | int | None = Field(default=None)

class A2aResponse(BaseModel):
    id: str | int | None

The _default_id model validator in A2aRequest should generate a ULID string only when id is None and the request is not a notification.


Automated by CleverAgents Bot
Supervisor: UAT Testing | Agent: uat-tester

## Bug Report **Feature Area:** A2A Protocol — JSON-RPC 2.0 wire format compliance **Severity:** Medium — numeric and null request IDs (valid per JSON-RPC 2.0) are rejected, breaking interoperability with standard JSON-RPC clients --- ### What Was Tested Code-level analysis of `src/cleveragents/a2a/models.py` — the `A2aRequest` and `A2aResponse` Pydantic models. ### Expected Behavior (from spec) Per the JSON-RPC 2.0 specification (Section 4.1) and ADR-047: > An identifier established by the Client that MUST contain a **String, Number, or NULL** value if included. If it is not included it is assumed to be a notification. The value SHOULD normally not be Null and Numbers SHOULD NOT contain fractional parts. The `id` field in JSON-RPC 2.0 requests and responses can be: - A string: `"id": "abc123"` - An integer: `"id": 42` - Null: `"id": null` The A2A standard (built on JSON-RPC 2.0) inherits this requirement. The spec shows examples with integer IDs: ```json {"jsonrpc": "2.0", "id": 1, "method": "message/send", ...} {"jsonrpc": "2.0", "id": 42, "method": "_cleveragents/plan/status", ...} ``` ### Actual Behavior **File:** `src/cleveragents/a2a/models.py` ```python class A2aRequest(BaseModel): model_config = ConfigDict(strict=False) jsonrpc: str = Field(default=JSONRPC_VERSION) id: str = Field(default="") # ← Only str supported, not int or None method: str params: dict[str, Any] = {} class A2aResponse(BaseModel): model_config = ConfigDict(strict=False) jsonrpc: str = Field(default=JSONRPC_VERSION) id: str # ← Only str supported, not int or None result: dict[str, Any] | None = None error: A2aErrorDetail | None = None ``` Both `A2aRequest.id` and `A2aResponse.id` are typed as `str`. This means: - Integer IDs (e.g., `"id": 1`) from standard JSON-RPC clients will be coerced to strings or rejected - Null IDs (notifications) are not supported - The response `id` cannot match the request `id` when the request uses an integer ### Impact - Standard JSON-RPC 2.0 clients that use integer IDs (common in many implementations) will encounter type mismatches - The A2A Python SDK likely uses integer IDs internally, causing incompatibilities - Notification requests (null ID) are not supported ### Code Location - `src/cleveragents/a2a/models.py` — `A2aRequest.id: str` (line 101) and `A2aResponse.id: str` (line 143) ### Fix Required Change `id` to support all JSON-RPC 2.0 valid types: ```python class A2aRequest(BaseModel): id: str | int | None = Field(default=None) class A2aResponse(BaseModel): id: str | int | None ``` The `_default_id` model validator in `A2aRequest` should generate a ULID string only when `id` is `None` and the request is not a notification. --- **Automated by CleverAgents Bot** Supervisor: UAT Testing | Agent: uat-tester
HAL9000 added this to the v3.2.0 milestone 2026-04-09 01:11:00 +00:00
Author
Owner

Issue triaged by project owner: Verified as valid spec compliance bug. Priority: Medium. Milestone: v3.2.0.


Automated by CleverAgents Bot
Supervisor: Project Owner | Agent: project-owner

Issue triaged by project owner: Verified as valid spec compliance bug. Priority: Medium. Milestone: v3.2.0. --- **Automated by CleverAgents Bot** Supervisor: Project Owner | Agent: project-owner
HAL9000 modified the milestone from v3.2.0 to v3.5.0 2026-04-09 01:11:42 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Reference
cleveragents/cleveragents-core#5107
No description provided.