Build1 publisher3 min readPublished
A2A holds on the wire. ADK, Strands and Agent Framework are still not substitutable.
One research agent, built three times on three hyperscaler frameworks with the same prompt and the same search tool, diverged in nine ways. None of them were protocol problems.
The Engineer · Build desk
Drafted by a language model from the sources cited here and checked against its claim ledger before publication. How we use AISend a correction

What happened
- The author built the same agent three times - one research agent, one instruction, one search tool, one word budget - on Google ADK, AWS Strands and Microsoft Agent Framework, hosted on each vendor's own runtime, and had one coordinator fan the same brief out to all three and score what came back.
- A2A worked; the article is about the nine other things that differ once it does.
- The A2A interoperability claim is true on the wire, and the wire is not the whole job.
- All three hyperscalers now ship an agent framework, and all three speak A2A.
- The A2A protocol page states: "In a world where agents are built using diverse frameworks and by different vendors, A2A provides the definitive common language for agent interoperability."
Compiled by The EngineerSomething wrong?How this is made
Why it matters
A developer writing at dev.to built the same research agent three times, on Google ADK, AWS Strands and Microsoft Agent Framework, each hosted on its own vendor's runtime, with one instruction, one search tool and one word budget, then had a single coordinator fan the identical brief to all three and score what came back [1]. A2A carried the traffic; by the author's count nine other things diverged, and they live in the runtime contract each framework imposes rather than in the protocol [2].
The A2A page's claim is that in a world of diverse frameworks and vendors, "A2A provides the definitive common language for agent interoperability" [4]. All three hyperscalers ship an agent framework and all three speak it [3]. The author's reading is narrower and more useful: that is true on the wire, and the wire is not the whole job [c2b].
Much of the value here is the experimental hygiene, which is rarely stated out loud. The rule was to share everything that is not the variable under test [6]. A first attempt produced three SDKs and three green ticks and taught nothing, because when three columns differ in nine ways no result can be attributed to any of them [7]. That forces a separation almost nobody makes: what differs because of the platform, and what differs because of the model [5].
Hence the contested decision. All three clouds got the same search function rather than each vendor's native one, and the author says it is the choice he would defend hardest [8]. Only Google ships a ready search tool [9]. Microsoft's Agent Framework exports SupportsWebSearchTool, which the author describes as a protocol a chat client may declare rather than a tool you can hand an agent, and Foundry's own grounding wants a Bing resource connection created out of band [10]. Strands bundles none at all [11]. Native search everywhere would have meant Gemini grounded against Google's index, a Foundry model against Bing and Bedrock against nothing, which reports the gap between three retrieval products as a gap between three models [12].
What is left varying is construction, and construction is where substitutability dies. ADK's LlmAgent takes the model as a string, "gemini-2.5-flash", the prompt as `instruction`, and a plain callable in `tools` [13]. Strands takes a model object, BedrockModel(model_id="us.amazon.nova-micro-v1:0"), the prompt as `system_prompt`, and a tool explicitly decorated with @tool [14]. Agent Framework takes a chat client, FoundryChatClient holding a project endpoint, a model id and a DefaultAzureCredential, and the prompt as `instructions`, plural [15]. Three names for the system prompt, three levels at which the model is named, three tool conventions [16]. The author's conclusion is that none of it is hard and all of it is untranslatable, and that every attempt at an adapter produced a fourth thing to maintain which then became what was actually under test [17].
The difference with the longest tail is the boundary. Strands hands back a function, so anything else can wrap it from outside [18]. ADK's to_a2a() serialises an agent's event stream and Agent Framework's A2AExecutor calls the agent itself, so neither gives a prompt-to-reply seam; anything you need between the model and the wire has to be done inside that framework's object model, a BaseAgent wrapping the first agent on one cloud and a delegating class implementing run on the other [19]. Two of the three, on this evidence, make middleware their object model's problem rather than yours [22]. The practical advice that follows is to share the prompt, the tool and the wire format, and not to try to share the agent [23].
Worth watching: whether ADK or Agent Framework ever exposes a supported callable boundary, and whether anyone repeats this run with vendor-native retrieval so the retrieval gap can be measured separately from the model gap [12]. The code is published, which makes both checkable rather than arguable [20].