feat(a2a): implement A2A stdio transport for local mode #713

Closed
freemo wants to merge 3 commits from feature/m9-a2a-stdio into master
Owner

Summary

Implements the A2A stdio transport for local mode per the specification (§Architecture > Transport Modes), enabling the CLI to communicate with agent subprocesses via JSON-RPC 2.0 messages over stdin/stdout.

Closes #691

Changes

New modules in src/cleveragents/a2a/

  • transport_protocol.pyA2aTransport Protocol defining the transport interface (send, send_stream, close) that both stdio and HTTP transports implement
  • stdio_transport.pyA2aStdioTransport class implementing:
    • Subprocess launch and lifecycle management (spawn, monitor, terminate)
    • JSON-RPC 2.0 message framing over stdin/stdout (newline-delimited JSON)
    • Request/response correlation via JSON-RPC id field
    • Graceful shutdown with configurable timeout
    • Error handling for subprocess crashes and malformed responses
  • transport_selector.pyTransportSelector class that picks A2aStdioTransport when no server.url is configured (local mode) or A2aRemoteTransport when a server URL is present (server mode)

Test files

  • features/a2a_stdio_transport.feature + step definitions — BDD tests for subprocess lifecycle, message framing, and error handling
  • features/fixtures/echo_agent.py — Minimal echo agent fixture for stdio transport testing
  • robot/a2a_stdio_transport.robot + helper — Integration tests for end-to-end stdio communication

Quality Checks

  • nox -e typecheck — 0 Pyright errors
  • nox -e lint — all checks passed
  • nox -e format — all files unchanged
## Summary Implements the A2A stdio transport for local mode per the specification (§Architecture > Transport Modes), enabling the CLI to communicate with agent subprocesses via JSON-RPC 2.0 messages over stdin/stdout. Closes #691 ## Changes ### New modules in `src/cleveragents/a2a/` - **`transport_protocol.py`** — `A2aTransport` Protocol defining the transport interface (`send`, `send_stream`, `close`) that both stdio and HTTP transports implement - **`stdio_transport.py`** — `A2aStdioTransport` class implementing: - Subprocess launch and lifecycle management (spawn, monitor, terminate) - JSON-RPC 2.0 message framing over stdin/stdout (newline-delimited JSON) - Request/response correlation via JSON-RPC `id` field - Graceful shutdown with configurable timeout - Error handling for subprocess crashes and malformed responses - **`transport_selector.py`** — `TransportSelector` class that picks `A2aStdioTransport` when no `server.url` is configured (local mode) or `A2aRemoteTransport` when a server URL is present (server mode) ### Test files - `features/a2a_stdio_transport.feature` + step definitions — BDD tests for subprocess lifecycle, message framing, and error handling - `features/fixtures/echo_agent.py` — Minimal echo agent fixture for stdio transport testing - `robot/a2a_stdio_transport.robot` + helper — Integration tests for end-to-end stdio communication ## Quality Checks - `nox -e typecheck` — 0 Pyright errors - `nox -e lint` — all checks passed - `nox -e format` — all files unchanged
refactor(a2a): rename ACP module and symbols to A2A standard
All checks were successful
CI / benchmark-publish (pull_request) Has been skipped
CI / lint (pull_request) Successful in 20s
CI / build (pull_request) Successful in 16s
CI / quality (pull_request) Successful in 35s
CI / security (pull_request) Successful in 47s
CI / typecheck (pull_request) Successful in 1m37s
CI / integration_tests (pull_request) Successful in 3m38s
CI / unit_tests (pull_request) Successful in 4m44s
CI / docker (pull_request) Successful in 1m6s
CI / coverage (pull_request) Successful in 5m30s
CI / benchmark-regression (pull_request) Successful in 35m37s
2fe95d1b38
Renamed src/cleveragents/acp/ to src/cleveragents/a2a/ and all 13
Acp* classes to A2a* per ADR-047 (A2A Standard Adoption). Updated
all imports, structlog event names (acp.* → a2a.*), field names
(acp_version → a2a_version), and test references across the entire
codebase. This is a cosmetic rename only — no behavioral changes.

ISSUES CLOSED: #688
feat(a2a): implement JSON-RPC 2.0 wire format and method routing
All checks were successful
CI / benchmark-publish (pull_request) Has been skipped
CI / lint (pull_request) Successful in 14s
CI / build (pull_request) Successful in 16s
CI / quality (pull_request) Successful in 18s
CI / security (pull_request) Successful in 35s
CI / typecheck (pull_request) Successful in 55s
CI / unit_tests (pull_request) Successful in 2m57s
CI / integration_tests (pull_request) Successful in 3m23s
CI / docker (pull_request) Successful in 41s
CI / coverage (pull_request) Successful in 5m36s
CI / benchmark-regression (pull_request) Successful in 35m11s
33900eab03
Implement the JSON-RPC 2.0 wire format layer and method routing for the
A2A protocol, building on the ACP-to-A2A rename from #688.

New modules in src/cleveragents/a2a/:
- jsonrpc_models.py: Pydantic v2 models for JSON-RPC 2.0 request,
  response, error, and notification envelopes
- jsonrpc_router.py: Method router that dispatches JSON-RPC requests
  to registered handlers, with support for standard A2A methods and
  _cleveragents/ extension methods
- jsonrpc_handlers.py: Handlers for standard A2A methods (message/send,
  message/stream, tasks/get, tasks/cancel) and extension method factory
  that delegates to A2aLocalFacade
- jsonrpc_errors.py: Maps domain error taxonomy to JSON-RPC 2.0 error
  codes (standard -32700 to -32603, application -32001 to -32008)
- agent_card.py: Agent Card model and generation for the
  /.well-known/agent.json capability advertisement endpoint

Standard A2A methods:
- message/send: Create/update tasks via messages
- message/stream: Streaming variant with SSE event indicators
- tasks/get: Retrieve task by ID
- tasks/cancel: Cancel running tasks

CleverAgents extension methods (_cleveragents/ prefix):
- plan/use, execute, status, diff, apply, cancel
- registry/list_tools, list_resources
- context/show
- sync/status
- namespace/list
- health

Tests:
- Behave BDD: features/a2a_jsonrpc.feature (28 scenarios)
- Robot Framework: robot/a2a_jsonrpc.robot (9 integration tests)

ISSUES CLOSED: #690
feat(a2a): implement A2A stdio transport for local mode
All checks were successful
CI / benchmark-publish (pull_request) Has been skipped
CI / lint (pull_request) Successful in 15s
CI / build (pull_request) Successful in 19s
CI / quality (pull_request) Successful in 19s
CI / security (pull_request) Successful in 36s
CI / typecheck (pull_request) Successful in 38s
CI / unit_tests (pull_request) Successful in 3m0s
CI / integration_tests (pull_request) Successful in 3m27s
CI / docker (pull_request) Successful in 41s
CI / coverage (pull_request) Successful in 5m31s
CI / benchmark-regression (pull_request) Successful in 35m39s
680cc8c352
Add A2aStdioTransport class that manages subprocess lifecycle and
communicates via newline-delimited JSON-RPC 2.0 messages over
stdin/stdout. Add A2aTransport protocol (typing.Protocol) defining
the abstract transport interface. Add A2aTransportSelector that
picks A2aStdioTransport in local mode (no server URL) or
A2aHttpTransport in server mode.

New files:
- transport_protocol.py: A2aTransport Protocol
- stdio_transport.py: A2aStdioTransport with subprocess management
- transport_selector.py: A2aTransportSelector configuration-based
- echo_agent.py: Minimal echo agent fixture for tests

Tests:
- 20 Behave BDD scenarios covering protocol conformance, construction,
  subprocess lifecycle, send/receive, context manager, transport
  selector, and contract round-trip tests
- 7 Robot Framework integration tests with helper script

ISSUES CLOSED: #691
freemo added this to the v3.8.0 milestone 2026-03-12 01:53:06 +00:00
freemo self-assigned this 2026-03-12 20:33:29 +00:00
Author
Owner

PM Status — Day 32

State: CONFLICTED — needs rebase onto master.

Priority: Low — M9 (v3.8.0), no deadline. Current focus should be M3-M6.

Dependencies: Depends on #708 (JSON-RPC wire format) being merged first. #722 (LangGraph Platform) depends on this.

File overlap with #720: Both this PR and #720 (HTTP transport) independently create transport_protocol.py and transport_selector.py. This PR should be merged before #720, then #720 rebases to reconcile.

Missing labels: Adding Priority/Low, MoSCoW/Could have, Points/13, State/In Progress.

@freemo — No immediate action needed. Rebase after #708 is merged, which itself should wait until higher-priority work is done.

### PM Status — Day 32 **State:** CONFLICTED — needs rebase onto master. **Priority:** Low — M9 (v3.8.0), no deadline. Current focus should be M3-M6. **Dependencies:** Depends on #708 (JSON-RPC wire format) being merged first. #722 (LangGraph Platform) depends on this. **File overlap with #720:** Both this PR and #720 (HTTP transport) independently create `transport_protocol.py` and `transport_selector.py`. This PR should be merged before #720, then #720 rebases to reconcile. **Missing labels:** Adding Priority/Low, MoSCoW/Could have, Points/13, State/In Progress. @freemo — No immediate action needed. Rebase after #708 is merged, which itself should wait until higher-priority work is done.
Author
Owner

Rebase Required

@freemo — This PR has merge conflicts with master. Please rebase onto the latest master and force-push. See also: #668, #669, #703, #708, #720, #722 (all need rebase).

## Rebase Required @freemo — This PR has merge conflicts with `master`. Please rebase onto the latest `master` and force-push. See also: #668, #669, #703, #708, #720, #722 (all need rebase).
Author
Owner

PM Review — Day 34

Status: NOT mergeable (conflicts), 0 reviews, M9 (v3.8.0), Priority/Low, Points/13
Author: @freemo

A2A stdio transport for local mode. M9 — lowest urgency. Rebase deferred.

Action Items

Who Action Deadline
@freemo Rebase when M9 sprint begins M9 sprint
## PM Review — Day 34 **Status**: NOT mergeable (conflicts), 0 reviews, M9 (v3.8.0), Priority/Low, Points/13 **Author**: @freemo A2A stdio transport for local mode. M9 — lowest urgency. Rebase deferred. ### Action Items | Who | Action | Deadline | |-----|--------|----------| | @freemo | Rebase when M9 sprint begins | M9 sprint |
Author
Owner

PM Status — Day 36 (2026-03-16)

Confirmed deferred status. M8/M9 rebase and review deferred until M3-M6 queue clears. No action required at this time.

Next check: Day 40 or when M6 work is substantially complete.

## PM Status — Day 36 (2026-03-16) Confirmed deferred status. M8/M9 rebase and review deferred until M3-M6 queue clears. No action required at this time. **Next check**: Day 40 or when M6 work is substantially complete.
freemo left a comment

PM Day 36: A2A stdio transport for local mode. M9 scope (deferred). @freemo author.

PM Day 36: A2A stdio transport for local mode. M9 scope (deferred). @freemo author.
Author
Owner

This feature is for a later version, so closing it and will do it at the appropriate time.

This feature is for a later version, so closing it and will do it at the appropriate time.
freemo closed this pull request 2026-03-16 22:34:50 +00:00
All checks were successful
CI / benchmark-publish (pull_request) Has been skipped
CI / lint (pull_request) Successful in 15s
Required
Details
CI / build (pull_request) Successful in 19s
Required
Details
CI / quality (pull_request) Successful in 19s
Required
Details
CI / security (pull_request) Successful in 36s
Required
Details
CI / typecheck (pull_request) Successful in 38s
Required
Details
CI / unit_tests (pull_request) Successful in 3m0s
Required
Details
CI / integration_tests (pull_request) Successful in 3m27s
Required
Details
CI / docker (pull_request) Successful in 41s
Required
Details
CI / coverage (pull_request) Successful in 5m31s
Required
Details
CI / benchmark-regression (pull_request) Successful in 35m39s

Pull request closed

Sign in to join this conversation.
No reviewers
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!713
No description provided.