{"slug": "can-google-adk-talk-to-microsoft-foundry-on-azure-a-cross-cloud-a2a-benchmark", "title": "Can Google ADK Talk to Microsoft Foundry on Azure? A Cross-Cloud A2A Benchmark", "summary": "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.", "body_md": "This article provides a step-by-step guide to building and testing a\n\ncross-cloud currency agent. A coordinator hosted on Microsoft Foundry in Azure\n\ncalls a Google ADK agent on Google Cloud over A2A v1.0, uses an MCP exchange-rate\n\ntool, and records what independent verification costs in latency.\n\nMost Agent-to-Agent (A2A) protocol demos stop at \"look, the request succeeded.\"\n\nThat is a smoke test, not an interoperability benchmark. This project goes\n\nfurther: a Microsoft Agent Framework coordinator, hosted on Microsoft Foundry\n\nin Azure, discovers and delegates to a Google ADK agent running on Cloud Run in\n\nGCP, then measures what that cross-cloud hop actually costs.\n\nThe questions, with numbers instead of vibes:\n\nThis builds directly on the currency agent from the previous articles in this series:\n\n[Getting Started with MCP, ADK and A2A | Google Codelabs](https://codelabs.developers.google.com/codelabs/currency-agent#0)\n\n[GitHub - xbill9/currency-agent](https://github.com/xbill9/currency-agent)\n\nThat agent — ADK, Gemini, a FastMCP exchange-rate server backed by the free [Frankfurter API](https://www.frankfurter.dev/) — becomes the *remote verifier* in this project. The new repo wraps it in a benchmark harness:\n\n[GitHub - xbill9/foundry-adk-a2a-currency](https://github.com/xbill9/foundry-adk-a2a-currency)\n\n```\nYou (Responses protocol, Entra ID)\n      |\nMicrosoft Foundry hosted agent          (Azure, eastus2, gpt-5-mini)\nMicrosoft Agent Framework coordinator\n      |\n      +-- MCP stdio --> Frankfurter rates      (in-container)\n      |\n      +-- A2A v1.0 --> Cloud Run               (GCP, us-central1)\n                          |\n                       Google ADK agent        (gemini-2.5-flash)\n                          |\n                       MCP HTTP --> Frankfurter rates\n```\n\nThe coordinator answers every conversion three ways:\n\n| Mode | What happens | Why it exists |\n|---|---|---|\n`mcp_only` |\nCoordinator calls the rate tool | Baseline |\n`a2a_only` |\nCoordinator delegates to the remote ADK agent | Measure remote-agent behavior |\n`verified` |\nMCP result independently checked over A2A | The accuracy/overhead tradeoff |\n\nBoth 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.\n\nCurrency conversion is a terrible job for an LLM and a great job for `Decimal`\n\n. 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?\"\n\n```\ndifference = abs(primary.converted_amount - verifier.converted_amount)\nrelative = difference / abs(primary.converted_amount)\nagreed = relative <= tolerance  # default 0.005\n```\n\nThe failure policy is explicit rather than emergent:\n\n`validation`\n\n, `provider`\n\n, `authentication`\n\n, `transport`\n\n, `timeout`\n\n, `protocol`\n\n). 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.\n\nHere is the headline interoperability lesson. The first attempt to point the Microsoft Agent Framework A2A client at the existing currency agent died instantly:\n\n```\na2a.utils.errors.MethodNotFoundError: Method not found\n```\n\nRoot cause: a clean protocol-version skew with **no negotiation**.\n\n`agent-framework-a2a`\n\n, requires `a2a-sdk>=1.0`\n\n) calls the A2A v1.0 JSON-RPC method `SendMessage`\n\n.`a2a-sdk 0.3.x`\n\n) only routes the v0.3.0 method `message/send`\n\n.`protocolVersion: 0.3.0`\n\n— and calls the v1.0 method anyway.Worse, the two ecosystems had mutually exclusive dependency pins at the time of writing:\n\n| Package | a2a-sdk requirement |\n|---|---|\n`agent-framework-a2a 1.0.0b260721` |\n`>=1.0.0,<2` |\n`google-adk 2.1.0 – 2.4.0` |\n`>=0.3.4,<0.4` |\n`google-adk 2.5.0` |\n`>=0.3.4,<2` ✅ |\n`a2ui-agent-sdk` (through 0.4.0) |\n`<0.4.0` ❌ |\n\n`google-adk 2.5.0`\n\nis the first release that allows `a2a-sdk 1.x`\n\n— 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`\n\n+ `a2a-sdk 1.1.2`\n\n. Separate `uv`\n\nvirtualenvs keep both worlds installable on one machine; the wire protocol is what has to match.\n\nTwo more v1.0 observations worth knowing:\n\n`url`\n\n/`protocolVersion`\n\ninto a `supportedInterfaces`\n\narray.`get_exchange_rate`\n\n) 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.\n\nVersions observed working (preview software; pin what works, expect drift): Azure Developer CLI `1.28.1`\n\n, `microsoft.foundry`\n\nazd extension `1.0.0-beta.2`\n\n, Python `3.13`\n\n, `agent-framework-core 1.12.1`\n\n, `agent-framework-foundry 1.10.3`\n\n, `agent-framework-foundry-hosting 1.0.0b260722`\n\n, region `eastus2`\n\n, model `gpt-5-mini`\n\n(`2025-08-07`\n\n, Global Standard).\n\nThe entire hosted agent is one file. `FoundryChatClient`\n\nauthenticates with `DefaultAzureCredential`\n\n— no API keys anywhere on the Azure side — and `ResponsesHostServer`\n\nexposes it over the Responses protocol:\n\n```\nagent = Agent(\n    client=FoundryChatClient(\n        project_endpoint=os.environ[\"FOUNDRY_PROJECT_ENDPOINT\"],\n        model=os.environ[\"AZURE_AI_MODEL_DEPLOYMENT_NAME\"],\n        credential=DefaultAzureCredential(),\n    ),\n    name=\"currency-interoperability-coordinator\",\n    instructions=\"For every conversion request, call run_currency_benchmark. \"\n                 \"Never calculate or verify arithmetic yourself. ...\",\n    tools=[run_currency_benchmark],\n)\nResponsesHostServer(agent).run()\n```\n\nThe adapters behind that tool are selected by environment variables (`CURRENCY_A2A_ENDPOINT`\n\n, `CURRENCY_RATE_PROVIDER`\n\n, `CURRENCY_RATE_TRANSPORT`\n\n, `CURRENCY_TIMEOUT_SECONDS`\n\n), passed through `azure.yaml`\n\n. Version 1 shipped with deterministic fixtures; version 2 flipped the env vars and went live without touching code.\n\nThe 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`\n\n) at the Foundry account scope.\n\nThe benchmark agent container colocates two processes: the FastMCP Frankfurter server on localhost and the A2A app on `$PORT`\n\n. The Gemini key comes from Secret Manager — never an env literal:\n\n```\ngcloud secrets create gemini-api-key --data-file=\"$HOME/gemini.key\"\ngcloud run deploy currency-adk-a2a \\\n  --source adk_agent --region us-central1 \\\n  --allow-unauthenticated --min-instances=0 --max-instances=2 \\\n  --set-secrets \"GOOGLE_API_KEY=gemini-api-key:latest\" \\\n  --set-env-vars \"MCP_SERVER_URL=http://127.0.0.1:8081/mcp,GENAI_MODEL=gemini-2.5-flash\"\n```\n\n`--min-instances=0`\n\nmeans the verifier costs nothing while idle. (Ask me how I know to check `min-instances`\n\non old GPU services. Actually, don't.)\n\nEverything local runs credential-free on fixtures first:\n\n```\ngit clone https://github.com/xbill9/foundry-adk-a2a-currency\ncd foundry-adk-a2a-currency\npip3 install --user -e \".[dev]\"\npytest                      # 35 deterministic tests, no cloud, no model calls\ncurrency-benchmark 100 USD EUR --mode verified --transport mcp-stdio\n```\n\nTo go live locally, start the ADK agent (needs `GOOGLE_API_KEY`\n\n):\n\n```\ncd adk_agent && uv sync\nMCP_SERVER_URL=http://127.0.0.1:8081/mcp uv run uvicorn agent:a2a_app --port 10001\n```\n\nand point the benchmark at it:\n\n```\nCURRENCY_RATE_PROVIDER=frankfurter currency-benchmark 250 GBP USD JPY \\\n  --mode verified --transport mcp-stdio \\\n  --a2a-endpoint http://127.0.0.1:10001 --timeout-seconds 60\n```\n\nThe full evaluation matrix (fault-free cases live, fault-injection cases deterministic — you cannot order a live agent to time out on demand):\n\n```\ncurrency-evaluate --a2a-endpoint http://127.0.0.1:10001 --live-rates \\\n  --output results.jsonl --summary summary.json\n```\n\nThe full cross-cloud deployment is one script — Secret Manager, Cloud Run, then `azd deploy`\n\n:\n\n```\nbash infra/deploy_live.sh\n```\n\nThe 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.\n\n| Mode | Success | Median latency | p95 latency |\n|---|---|---|---|\n`mcp_only` |\n100% | 297 ms | 1.09 s |\n`a2a_only` (live Gemini) |\n100% | 1.69 s | 4.82 s |\n`verified` (live) |\n100% | 1.71 s | 4.15 s |\n\nThe two numbers I care most about:\n\nOn the fully hosted path (Azure coordinator → GCP agent), the remote Foundry endpoint completed all three modes: `mcp_only`\n\nin 0.71 s, `verified`\n\nin 2.7 s with `agreed: true`\n\nand `relative_difference: 0`\n\n. One warm-path anecdote, not a distribution — repeated warm/cold trials and token/cost accounting are the remaining evaluation work.\n\n`a2a-sdk`\n\nmajor version on `MethodNotFoundError`\n\nis the signature.`protocol`\n\nfailure instead of a silently incomplete answer. Design for partial replies.`azd deploy`\n\ndied with `AzureDeveloperCLICredential: signal: killed`\n\nand succeeded unchanged on retry. Retry before you bisect.`gpt-5-mini`\n\nand `gemini-2.5-flash`\n\nrespected \"call the tool, never calculate\" — and because all math is `Decimal`\n\nin 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`\n\nat 297 ms is your friend.\n\nEverything — coordinator, benchmark agent, deploy script, evaluation cases, and the raw results behind every table above:\n\n[GitHub - xbill9/foundry-adk-a2a-currency](https://github.com/xbill9/foundry-adk-a2a-currency)\n\nUpstream agent pinned at [xbill9/currency-agent@aeef3c4](https://github.com/xbill9/currency-agent).\n\nIf 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.", "url": "https://wpnews.pro/news/can-google-adk-talk-to-microsoft-foundry-on-azure-a-cross-cloud-a2a-benchmark", "canonical_source": "https://dev.to/gde/can-google-adk-talk-to-microsoft-foundry-on-azure-a-cross-cloud-a2a-benchmark-4h36", "published_at": "2026-07-27 20:54:36+00:00", "updated_at": "2026-07-27 21:30:45.070618+00:00", "lang": "en", "topics": ["artificial-intelligence", "ai-agents", "ai-infrastructure", "developer-tools"], "entities": ["Microsoft Foundry", "Azure", "Google ADK", "Google Cloud", "Cloud Run", "Microsoft Agent Framework", "Frankfurter API", "Gemini"], "alternates": {"html": "https://wpnews.pro/news/can-google-adk-talk-to-microsoft-foundry-on-azure-a-cross-cloud-a2a-benchmark", "markdown": "https://wpnews.pro/news/can-google-adk-talk-to-microsoft-foundry-on-azure-a-cross-cloud-a2a-benchmark.md", "text": "https://wpnews.pro/news/can-google-adk-talk-to-microsoft-foundry-on-azure-a-cross-cloud-a2a-benchmark.txt", "jsonld": "https://wpnews.pro/news/can-google-adk-talk-to-microsoft-foundry-on-azure-a-cross-cloud-a2a-benchmark.jsonld"}}