cd /news/artificial-intelligence/can-google-adk-talk-to-microsoft-fou… · home topics artificial-intelligence article
[ARTICLE · art-76028] src=dev.to ↗ pub= topic=artificial-intelligence verified=true sentiment=· neutral

Can Google ADK Talk to Microsoft Foundry on Azure? A Cross-Cloud A2A Benchmark

A developer benchmarked cross-cloud Agent-to-Agent (A2A) interoperability between Microsoft Foundry on Azure and Google ADK on Cloud Run, measuring latency and accuracy of a currency conversion agent. The project revealed a protocol-version skew between the two ecosystems, with the Microsoft A2A client calling v1.0 methods while the Google ADK agent only routed v0.3.0 methods, causing an initial failure. The benchmark also found that Google ADK 2.5.0 is the first release compatible with a2a-sdk 1.x, resolving the dependency conflict.

read7 min views1 publishedJul 27, 2026

This article provides a step-by-step guide to building and testing a

cross-cloud currency agent. A coordinator hosted on Microsoft Foundry in Azure

calls a Google ADK agent on Google Cloud over A2A v1.0, uses an MCP exchange-rate

tool, and records what independent verification costs in latency.

Most Agent-to-Agent (A2A) protocol demos stop at "look, the request succeeded."

That is a smoke test, not an interoperability benchmark. This project goes

further: a Microsoft Agent Framework coordinator, hosted on Microsoft Foundry

in Azure, discovers and delegates to a Google ADK agent running on Cloud Run in

GCP, then measures what that cross-cloud hop actually costs.

The questions, with numbers instead of vibes:

This builds directly on the currency agent from the previous articles in this series:

Getting Started with MCP, ADK and A2A | Google Codelabs

GitHub - xbill9/currency-agent

That agent — ADK, Gemini, a FastMCP exchange-rate server backed by the free Frankfurter API — becomes the remote verifier in this project. The new repo wraps it in a benchmark harness:

GitHub - xbill9/foundry-adk-a2a-currency

You (Responses protocol, Entra ID)
      |
Microsoft Foundry hosted agent          (Azure, eastus2, gpt-5-mini)
Microsoft Agent Framework coordinator
      |
      +-- MCP stdio --> Frankfurter rates      (in-container)
      |
      +-- A2A v1.0 --> Cloud Run               (GCP, us-central1)
                          |
                       Google ADK agent        (gemini-2.5-flash)
                          |
                       MCP HTTP --> Frankfurter rates

The coordinator answers every conversion three ways:

Mode What happens Why it exists
mcp_only
Coordinator calls the rate tool Baseline
a2a_only
Coordinator delegates to the remote ADK agent Measure remote-agent behavior
verified
MCP result independently checked over A2A The accuracy/overhead tradeoff

Both sides read the same Frankfurter daily reference rates on purpose: when the two clouds disagree, that measures protocol and model behavior, not data-source skew.

Currency conversion is a terrible job for an LLM and a great job for Decimal

. The domain layer is framework-independent Python with pydantic models, and agreement is judged by relative numeric difference — no model is ever asked "do these numbers look the same to you?"

difference = abs(primary.converted_amount - verifier.converted_amount)
relative = difference / abs(primary.converted_amount)
agreed = relative <= tolerance  # default 0.005

The failure policy is explicit rather than emergent:

validation

, provider

, authentication

, transport

, timeout

, protocol

). Never fabricate a rate."Which layer broke" is a research question, so every adapter failure is converted into exactly one of those kinds at one boundary.

Here is the headline interoperability lesson. The first attempt to point the Microsoft Agent Framework A2A client at the existing currency agent died instantly:

a2a.utils.errors.MethodNotFoundError: Method not found

Root cause: a clean protocol-version skew with no negotiation.

agent-framework-a2a

, requires a2a-sdk>=1.0

) calls the A2A v1.0 JSON-RPC method SendMessage

.a2a-sdk 0.3.x

) only routes the v0.3.0 method message/send

.protocolVersion: 0.3.0

— and calls the v1.0 method anyway.Worse, the two ecosystems had mutually exclusive dependency pins at the time of writing:

Package a2a-sdk requirement
agent-framework-a2a 1.0.0b260721
>=1.0.0,<2
google-adk 2.1.0 – 2.4.0
>=0.3.4,<0.4
google-adk 2.5.0
>=0.3.4,<2
a2ui-agent-sdk (through 0.4.0)
<0.4.0

google-adk 2.5.0

is the first release that allows a2a-sdk 1.x

— but the A2UI extension from the previous article still pins the old protocol. So the benchmark agent is the currency agent with A2UI removed, pinned to google-adk 2.5.0

  • a2a-sdk 1.1.2

. Separate uv

virtualenvs keep both worlds installable on one machine; the wire protocol is what has to match.

Two more v1.0 observations worth knowing:

url

/protocolVersion

into a supportedInterfaces

array.get_exchange_rate

) as A2A skills on the card — your remote agent's card documents its toolbox for free.After the version alignment, the answer to research question 1 is yes: the Microsoft Agent Framework client consumed the ADK-generated card and delegated over A2A v1.0 with no schema translation beyond prompting the agent to answer in parseable JSON.

Versions observed working (preview software; pin what works, expect drift): Azure Developer CLI 1.28.1

, microsoft.foundry

azd extension 1.0.0-beta.2

, Python 3.13

, agent-framework-core 1.12.1

, agent-framework-foundry 1.10.3

, agent-framework-foundry-hosting 1.0.0b260722

, region eastus2

, model gpt-5-mini

(2025-08-07

, Global Standard).

The entire hosted agent is one file. FoundryChatClient

authenticates with DefaultAzureCredential

— no API keys anywhere on the Azure side — and ResponsesHostServer

exposes it over the Responses protocol:

agent = Agent(
    client=FoundryChatClient(
        project_endpoint=os.environ["FOUNDRY_PROJECT_ENDPOINT"],
        model=os.environ["AZURE_AI_MODEL_DEPLOYMENT_NAME"],
        credential=DefaultAzureCredential(),
    ),
    name="currency-interoperability-coordinator",
    instructions="For every conversion request, call run_currency_benchmark. "
                 "Never calculate or verify arithmetic yourself. ...",
    tools=[run_currency_benchmark],
)
ResponsesHostServer(agent).run()

The adapters behind that tool are selected by environment variables (CURRENCY_A2A_ENDPOINT

, CURRENCY_RATE_PROVIDER

, CURRENCY_RATE_TRANSPORT

, CURRENCY_TIMEOUT_SECONDS

), passed through azure.yaml

. Version 1 shipped with deterministic fixtures; version 2 flipped the env vars and went live without touching code.

The gotcha that will probably bite you too: control-plane roles (Owner/Contributor) are not enough to deploy. The deploying identity also needs the Foundry Project Manager data-plane role (definition eadc314b-1a2d-4efa-be10-5d325db5065e

) at the Foundry account scope.

The benchmark agent container colocates two processes: the FastMCP Frankfurter server on localhost and the A2A app on $PORT

. The Gemini key comes from Secret Manager — never an env literal:

gcloud secrets create gemini-api-key --data-file="$HOME/gemini.key"
gcloud run deploy currency-adk-a2a \
  --source adk_agent --region us-central1 \
  --allow-unauthenticated --min-instances=0 --max-instances=2 \
  --set-secrets "GOOGLE_API_KEY=gemini-api-key:latest" \
  --set-env-vars "MCP_SERVER_URL=http://127.0.0.1:8081/mcp,GENAI_MODEL=gemini-2.5-flash"

--min-instances=0

means the verifier costs nothing while idle. (Ask me how I know to check min-instances

on old GPU services. Actually, don't.)

Everything local runs credential-free on fixtures first:

git clone https://github.com/xbill9/foundry-adk-a2a-currency
cd foundry-adk-a2a-currency
pip3 install --user -e ".[dev]"
pytest                      # 35 deterministic tests, no cloud, no model calls
currency-benchmark 100 USD EUR --mode verified --transport mcp-stdio

To go live locally, start the ADK agent (needs GOOGLE_API_KEY

):

cd adk_agent && uv sync
MCP_SERVER_URL=http://127.0.0.1:8081/mcp uv run uvicorn agent:a2a_app --port 10001

and point the benchmark at it:

CURRENCY_RATE_PROVIDER=frankfurter currency-benchmark 250 GBP USD JPY \
  --mode verified --transport mcp-stdio \
  --a2a-endpoint http://127.0.0.1:10001 --timeout-seconds 60

The full evaluation matrix (fault-free cases live, fault-injection cases deterministic — you cannot order a live agent to time out on demand):

currency-evaluate --a2a-endpoint http://127.0.0.1:10001 --live-rates \
  --output results.jsonl --summary summary.json

The full cross-cloud deployment is one script — Secret Manager, Cloud Run, then azd deploy

:

bash infra/deploy_live.sh

The 38-case matrix (validation, cross-rates, precision, injected timeouts, stale rates, disagreement, malicious tool text) ran in all three modes — 114 records, raw JSONL retained in the repo so every number below is regenerable.

Mode Success Median latency p95 latency
mcp_only
100% 297 ms 1.09 s
a2a_only (live Gemini)
100% 1.69 s 4.82 s
verified (live)
100% 1.71 s 4.15 s

The two numbers I care most about:

On the fully hosted path (Azure coordinator → GCP agent), the remote Foundry endpoint completed all three modes: mcp_only

in 0.71 s, verified

in 2.7 s with agreed: true

and relative_difference: 0

. One warm-path anecdote, not a distribution — repeated warm/cold trials and token/cost accounting are the remaining evaluation work.

a2a-sdk

major version on MethodNotFoundError

is the signature.protocol

failure instead of a silently incomplete answer. Design for partial replies.azd deploy

died with AzureDeveloperCLICredential: signal: killed

and succeeded unchanged on retry. Retry before you bisect.gpt-5-mini

and gemini-2.5-flash

respected "call the tool, never calculate" — and because all math is Decimal

in deterministic code, agreement checks compare numbers, not model prose.Based on what's measured so far: the accuracy delta on the happy path is zero — both paths read the same rates and agree. What you're actually buying for your ~1.4 s is independent failure detection: a second implementation, on a second cloud, that will loudly disagree when a tool is compromised, stale, or wrong. The injected-fault case shows the mechanism works; the malicious-tool-text and hosted-injection cases are where that budget earns its keep. If your tool result feeds a decision that matters, one extra second for a cross-checked answer is cheap. If it's a chatbot rate lookup — mcp_only

at 297 ms is your friend.

Everything — coordinator, benchmark agent, deploy script, evaluation cases, and the raw results behind every table above:

GitHub - xbill9/foundry-adk-a2a-currency

Upstream agent pinned at xbill9/currency-agent@aeef3c4.

If you've wired a Microsoft Agent Framework agent to a Google ADK agent over A2A — especially if you hit card or version mismatches I didn't — I'd genuinely like to hear what broke.

── more in #artificial-intelligence 4 stories · sorted by recency
── more on @microsoft foundry 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/can-google-adk-talk-…] indexed:0 read:7min 2026-07-27 ·