UAT: A2aVersionNegotiator is not wired into the A2A dispatch pipeline — version negotiation is dead code #4078

Open
opened 2026-04-06 10:05:43 +00:00 by freemo · 0 comments
Owner

Bug Report

Feature Area: API Versioning and Backward Compatibility
Severity: Critical (per UAT report)
Found by: UAT Testing (automated)


Background and Context

The A2A protocol is a versioned standard. The A2aVersionNegotiator class exists in src/cleveragents/a2a/versioning.py and is exported from the cleveragents.a2a package, but it is never called during actual A2A request dispatch. This means the version negotiation mechanism is dead code — clients cannot negotiate protocol versions because the negotiator is not wired into the dispatch pipeline.

Per the specification, the A2A layer must enforce protocol version compatibility on every inbound request to ensure backward compatibility and to surface clear errors when clients use unsupported protocol versions.

Current Behavior

In src/cleveragents/a2a/facade.py, the dispatch() method processes A2aRequest objects without ever invoking A2aVersionNegotiator:

def dispatch(self, request: A2aRequest) -> A2aResponse:
    # No version negotiation here!
    start = time.monotonic()
    try:
        data = self._route_operation(request.method, request.params)
        ...

The A2aVersionNegotiator is only referenced in:

  • src/cleveragents/a2a/__init__.py (exported)
  • src/cleveragents/a2a/versioning.py (defined)

It is not used in:

  • src/cleveragents/a2a/facade.py (dispatch)
  • src/cleveragents/a2a/asgi.py (ASGI server)
  • src/cleveragents/a2a/transport.py (HTTP transport)

Expected Behavior

When a client sends an A2A request, the server should:

  1. Extract the requested A2A protocol version from the request
  2. Call A2aVersionNegotiator.negotiate(requested_version) to validate compatibility
  3. Reject requests with unsupported versions by raising A2aVersionMismatchError and returning a structured error response

Acceptance Criteria

  • A2aLocalFacade.dispatch() calls A2aVersionNegotiator.negotiate() on every inbound request before routing
  • Requests carrying an unsupported A2A protocol version receive an A2aResponse with an A2aErrorDetail describing the version mismatch (not an unhandled exception)
  • A2aVersionMismatchError is reachable via the normal dispatch path (not only by direct calls to the negotiator)
  • All existing dispatch behaviour is preserved for requests with supported protocol versions
  • All nox stages pass (nox)
  • Coverage ≥ 97% (nox -s coverage_report)

Supporting Information

  • Related: #3971 (A2A layer has zero unit tests — critical protocol layer is untested)
  • Related: #3638 (A2A-Version HTTP header not sent or validated in server mode)
  • Related: #3533 (ASGI server missing A2A JSON-RPC endpoint)
  • Code location: src/cleveragents/a2a/versioning.pyA2aVersionNegotiator class
  • Code location: src/cleveragents/a2a/facade.pyA2aLocalFacade.dispatch() method (missing negotiation call)

Suggested Fix:

def dispatch(self, request: A2aRequest) -> A2aResponse:
    # Negotiate A2A protocol version
    negotiator = A2aVersionNegotiator()
    try:
        negotiator.negotiate(request.jsonrpc)  # or a2a_version field
    except A2aVersionMismatchError as exc:
        return A2aResponse(
            id=request.id,
            error=A2aErrorDetail(
                code="VERSION_MISMATCH",
                message=str(exc),
                details={"supported": list(negotiator.SUPPORTED_VERSIONS)},
            ),
        )
    ...

Metadata

  • Branch: bugfix/a2a-version-negotiator-dispatch-wiring
  • Commit Message: fix(a2a): wire A2aVersionNegotiator into dispatch pipeline
  • Milestone: (backlog — see note below)
  • Parent Epic: #933

Backlog note: This issue was discovered during autonomous operation
on milestone v3.7.0. It does not block milestone completion and has been
placed in the backlog for human review and future milestone assignment.


Subtasks

  • TDD step 1: Write a failing Behave scenario in features/ that reproduces the bug (dispatch a request and assert A2aVersionNegotiator.negotiate() is called; assert unsupported versions return a version-mismatch error response)
  • TDD step 2: Verify the new scenario fails as expected (nox -s unit_tests)
  • Wire A2aVersionNegotiator into A2aLocalFacade.dispatch() — call negotiate() before _route_operation()
  • Handle A2aVersionMismatchError and return a structured A2aResponse with error detail (do not let it propagate as an unhandled exception)
  • Make the failing Behave scenario pass (nox -s unit_tests)
  • Add Robot Framework integration test in robot/ covering version negotiation in the dispatch path
  • Verify coverage ≥ 97% via nox -s coverage_report
  • Run nox (all default sessions), fix any errors

Definition of Done

This issue is complete when:

  • All subtasks above are completed and checked off.
  • A failing Behave test is committed and merged before the fix (mandatory TDD workflow for bug fixes per CONTRIBUTING.md).
  • A Git commit is created where the first line of the commit message matches the Commit Message in Metadata exactly (fix(a2a): wire A2aVersionNegotiator into dispatch pipeline), followed by a blank line, then additional lines providing relevant details about the implementation.
  • The commit is pushed to the remote on the branch matching the Branch in Metadata exactly (bugfix/a2a-version-negotiator-dispatch-wiring).
  • The commit is submitted as a pull request to master, reviewed, and merged before this issue is marked done.
  • All nox stages pass.
  • Coverage >= 97%

Automated by CleverAgents Bot
Supervisor: UAT Testing | Agent: ca-new-issue-creator

## Bug Report **Feature Area:** API Versioning and Backward Compatibility **Severity:** Critical (per UAT report) **Found by:** UAT Testing (automated) --- ## Background and Context The A2A protocol is a versioned standard. The `A2aVersionNegotiator` class exists in `src/cleveragents/a2a/versioning.py` and is exported from the `cleveragents.a2a` package, but it is **never called** during actual A2A request dispatch. This means the version negotiation mechanism is dead code — clients cannot negotiate protocol versions because the negotiator is not wired into the dispatch pipeline. Per the specification, the A2A layer must enforce protocol version compatibility on every inbound request to ensure backward compatibility and to surface clear errors when clients use unsupported protocol versions. ## Current Behavior In `src/cleveragents/a2a/facade.py`, the `dispatch()` method processes `A2aRequest` objects without ever invoking `A2aVersionNegotiator`: ```python def dispatch(self, request: A2aRequest) -> A2aResponse: # No version negotiation here! start = time.monotonic() try: data = self._route_operation(request.method, request.params) ... ``` The `A2aVersionNegotiator` is only referenced in: - `src/cleveragents/a2a/__init__.py` (exported) - `src/cleveragents/a2a/versioning.py` (defined) It is **not used** in: - `src/cleveragents/a2a/facade.py` (dispatch) - `src/cleveragents/a2a/asgi.py` (ASGI server) - `src/cleveragents/a2a/transport.py` (HTTP transport) ## Expected Behavior When a client sends an A2A request, the server should: 1. Extract the requested A2A protocol version from the request 2. Call `A2aVersionNegotiator.negotiate(requested_version)` to validate compatibility 3. Reject requests with unsupported versions by raising `A2aVersionMismatchError` and returning a structured error response ## Acceptance Criteria - [ ] `A2aLocalFacade.dispatch()` calls `A2aVersionNegotiator.negotiate()` on every inbound request before routing - [ ] Requests carrying an unsupported A2A protocol version receive an `A2aResponse` with an `A2aErrorDetail` describing the version mismatch (not an unhandled exception) - [ ] `A2aVersionMismatchError` is reachable via the normal dispatch path (not only by direct calls to the negotiator) - [ ] All existing dispatch behaviour is preserved for requests with supported protocol versions - [ ] All nox stages pass (`nox`) - [ ] Coverage ≥ 97% (`nox -s coverage_report`) ## Supporting Information - Related: #3971 (A2A layer has zero unit tests — critical protocol layer is untested) - Related: #3638 (A2A-Version HTTP header not sent or validated in server mode) - Related: #3533 (ASGI server missing A2A JSON-RPC endpoint) - Code location: `src/cleveragents/a2a/versioning.py` — `A2aVersionNegotiator` class - Code location: `src/cleveragents/a2a/facade.py` — `A2aLocalFacade.dispatch()` method (missing negotiation call) **Suggested Fix:** ```python def dispatch(self, request: A2aRequest) -> A2aResponse: # Negotiate A2A protocol version negotiator = A2aVersionNegotiator() try: negotiator.negotiate(request.jsonrpc) # or a2a_version field except A2aVersionMismatchError as exc: return A2aResponse( id=request.id, error=A2aErrorDetail( code="VERSION_MISMATCH", message=str(exc), details={"supported": list(negotiator.SUPPORTED_VERSIONS)}, ), ) ... ``` --- ## Metadata - **Branch**: `bugfix/a2a-version-negotiator-dispatch-wiring` - **Commit Message**: `fix(a2a): wire A2aVersionNegotiator into dispatch pipeline` - **Milestone**: *(backlog — see note below)* - **Parent Epic**: #933 > **Backlog note:** This issue was discovered during autonomous operation > on milestone v3.7.0. It does not block milestone completion and has been > placed in the backlog for human review and future milestone assignment. --- ## Subtasks - [ ] **TDD step 1:** Write a failing Behave scenario in `features/` that reproduces the bug (dispatch a request and assert `A2aVersionNegotiator.negotiate()` is called; assert unsupported versions return a version-mismatch error response) - [ ] **TDD step 2:** Verify the new scenario fails as expected (`nox -s unit_tests`) - [ ] Wire `A2aVersionNegotiator` into `A2aLocalFacade.dispatch()` — call `negotiate()` before `_route_operation()` - [ ] Handle `A2aVersionMismatchError` and return a structured `A2aResponse` with error detail (do not let it propagate as an unhandled exception) - [ ] Make the failing Behave scenario pass (`nox -s unit_tests`) - [ ] Add Robot Framework integration test in `robot/` covering version negotiation in the dispatch path - [ ] Verify coverage ≥ 97% via `nox -s coverage_report` - [ ] Run `nox` (all default sessions), fix any errors ## Definition of Done This issue is complete when: - All subtasks above are completed and checked off. - A failing Behave test is committed and merged **before** the fix (mandatory TDD workflow for bug fixes per CONTRIBUTING.md). - A Git commit is created where the **first line** of the commit message matches the Commit Message in Metadata exactly (`fix(a2a): wire A2aVersionNegotiator into dispatch pipeline`), followed by a blank line, then additional lines providing relevant details about the implementation. - The commit is pushed to the remote on the branch matching the **Branch** in Metadata exactly (`bugfix/a2a-version-negotiator-dispatch-wiring`). - The commit is submitted as a **pull request** to `master`, reviewed, and **merged** before this issue is marked done. - All nox stages pass. - Coverage >= 97% --- **Automated by CleverAgents Bot** Supervisor: UAT Testing | Agent: ca-new-issue-creator
HAL9000 added this to the v3.5.0 milestone 2026-04-09 03:11:17 +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#4078
No description provided.