Describe the bug
ClientBuilder#getServerInterfacesMap() builds its list of candidate transports from AgentCard#supportedInterfaces() only:
private Map<String, AgentInterface> getServerInterfacesMap() throws A2AClientException {
List<AgentInterface> interfaces = agentCard.supportedInterfaces();
if (interfaces == null || interfaces.isEmpty()) {
throw new A2AClientException("No server interface available in the AgentCard");
}
...
}
If an AgentCard was produced by an A2A "0.3" server (e.g. anything built on io.a2a.spec.AgentCard from io.github.a2asdk:a2a-java-sdk-reference-jsonrpc, which only has additionalInterfaces/preferredTransport, not supportedInterfaces), Client.builder(agentCard) / ClientBuilder#build() always throws A2AClientException: No server interface available in the AgentCard, even though AgentCard itself models exactly this legacy shape via additionalInterfaces():
private final List<AgentInterface> supportedInterfaces;
private final List<Legacy_0_3_AgentInterface> additionalInterfaces;
...
public List<AgentInterface> supportedInterfaces();
public List<Legacy_0_3_AgentInterface> additionalInterfaces();
Since Legacy_0_3_AgentInterface exists specifically to deserialize the older additionalInterfaces/preferredTransport shape, I'd expect ClientBuilder to fall back to it (converting each Legacy_0_3_AgentInterface + the card's preferredTransport into an AgentInterface) when supportedInterfaces is absent, so that clients built against the current SDK can still talk to agents that only publish a 0.3-style card.
How to reproduce
- Stand up any A2A server that only serves a 0.3-style card, e.g.:
{
"name": "Summarizer Agent",
"url": "http://localhost:10010",
"version": "1.0.0",
"capabilities": {"streaming": false, "pushNotifications": false, "stateTransitionHistory": false},
"defaultInputModes": ["text"],
"defaultOutputModes": ["text"],
"skills": [...],
"additionalInterfaces": [{"transport": "JSONRPC", "url": "http://localhost:10010"}],
"preferredTransport": "JSONRPC",
"protocolVersion": "0.3.0"
}
(this is exactly what io.a2a.spec.AgentCard.Builder from a2a-java-sdk-reference-jsonrpc 0.3.0.Beta1/0.3.2.Final produces — there's no supportedInterfaces() builder method on that class at all, so no 0.3-based server can add it)
AgentCard card = A2A.getAgentCard("http://localhost:10010");
Client.builder(card).withTransport(JSONRPCTransport.class, new JSONRPCTransportConfigBuilder()).build();
- Observe
A2AClientException: No server interface available in the AgentCard, even though the server is reachable and does support JSON-RPC.
I confirmed via a minimal Jackson round-trip that a supportedInterfaces entry must use the field name protocolBinding (not transport) to deserialize into AgentInterface, and that capabilities.stateTransitionHistory (present on all 0.3-style cards) is silently ignored rather than rejected — so the parsing itself is otherwise lenient, it's specifically this transport-selection step that has no legacy fallback.
Expected behavior
ClientBuilder should be able to build a working client against an agent that only publishes a 0.3-style card (additionalInterfaces + preferredTransport), by falling back to AgentCard#additionalInterfaces() (converting Legacy_0_3_AgentInterface → AgentInterface, using preferredTransport() to pick the client's preferred one) when supportedInterfaces() is null/empty.
Context
Found this while wiring up langchain4j-agentic-a2a's AgenticServices.a2aBuilder(url) (used by quarkus-langchain4j-a2a-apicurio-registry's ApicurioAgentsRegistry) against real A2A agents built with a2a-java-sdk-reference-jsonrpc 0.3.0.Beta1/0.3.2.Final for a demo project (https://github.com/carlesarnal/agent-discovery-demo). As things stand, no agent built on the "0.3" reference server can be reached by any client built on the current org.a2aproject.sdk Client/ClientBuilder, regardless of how the client obtains the AgentCard.
Describe the bug
ClientBuilder#getServerInterfacesMap()builds its list of candidate transports fromAgentCard#supportedInterfaces()only:If an
AgentCardwas produced by an A2A "0.3" server (e.g. anything built onio.a2a.spec.AgentCardfromio.github.a2asdk:a2a-java-sdk-reference-jsonrpc, which only hasadditionalInterfaces/preferredTransport, notsupportedInterfaces),Client.builder(agentCard)/ClientBuilder#build()always throwsA2AClientException: No server interface available in the AgentCard, even thoughAgentCarditself models exactly this legacy shape viaadditionalInterfaces():Since
Legacy_0_3_AgentInterfaceexists specifically to deserialize the olderadditionalInterfaces/preferredTransportshape, I'd expectClientBuilderto fall back to it (converting eachLegacy_0_3_AgentInterface+ the card'spreferredTransportinto anAgentInterface) whensupportedInterfacesis absent, so that clients built against the current SDK can still talk to agents that only publish a 0.3-style card.How to reproduce
{ "name": "Summarizer Agent", "url": "http://localhost:10010", "version": "1.0.0", "capabilities": {"streaming": false, "pushNotifications": false, "stateTransitionHistory": false}, "defaultInputModes": ["text"], "defaultOutputModes": ["text"], "skills": [...], "additionalInterfaces": [{"transport": "JSONRPC", "url": "http://localhost:10010"}], "preferredTransport": "JSONRPC", "protocolVersion": "0.3.0" }io.a2a.spec.AgentCard.Builderfroma2a-java-sdk-reference-jsonrpc0.3.0.Beta1/0.3.2.Final produces — there's nosupportedInterfaces()builder method on that class at all, so no 0.3-based server can add it)AgentCard card = A2A.getAgentCard("http://localhost:10010");Client.builder(card).withTransport(JSONRPCTransport.class, new JSONRPCTransportConfigBuilder()).build();A2AClientException: No server interface available in the AgentCard, even though the server is reachable and does support JSON-RPC.I confirmed via a minimal Jackson round-trip that a
supportedInterfacesentry must use the field nameprotocolBinding(nottransport) to deserialize intoAgentInterface, and thatcapabilities.stateTransitionHistory(present on all 0.3-style cards) is silently ignored rather than rejected — so the parsing itself is otherwise lenient, it's specifically this transport-selection step that has no legacy fallback.Expected behavior
ClientBuildershould be able to build a working client against an agent that only publishes a 0.3-style card (additionalInterfaces+preferredTransport), by falling back toAgentCard#additionalInterfaces()(convertingLegacy_0_3_AgentInterface→AgentInterface, usingpreferredTransport()to pick the client's preferred one) whensupportedInterfaces()is null/empty.Context
Found this while wiring up
langchain4j-agentic-a2a'sAgenticServices.a2aBuilder(url)(used byquarkus-langchain4j-a2a-apicurio-registry'sApicurioAgentsRegistry) against real A2A agents built witha2a-java-sdk-reference-jsonrpc0.3.0.Beta1/0.3.2.Final for a demo project (https://github.com/carlesarnal/agent-discovery-demo). As things stand, no agent built on the "0.3" reference server can be reached by any client built on the currentorg.a2aproject.sdkClient/ClientBuilder, regardless of how the client obtains theAgentCard.