Skip to content

[Bug] Scaffolded agent card grows a duplicate JSONRPC 0.3 interface on every GET (card_modifier mutates the shared AgentCard) #84

Description

@cph3cob

Every project scaffolded from the ADK template appends a duplicate
JSONRPC / 0.3 entry to supportedInterfaces on every request to the
public agent-card endpoint. The list grows without bound for the life of
the process.

Reproduction

uv tool install google-agents-cli          # 1.4.1
agents-cli create react-agent --adk
cd react-agent && uv sync
uv run uvicorn app.fast_api_app:app --host 127.0.0.1 --port 8000

for i in 1 2 3 4 5; do
  curl -s localhost:8000/a2a/app/.well-known/agent-card.json \
    | python3 -c "import sys,json;print(len(json.load(sys.stdin)['supportedInterfaces']))"
done

Observed: 2 3 4 5 6 — one JSONRPC 1.0 entry plus N identical
JSONRPC 0.3 entries, all with the same URL.

Expected: a stable card with exactly two interfaces, regardless of how
many times it is fetched.

Activity

  1. qingvincentyin commented on Aug 31, 2026

    @qingvincentyin

    Still present in 1.4.2, the current release. I also reproduced it against a deployed Cloud Run service rather than a local uvicorn run, so it is not confined to dev.

    A fix, plus three details that aren't in the report above.

    AgentCard is a protobuf message (a2a_pb2), not a pydantic model, so there's no model_copy to reach for. The protobuf idiom is CopyFrom:

    async def _add_v0_3_compat_interface(card: AgentCard) -> AgentCard:
        if not card.supported_interfaces:
            return card
        modified = AgentCard()
        modified.CopyFrom(card)
        modified.supported_interfaces.append(
            AgentInterface(
                protocol_binding="JSONRPC",
                protocol_version="0.3",
                url=card.supported_interfaces[0].url,
            )
        )
        return modified

    Verified against a2a-sdk 1.1.2 over 5 requests: current code serves [2, 3, 4, 5, 6] interfaces, the patched version serves [2, 2, 2, 2, 2] and leaves the shared object at 1.

    A simpler alternative is to append the 0.3 entry once in attach_a2a_routes, right after AgentCardBuilder(...).build(), and drop card_modifier entirely. The entry is static, so there is nothing to recompute per request. Also verified.

    Age. I inspected the app_utils/a2a.py template inside each published wheel. _add_v0_3_compat_interface is absent in 1.0.0, 1.1.0, 1.2.0 and 1.2.1. It appears in 1.3.0 (2026-08-04) and is byte-identical in 1.3.1, 1.4.0, 1.4.1 and 1.4.2.

    additionalInterfaces grows too. The 0.3 serialization emits it alongside supportedInterfaces, and in every sample I took it stayed exactly 2 entries behind. So the served card grows by 9 pretty-printed lines per fetch, not 5.

    It reaches stored registration data, which may raise the priority. agents-cli publish gemini-enterprise sends the card verbatim — fetch_agent_card_from_url returns response.json() unmodified, and the A2A registration payload does json.dumps(agent_card). Whatever duplicates exist at publish time are written into Gemini Enterprise's stored jsonAgentCard and persist for the life of the registration. This is observable on a live registration, not just theoretical. On Cloud Run the growth is also per container instance, so with min-instances 0 concurrent callers can receive different cards from the same service.

  2. added theissue type on Aug 31, 2026
  3. self-assigned this
    on Sep 25, 2026
  4. asrujana-44 commented on Sep 28, 2026

    @asrujana-44

    Thanks for reporting this! We are working on this issue and we will get back to you soon.

  5. pwkowalski commented on Oct 6, 2026

    @pwkowalski
    Collaborator

    Fixed in 1.9.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions