{"slug": "the-a2a-cli-on-azure-one-client-for-container-apps-agent-framework-and-localhost", "title": "The A2A CLI on Azure: One Client for Container Apps, Agent Framework and Localhost", "summary": "A developer published a step-by-step guide and open-source repository showing how to run A2A 1.0 agents on Azure and drive them with a single A2A CLI. The setup pairs a Rust agent built on the official A2A Rust SDK with a Microsoft Agent Framework coordinator on Azure OpenAI's gpt-5.4-mini, both deployed to Azure Container Apps behind Entra ID and also runnable locally, with the CLI executing the same commands against all four endpoints and passing 19 of 19 checks. All access uses Entra ID tokens via az login, with no API keys anywhere in the stack.", "body_md": "This article provides a step by step guide to running A2A agents on Azure and driving them with the A2A CLI. A Rust agent on the official A2A Rust SDK runs in Azure Container Apps. A Microsoft Agent Framework agent on an Azure OpenAI model runs in Container Apps behind Entra ID and hands its work to the Rust agent. Both also run on a laptop, and one set of `a2a` commands checks all four.\n\n[https://github.com/xbill9/rust-dev/tree/main/a2a-agentframework-azure](https://github.com/xbill9/rust-dev/tree/main/a2a-agentframework-azure)\n\n**The A2A CLI drove all four endpoints with the same commands, and 19 of 19 checks passed.** Every hop speaks A2A 1.0: the Rust SDK serves it, Agent Framework serves it, and the Agent Framework agent calls the Rust agent with the A2A 1.0 Python client. On Azure the CLI needs one extra flag, an Entra ID bearer token, which `az login` already provides. Model access, registry pulls and the token all run on Entra ID, with no API key anywhere.\n\n| Agent | Where it runs | A2A | Model | \n|---|---|---|---|\n| `mersenne-agent` (Rust) | laptop, port 8304 | 1.0, JSON-RPC and REST | none | \n| `mersenne-agent` (same image) | Container Apps, 0.25 vCPU, 0.5 GiB | 1.0, JSON-RPC and REST | none | \n| Agent Framework coordinator | laptop, port 8309 | 1.0, JSON-RPC and REST | `gpt-5.4-mini` on Azure OpenAI | \n| Agent Framework coordinator (same code) | Container Apps, Entra ID auth | 1.0, JSON-RPC and REST | `gpt-5.4-mini` on Azure OpenAI | \n\n```\na2a CLI ──► Container Apps auth (Entra ID token) ──► Agent Framework Agent ──Entra ID──► Azure OpenAI gpt-5.4-mini\n                                                           └── find_mersenne_primes tool\n                                                                 └── a2a-sdk 1.x client ──► Container Apps (A2A 1.0) ──► mersenne-agent\na2a CLI ────────────────────────────────────────────────────────────────────────────────► Container Apps (A2A 1.0)\n```\n\nThe workload is a Lucas-Lehmer test over the first N known Mersenne prime exponents, timed by the agent itself. Every reply carries the line `Found first N Mersenne primes in X ms.` and a data part with `requested`, `found` and `elapsed_ms`.\n\nVersions, read from the machine on 2026-11-06:\n\n| Component | Version | \n|---|---|\n| A2A CLI ( `a2a` ) | v0.3.1 | \n| `a2a-lf` /`a2a-server-lf` (Rust SDK, A2A 1.0) | 0.4.2 / 0.5.3 | \n| `agent-framework-core` /`agent-framework-openai` /`agent-framework-a2a` | 1.24.0 / 1.18.0 / 1.0.0b261030 | \n| `a2a-sdk` (Python, A2A 1.0) /`azure-identity` | 1.3.0 / 1.27.0 | \n| Python / Rust | 3.14.7 / 1.99.1 | \n| Azure CLI | 2.90.0 | \n| Model | `gpt-5.4-mini` 2026-03-17, GlobalStandard | \n| Region | eastus2 | \n\n`PATH` as `a2a`: `go install github.com/a2aproject/a2a-cli@latest`, then rename `a2a-cli` to `containerapp` extension, signed in with `az login` to a subscription where you can create resource groups and Entra ID app registrations\n\n```\na2a version\na2a v0.3.1\ngit clone https://github.com/xbill9/rust-dev && cd rust-dev/a2a-agentframework-azure\nscripts/deploy-model.py\n```\n\nThe script creates one resource group in eastus2 holding a container registry, a user-assigned managed identity, a Container Apps environment and an AIServices account with a `gpt-5.4-mini` deployment. It grants \"Cognitive Services OpenAI User\" on the account twice: to the signed-in user, for the laptop, and to the managed identity, for the containers.\n\n``` bash\n$ az group create -n a2a-agentframework-azure-rg -l eastus2\n$ az containerapp env create -n a2a-af-env -g a2a-agentframework-azure-rg -l eastus2 --logs-destination none\n$ az cognitiveservices account create -n a2a-af-openai-defaba -g a2a-agentframework-azure-rg -l eastus2 --kind AIServices --sku S0 --custom-domain a2a-af-openai-defaba --yes\n$ az cognitiveservices account deployment create ... --model-name gpt-5.4-mini --model-version 2026-03-17 --model-format OpenAI --sku-name GlobalStandard --sku-capacity 50\n✅ https://a2a-af-openai-defaba.cognitiveservices.azure.com/ deployment gpt-5.4-mini\n```\n\nThe account gets a custom subdomain, and every call to the model authenticates with Entra ID. The coordinator holds no key.\n\n```\nscripts/start-local.sh\nphp\nup: 8304 rust agent, 8309 agent framework coordinator -> http://localhost:8304\n```\n\nThe coordinator is an Agent Framework `Agent` with one tool, served over A2A 1.0 by `agent_framework_a2a` on the `a2a-sdk` server routes. The same file runs on the laptop and in Container Apps:\n\n```\nclient = OpenAIChatClient(\n    model=MODEL,\n    azure_endpoint=os.environ[\"AZURE_OPENAI_ENDPOINT\"],\n    credential=DefaultAzureCredential(),\n)\nagent = Agent(client=client, name=NAME, description=DESCRIPTION,\n              instructions=INSTRUCTIONS, tools=[find_mersenne_primes])\nhandler = DefaultRequestHandler(\n    agent_executor=WholeTextA2AExecutor(agent, stream=True),\n    task_store=InMemoryTaskStore(),\n    agent_card=card,\n)\nreturn Starlette(routes=[\n    *create_agent_card_routes(card),\n    *create_rest_routes(handler, path_prefix=\"/rest\"),\n    *create_jsonrpc_routes(handler, \"/\"),\n])\n```\n\n`DefaultAzureCredential` picks up `az login` on the laptop and the managed identity in Azure. The CLI reads both cards and shows each one's protocol version:\n\n```\na2a card get -a http://localhost:8304\na2a card get -a http://localhost:8309\nName:         Mersenne Prime Agent Rust\nVersion:      0.1.0\nInterfaces:\n  JSONRPC (A2A v1.0)     http://localhost:8304/jsonrpc\n  HTTP+JSON (A2A v1.0)   http://localhost:8304/rest\nName:         Agent Framework Mersenne Coordinator\nVersion:      0.1.0\nInterfaces:\n  JSONRPC (A2A v1.0)     http://localhost:8309/\n  HTTP+JSON (A2A v1.0)   http://localhost:8309/rest\n```\n\nAgent Framework's A2A package is built on `a2a-sdk` 1.x, the same protocol version as the Rust agent. The tool sends a data part and reads the Rust agent's structured report straight from the reply:\n\n```\nvalue = Value()\nvalue.struct_value.update({\"count\": count})\nrequest = SendMessageRequest(message=Message(\n    role=Role.ROLE_USER, message_id=os.urandom(16).hex(), parts=[Part(data=value)],\n))\nasync with httpx.AsyncClient(timeout=60) as http:\n    client = await create_client(\n        RUST_AGENT_URL, ClientConfig(streaming=False, httpx_client=http))\n    async for event in client.send_message(request):\n        task = event.task if event.HasField(\"task\") else None\n        for artifact in (task.artifacts if task else []):\n            for part in artifact.parts:\n                if part.HasField(\"data\"):\n                    report = MessageToDict(part.data)\n                elif part.HasField(\"text\"):\n                    summary = part.text\n```\n\nThe tool refuses a reply whose `requested` or `found` differs from the count the model asked for, and the instructions tell the model to quote the agent's own reply line. The model picks N; the Rust agent does the counting and the timing. Data parts cross a protobuf `Struct`, so integers arrive as floats and the tool reads them with `int()`.\n\n`agent-framework-a2a` requires `a2a-sdk` 1.x, and the same machine runs a Strands rig whose `a2a-sdk` is pinned to 0.3:\n\n```\n# agent-framework-a2a wheel metadata (Requires-Dist)\nRequires-Dist: agent-framework-core>=1.22.0,<2\nRequires-Dist: a2a-sdk>=1.0.0,<2\n\n# shared pyenv Python (used by the Strands rig)\na2a-sdk 0.3.26\n```\n\n`scripts/start-local.sh` installs the coordinator's pinned requirements into `build/local-site` with `pip install --target`, and starts the coordinator with `PYTHONPATH=build/local-site`. The two SDK versions never meet, and the container image installs the same pins.\n\n`scripts/deploy-rust.py` builds `docker/agent.Dockerfile`, pushes it to the registry and creates a container app with external ingress. The app pulls with the managed identity, which holds AcrPull, so there is no registry password. The script computes the app's address from the environment's default domain before creating it and sets `ADVERTISE_URL` to it, so the card points at Container Apps from the first revision.\n\n```\nscripts/deploy-rust.py\nbash\n$ docker build --platform linux/amd64 -f docker/agent.Dockerfile -t a2aafazuredefaba.azurecr.io/mersenne-agent:20261106T153734Z /home/xbill/rust-dev/a2a-agentframework-azure\n$ docker push a2aafazuredefaba.azurecr.io/mersenne-agent:20261106T153734Z\n$ az containerapp create -n a2a-rust-mersenne ... --target-port 8080 --ingress external --registry-identity <identity> --cpu 0.25 --memory 0.5Gi --min-replicas 1 --max-replicas 1 --env-vars PORT=8080 HOST=0.0.0.0 ADVERTISE_URL=https://a2a-rust-mersenne.braveground-531dbad2.eastus2.azurecontainerapps.io\n✅ https://a2a-rust-mersenne.braveground-531dbad2.eastus2.azurecontainerapps.io/.well-known/agent-card.json\n```\n\nThe commands are the laptop's, with the Container Apps address:\n\n```\nscripts/test-cli.sh aca-rust\n== aca-rust rust agent (https://a2a-rust-mersenne.braveground-531dbad2.eastus2.azurecontainerapps.io)\nInterfaces:\n  JSONRPC (A2A v1.0)     https://a2a-rust-mersenne.braveground-531dbad2.eastus2.azurecontainerapps.io/jsonrpc\n  HTTP+JSON (A2A v1.0)   https://a2a-rust-mersenne.braveground-531dbad2.eastus2.azurecontainerapps.io/rest\n✅ aca-rust card (A2A v1.0)\n✅ aca-rust send\n✅ aca-rust stream\n✅ aca-rust rest\n✅ aca-rust data-part\n```\n\n`scripts/deploy-coordinator.py` does four things:\n\n`api://<app id>`, one delegated scope `access_as_user`, version 2 access tokens, and the Azure CLI's client id pre-authorized on that scope`docker/coordinator.Dockerfile` and pushes it`RUST_AGENT_URL` set to the Container Apps Rust agent and `AZURE_CLIENT_ID` set to the managed identity\n\n```\nscripts/deploy-coordinator.py\nbash\n$ az containerapp auth microsoft update -n a2a-af-coordinator -g a2a-agentframework-azure-rg --client-id 67ce79d7-7432-4261-b394-d32c2fc36890 --issuer https://login.microsoftonline.com/<tenant>/v2.0 --allowed-audiences api://67ce79d7-7432-4261-b394-d32c2fc36890,67ce79d7-7432-4261-b394-d32c2fc36890 --yes\n$ az containerapp auth update -n a2a-af-coordinator -g a2a-agentframework-azure-rg --enabled true --unauthenticated-client-action Return401\n✅ https://a2a-af-coordinator.braveground-531dbad2.eastus2.azurecontainerapps.io/.well-known/agent-card.json (401 without a token)\n```\n\nFrom the CLI, the coordinator takes one flag beyond the laptop's: a bearer token for the app registration.\n\n```\nURL=$(scripts/azure_state.py get coordinator_url)\nTOKEN=$(scripts/entra-token.py)    # az account get-access-token --resource api://<app id>\na2a --auth \"Bearer $TOKEN\" card get -a \"$URL\"\na2a --auth \"Bearer $TOKEN\" send -a \"$URL\" --transport rest \"Find the first 3 Mersenne primes\"\nName:         Agent Framework Mersenne Coordinator\nInterfaces:\n  JSONRPC (A2A v1.0)     https://a2a-af-coordinator.braveground-531dbad2.eastus2.azurecontainerapps.io/\n  HTTP+JSON (A2A v1.0)   https://a2a-af-coordinator.braveground-531dbad2.eastus2.azurecontainerapps.io/rest\nStatus:   completed (2026-11-06T16:20:22Z)\nArtifacts:\n  [msg_0a2ef6a5893a0e6d006aedfe460ca48195931f337d1ca8db4e] Found first 3 Mersenne primes in 0.0030ms.\n2, 3, 5\n```\n\nThe CLI takes the base URL, the card sits at the standard `/.well-known/agent-card.json` path, and each call gets its own A2A context with no session header. Without a token, and with a malformed one, the card itself answers 401:\n\n``` bash\n$ curl -s -o /dev/null -w '%{http_code}' $URL/.well-known/agent-card.json\n401\n$ curl -s -o /dev/null -w '%{http_code}' -H 'Authorization: Bearer not-a-jwt' $URL/.well-known/agent-card.json\n401\n```\n\nWith the Azure CLI's client id listed under `preAuthorizedApplications` for the `access_as_user` scope, `az account get-access-token --resource api://<app id>` returns a token for the coordinator with no consent prompt and no client secret. The token's claims, payload only:\n\n```\n{\n  \"aud\": \"67ce79d7-7432-4261-b394-d32c2fc36890\",\n  \"iss\": \"https://login.microsoftonline.com/40482c55-d00d-4c6d-8903-643d76a74b9c/v2.0\",\n  \"ver\": \"2.0\",\n  \"scp\": \"access_as_user\",\n  \"azp\": \"04b07795-8ddb-461a-bbee-02f9e1bf7b46\"\n}\n```\n\n`azp` is the Azure CLI. With `requestedAccessTokenVersion: 2` the audience is the bare app id and the issuer ends in `/v2.0`, so the built-in authentication lists both `api://<app id>` and `<app id>` as allowed audiences and uses the v2 issuer.\n\n`azure.identity.aio` needs `aiohttp` for managed identity, and nothing in the Agent Framework or `a2a-sdk` dependency tree installs it. The same requirements without the pin, in a clean `python:3.14-slim-trixie` container:\n\n```\naiohttp dist-info dirs installed: 0\nImportError: aiohttp package is not installed\n```\n\n`coordinator/requirements.txt` pins `aiohttp==3.14.5`. A shared Python on a laptop that already has `aiohttp` from another package hides the gap, so the clean container is the place to check it.\n\nAgent Framework's OpenAI client streams a reply as text deltas, then sends one more update holding the whole text under the same message id. One streamed reply, every text update:\n\n```\n1 msg_02d7537ef107 'Found'\n2 msg_02d7537ef107 ' first'\n...\n21 msg_02d7537ef107 ' 7'\n22 msg_02d7537ef107 'Found first 4 Mersenne primes in 0.0026ms.\\n2, 3, 5, 7'\n# last update repeats everything streamed before it under the same message_id: True\n```\n\n`A2AExecutor` appends every update to one artifact, which leaves the reply in the task twice. `WholeTextA2AExecutor` lets the closing update replace the artifact, so streaming clients see the deltas and the finished task holds the reply once, as a single text part:\n\n``` python\nclass WholeTextA2AExecutor(A2AExecutor):\n    async def handle_events(self, item, updater, streamed_artifact_ids=None, default_artifact_id=None):\n        if isinstance(item, AgentResponseUpdate):\n            key = item.message_id or default_artifact_id or \"\"\n            text = \"\".join(c.text for c in item.contents if c.type == \"text\" and c.text)\n            so_far = self._streamed.get(key, \"\")\n            if text and so_far and text == so_far:\n                del self._streamed[key]\n                if streamed_artifact_ids is not None:\n                    streamed_artifact_ids.discard(key)  # next add_artifact replaces\n            elif text:\n                self._streamed[key] = so_far + text\n        await super().handle_events(item, updater, streamed_artifact_ids, default_artifact_id)\na2a --auth \"Bearer $TOKEN\" send -a \"$URL\" -o json \"Find the first 10 Mersenne primes\"\n\"artifacts\": [\n  {\n    \"artifactId\": \"msg_0df9fa92840724f8006aedfe47b9208195b7c9c1698118b7c1\",\n    \"parts\": [\n      {\n        \"text\": \"Found first 10 Mersenne primes in 0.0549ms.\\n2, 3, 5, 7, 13, 17, 19, 31, 61, 89\"\n      }\n    ]\n  }\n]\n```\n\nThe coordinator checks in the next step require the reply line exactly once, and the timing script counts a call only when it appears once.\n\n`scripts/test-cli.sh all` starts the laptop agents and runs one set of checks against each endpoint. Each Rust agent gets card (A2A v1.0), send, stream, REST and a data part. Each coordinator gets card (A2A v1.0), send, stream and REST, and the Container Apps coordinator also gets a request with no token, which must answer 401.\n\n```\nscripts/test-cli.sh all\n== local rust agent (http://localhost:8304)\n✅ local card (A2A v1.0)\n✅ local send\n✅ local stream\n✅ local rest\n✅ local data-part\n== local agent framework coordinator (http://localhost:8309)\n✅ local card (A2A v1.0)\n✅ local send\n✅ local stream\n✅ local rest\n== aca-rust rust agent (https://a2a-rust-mersenne.braveground-531dbad2.eastus2.azurecontainerapps.io)\n✅ aca-rust card (A2A v1.0)\n✅ aca-rust send\n✅ aca-rust stream\n✅ aca-rust rest\n✅ aca-rust data-part\n-- without a token (expect 401)\n✅ aca-coordinator rejects no token (401)\n== aca-coordinator agent framework coordinator (https://a2a-af-coordinator.braveground-531dbad2.eastus2.azurecontainerapps.io)\n✅ aca-coordinator card (A2A v1.0)\n✅ aca-coordinator send\n✅ aca-coordinator stream\n✅ aca-coordinator rest\n```\n\nThe Container Apps coordinator checks ask for 7, 11 and 3 primes. All three reached the Container Apps Rust agent, and the coordinator's log shows each one:\n\n```\nINFO:coordinator:rust agent https://a2a-rust-mersenne.braveground-531dbad2.eastus2.azurecontainerapps.io: Found first 7 Mersenne primes in 0.0059ms.\nINFO:coordinator:rust agent https://a2a-rust-mersenne.braveground-531dbad2.eastus2.azurecontainerapps.io: Found first 11 Mersenne primes in 0.0339ms.\nINFO:coordinator:rust agent https://a2a-rust-mersenne.braveground-531dbad2.eastus2.azurecontainerapps.io: Found first 3 Mersenne primes in 0.0039ms.\n```\n\n`scripts/cli-bench.py` starts one `a2a` process per call and times it, so wall time includes starting the CLI, fetching the card, TLS on Azure and the reply. Targets take turns, one call each per round, so drift during the run lands on every target alike. Every reply is checked, and the statistics come from the script (`results/summary-20261106.txt`). N=10 and 20 calls per target throughout.\n\n```\nscripts/cli-bench.py --targets local-rust,aca-rust --reps 20 --n 10\nlocal-rust               ok 20/20  wall median 10.5 ms (min 7.9, max 12.3)  compute median 0.02268 ms\naca-rust                 ok 20/20  wall median 164.2 ms (min 143.4, max 199.9)  compute median 0.02985 ms\nscripts/cli-bench.py --targets local-coordinator,aca-coordinator --reps 20 --n 10\nlocal-coordinator        ok 20/20  wall median 1836.0 ms (min 1374.5, max 4833.5)\naca-coordinator          ok 20/20  wall median 1891.2 ms (min 1581.2, max 4372.4)\n```\n\nThe Rust agent's own compute time is a fraction of a millisecond on both machines, so the 153.7 ms between the laptop and Container Apps medians is the network and TLS. A coordinator call is an Azure OpenAI call plus a nested A2A call to a Rust agent. The Container Apps coordinator's median sits 55.2 ms above the laptop's, and both ranges span more than a second: the model call sets the time, and where the coordinator runs moves it by less than the spread between calls.\n\n```\nmake teardown\nbash\n$ az ad app delete --id 67ce79d7-7432-4261-b394-d32c2fc36890\n$ az group delete -n a2a-agentframework-azure-rg --yes\n$ az cognitiveservices account purge -n a2a-af-openai-defaba -g a2a-agentframework-azure-rg -l eastus2\ndeleted a2a-agentframework-azure-rg\n```\n\nEverything except the app registration lives in one resource group, so one delete removes it. The app registration lives in Entra ID and is deleted first. The script then purges the AIServices account, so no soft-deleted copy is left behind. Afterwards:\n\n``` bash\n$ az group exists -n a2a-agentframework-azure-rg\nfalse\n$ az cognitiveservices account list-deleted --query \"[].name\"\n[]\n```\n\nThe Container Apps and model addresses shown in this article belong to that deployment and no longer resolve. `make deploy` recreates all three steps under new addresses, and `make test-cli T=all` checks them again.\n\n| Endpoint | CLI flags beyond the laptop's | A2A | Median wall time, N=10 | \n|---|---|---|---|\n| Rust, laptop 🥇 | none | 1.0 | 10.5 ms | \n| Rust, Container Apps 🥈 | none, HTTPS address | 1.0 | 164.2 ms | \n| Agent Framework, laptop | none | 1.0 | 1836.0 ms | \n| Agent Framework, Container Apps | `--auth` with an Entra ID token | 1.0 | 1891.2 ms | \n\nFor an agent with no model in it, Container Apps is the short path: one container app with external ingress, a public HTTPS address and no client changes. Every call costs the network trip, 153.7 ms here, on top of a computation that takes a fraction of a millisecond.\n\nFor an agent built around a model, the same Container Apps environment hosts it behind Entra ID with built-in authentication and no code in the agent. The CLI adds one flag, and `az login` supplies the token. The model call sets the response time, wherever the agent runs.\n\nFor talking to any of them, the A2A CLI is the one client. With Agent Framework on A2A 1.0, the agents talk to each other with the Python SDK and the laptop talks to all of them with the CLI, over one protocol version end to end.\n\nThe goal of this article was to show that the A2A CLI drives the same agents on a laptop and on Azure Container Apps with the same commands. The key to the solution was A2A 1.0 on every hop, Entra ID for every credential, and one set of checks run against every endpoint. The results were:\n\n`a2a-sdk` 1.x client`WholeTextA2AExecutor`, or each reply lands in the task twice` aiohttp` pinned; nothing else installs it\nScope: one laptop (13th Gen Intel Core i7-1360P, Linux), one Azure region (eastus2), one replica of each app at 0.25 vCPU and 0.5 GiB, one model (`gpt-5.4-mini`), measured on 2026-11-06. Timing used N=10 with 20 calls per target, one run per comparison. Every Azure figure includes the trip from the laptop. Both apps kept one replica running, so cold starts were not measured; cost, gRPC, task commands, push notifications and load were not tested.\n\nThe strategy for running A2A agents on Azure and driving them with the A2A CLI was validated with an incremental step by step approach.", "url": "https://wpnews.pro/news/the-a2a-cli-on-azure-one-client-for-container-apps-agent-framework-and-localhost", "canonical_source": "https://dev.to/xbill/the-a2a-cli-on-azure-one-client-for-container-apps-agent-framework-and-localhost-4b6k", "published_at": "2026-11-06 18:21:08+00:00", "updated_at": "2026-11-06 18:27:00.299683+00:00", "lang": "en", "topics": ["ai-agents", "agent-protocols", "ai-tools", "developer-tools", "ai-infrastructure"], "entities": ["Microsoft", "Azure Container Apps", "Azure OpenAI", "Microsoft Agent Framework", "A2A", "Entra ID", "Rust", "gpt-5.4-mini"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/the-a2a-cli-on-azure-one-client-for-container-apps-agent-framework-and-localhost", "markdown": "https://wpnews.pro/news/the-a2a-cli-on-azure-one-client-for-container-apps-agent-framework-and-localhost.md", "text": "https://wpnews.pro/news/the-a2a-cli-on-azure-one-client-for-container-apps-agent-framework-and-localhost.txt", "jsonld": "https://wpnews.pro/news/the-a2a-cli-on-azure-one-client-for-container-apps-agent-framework-and-localhost.jsonld"}}