| name | fix-tck-issue |
| description | Analyzes and fixes A2A Transport Compatibility Kit (TCK) issues by understanding the specification, reproducing the failure, implementing the fix, and validating it works. |
| compatibility | Requires gh CLI and mvn |
| allowed-tools | Bash(gh:*) Bash(mvn:*) Bash(git:*) Bash(curl:*) Read Edit Write Glob Grep WebFetch |
Fix A2A TCK Compatibility Issue
Triggers
- Issue references TCK, compatibility, or transport-specific behavior
- Keywords: "TCK", "compatibility", "HTTP+JSON", "gRPC", "JSON-RPC", "specification", "proto"
- Issue mentions transport layer discrepancies
Input
- Issue number from a2aproject/a2a-java repository
- Optional: A2A spec reference (branch/tag/commit, defaults to
main)
Workflow
1. Fetch Issue Details
gh issue view <issue-number> --repo a2aproject/a2a-java --json title,body,labels,url
Parse issue to identify:
- Affected transport(s): HTTP+JSON, gRPC, JSON-RPC
- Expected behavior from specification
- Actual behavior (error message, reproducer)
- Specification section references
- Spec commit checksum (TCK issues include this in spec URLs)
2. Read Specification (if needed)
TCK issues contain the spec checksum, but reading the spec is helpful if TCK lags behind or for additional context.
Fetch from https://github.com/a2aproject/A2A with specified ref (use checksum from issue or default to main):
specification/grpc/a2a.proto - for proto definitions and HTTP transcoding
docs/specification.md - for detailed protocol requirements
Focus on sections referenced in the issue.
3. Analyze Code
Locate relevant code based on transport:
- HTTP+JSON:
transport/rest
- gRPC:
transport/grpc
- JSON-RPC:
transport/jsonrpc
Identify root cause by comparing:
- What the spec says should happen
- What the code currently does
- Why they differ
Optional: If issue includes a curl/grpcurl reproducer, run it manually to validate the issue is genuine.
4. Determine Affected Transports
CRITICAL: If issue doesn't specify a single transport, you MUST create reproducers for ALL affected transports.
Issue mentions specific transport → Test that one only
Issue generic or mentions "all transports" → Test HTTP+JSON, gRPC, AND JSON-RPC
5. Create Temporary Reproducer(s)
Create test in appropriate module. Choose location based on test complexity:
Option A: transport/ modules (Unit Tests)* - Use when:
- Testing handler logic directly
- Need custom AgentCard configuration (e.g., capability flags)
- Simpler to set up specific test conditions
- HTTP+JSON →
transport/rest/src/test/java/org/a2aproject/sdk/transport/rest/handler/RestHandlerTest.java
- gRPC →
transport/grpc/src/test/java/org/a2aproject/sdk/transport/grpc/handler/GrpcHandlerTest.java
- JSON-RPC →
transport/jsonrpc/src/test/java/org/a2aproject/sdk/transport/jsonrpc/handler/JSONRPCHandlerTest.java
Option B: reference/ modules (Integration Tests)* - Use when:
- Testing full request/response cycle
- Need real server behavior
- Testing with standard agent configuration
- HTTP+JSON →
reference/rest/src/test/java/.../
- gRPC →
reference/grpc/src/test/java/.../
- JSON-RPC →
reference/jsonrpc/src/test/java/.../
Reproducer requirements:
- Follow the exact scenario from the issue
- Use request format per specification (e.g., NO taskId in body for HTTP+JSON)
- Be named clearly:
test_Issue<number>_Reproducer()
- Assert the WRONG behavior that issue reports (should fail)
Example:
@Test
public void test_Issue732_Reproducer() {
String requestBody = """
{
"id": "my-config-001",
"url": "https://example.com/webhook"
}""";
HTTPRestResponse response = handler.createTaskPushNotificationConfiguration(
context, "", requestBody, taskId);
assertEquals(201, response.getStatusCode());
}
6. Run Reproducer(s) - Confirm Failure
CRITICAL: You MUST run the reproducer and see it FAIL before proceeding to fix.
For transport/* modules:
mvn test -Dtest=<TestClass>#test_Issue<number>_Reproducer -pl transport/<transport>
For reference/* modules:
mvn test -Dtest=<TestClass>#test_Issue<number>_Reproducer -pl reference/<transport>
Required verification (DO NOT SKIP):
- ❌ Test MUST fail with the exact error mentioned in the issue
- ❌ Error message, status code, or exception type MUST match issue description
- ❌ If testing multiple transports, ALL reproducers must fail
If reproducer doesn't fail as expected:
- STOP - Do not proceed to fix
- Reassess understanding of the issue
- Check if test conditions match issue scenario
- Verify you're testing the right transport/endpoint
Only proceed to step 7 after confirming all reproducers fail correctly.
7. Implement Fix
Make minimal code changes to fix the root cause.
If multiple transports are affected: Fix ALL of them before proceeding to verification.
Common patterns:
- Missing path parameter extraction: Add
builder.setFieldName(pathParam)
- Wrong validation: Adjust validation logic to match spec
- Incorrect mapping: Fix proto/domain conversion
- Wrong error type: Return correct error based on failure reason
8. Run Reproducer(s) - Confirm Fix
Run ALL reproducers you created in step 5.
For transport/* modules:
mvn test -Dtest=<TestClass>#test_Issue<number>_Reproducer -pl transport/<transport>
For reference/* modules:
mvn test -Dtest=<TestClass>#test_Issue<number>_Reproducer -pl reference/<transport>
Required verification:
- ✅ ALL reproducers must now PASS
- ✅ Test output shows expected behavior (correct status, no error, etc.)
If any reproducer still fails, debug and refine the fix.
9. Verify Backward Compatibility
Run full test suite for ALL modified transport modules to ensure no regressions:
mvn test -pl transport/rest,transport/jsonrpc,transport/grpc
If you also modified reference modules or only created reproducers there:
mvn test -pl reference/rest,reference/jsonrpc,reference/grpc
All existing tests must pass.
10. Delete Temporary Reproducer(s)
Remove ALL test methods or files created in step 5.
If you added a method to existing test class:
- Delete just the
test_Issue<number>_Reproducer() method
If you created a new test file:
- Delete the entire file (e.g.,
Issue733ReproducerTest.java)
11. Commit
Add only the impacted files (NOT the temporary reproducers):
git add <changed-files>
git commit -m "fix: <concise description>
<explanation of spec requirement and how code was fixed>
Applied to <list transports if multiple>.
Fixes #<issue-number>"
Example for multi-transport fix:
git add transport/rest/src/main/java/org/a2aproject/sdk/transport/rest/handler/RestHandler.java \
transport/jsonrpc/src/main/java/org/a2aproject/sdk/transport/jsonrpc/handler/JSONRPCHandler.java \
transport/grpc/src/main/java/org/a2aproject/sdk/transport/grpc/handler/GrpcHandler.java
git commit -m "fix: Return UnsupportedOperationError when capability is disabled
Applied to all three transports: HTTP+JSON, JSON-RPC, and gRPC.
Fixes #733"
Common Root Causes
HTTP+JSON with body: "*"
Proto definition with path parameters and body: "*" means:
- Path parameters extracted from URL
- Body contains remaining fields only
- Handler must set path params into builder
Example proto:
rpc CreateTaskPushNotificationConfig(...) {
option (google.api.http) = {
post: "/tasks/{task_id}/pushNotificationConfigs"
body: "*"
};
}
Fix pattern:
builder.setTaskId(taskId);
Field Validation Errors
"X is required" errors often mean:
- Field should come from URL path, not body
- Handler isn't setting the path parameter
- Check proto's HTTP annotation
Test Location Decision Guide
transport/* modules (Unit Tests)
Best for:
- Testing handler logic with custom configurations
- Issues requiring specific AgentCard capabilities (e.g., streaming=false, extendedAgentCard=false)
- Faster test execution
- More control over test setup
Test file locations:
transport/rest/src/test/java/org/a2aproject/sdk/transport/rest/handler/RestHandlerTest.java
transport/grpc/src/test/java/org/a2aproject/sdk/transport/grpc/handler/GrpcHandlerTest.java
transport/jsonrpc/src/test/java/org/a2aproject/sdk/transport/jsonrpc/handler/JSONRPCHandlerTest.java
reference/* modules (Integration Tests)
Best for:
- Testing full request/response cycles
- Issues related to server behavior
- Testing with standard agent configuration
- Real-world scenario validation
Structure:
reference/
├── rest/ # HTTP+JSON integration tests
├── grpc/ # gRPC integration tests
└── jsonrpc/ # JSON-RPC integration tests
Examples
Example 1: Single Transport Issue
Issue #732: CreateTaskPushNotificationConfig required taskId in body (HTTP+JSON only)
- ✅ Fetched issue - HTTP+JSON transport, expects taskId from URL
- Issue references spec @
0833a5f5fd1b715519c0aecf9e3055e3f9f38089
- ✅ Read spec -
body: "*" means taskId from path
- ✅ Found root cause - RestHandler wasn't setting taskId from path param
- ✅ Issue specifies HTTP+JSON only - test only that transport
- ✅ Created reproducer in reference/rest without taskId in body
- ✅ Ran reproducer - CONFIRMED FAILURE with 422 status
- ✅ Fixed - added
builder.setTaskId(taskId) to RestHandler
- ✅ Ran reproducer - CONFIRMED PASS
- ✅ Ran full test suite - all tests pass
- ✅ Deleted reproducer
- ✅ Committed (RestHandler.java only)
Example 2: Multi-Transport Issue
Issue #733: GetExtendedAgentCard returns wrong error when capability disabled
- ✅ Fetched issue - affects all transports (not specified which)
- Issue references spec @
0833a5f5fd1b715519c0aecf9e3055e3f9f38089
- ✅ Read spec - should return UnsupportedOperationError when capability=false
- ✅ Found root cause - handlers check config before capability
- ✅ Issue affects all transports - must test all three
- ✅ Created reproducers in transport/rest, transport/jsonrpc, transport/grpc
- ✅ Ran all reproducers - CONFIRMED all fail (wrong error type)
- ✅ Fixed all three handlers - check capability before config
- ✅ Ran all reproducers - CONFIRMED all pass
- ✅ Ran full test suite - all tests pass
- ✅ Deleted all three reproducers
- ✅ Committed (all three handler files)
Critical Success Factors
Must Do
- ✅ ALWAYS run reproducer BEFORE fixing - Confirms you understand the issue
- ✅ Test ALL affected transports - Don't assume single transport unless issue specifies
- ✅ Confirm exact failure - Error type, status code, message must match issue
- ✅ Verify fix with reproducers - All must pass before proceeding
- ✅ Delete all reproducers - Keep test suites clean
Best Practices
- a2a.proto and spec are source of truth for compatibility
- Reproducers prove understanding before fixing
- Minimal, targeted fixes are better than broad changes
- Choose test location (transport/* vs reference/*) based on requirements
- Run full test suite to ensure no regressions
- Commit only code changes, never temporary reproducers
Common Pitfalls
- ❌ Fixing without running reproducer first
- ❌ Testing only one transport when issue affects multiple
- ❌ Not confirming exact error before proceeding
- ❌ Committing temporary reproducer tests
- ❌ Skipping backward compatibility verification