Hacktoberfest 2026:メンテナが10月に向けて印を付けた、オープンで初心者向けの issue。 Hacktoberfest の issue を見る

[Bug]: `A2A-Version` sent as a request parameter is ignored (spec §3.6.1), so a v1.0 request is treated as 0.3

オープン
#1,344 コメント 0 件 リアクション 0 件 担当者 2 名 GitHub で見る

メンテナーはふだん 2 日以内に返信

@rohityan がすでに取り組んでいます。

2026年10月16日 から。

評価

この issue はまだ評価されていません。

説明

What happened?

Summary

The server only reads A2A-Version from the request header. A client that sends the version as a request parameter, which the specification allows, is treated as a 0.3 client and gets VersionNotSupportedError for a valid v1.0 request.

Section 3.6.1 ("Client Responsibilities") of the v1.0.0 specification says: "Clients MAY provide the A2A-Version as a request parameter instead of a header." Its example is GET /tasks/task-123?A2A-Version=1.0. Section 3.6.2 then requires the agent to process the request using the semantics of the requested version.

DefaultServerCallContextBuilder.build() copies only request.headers into state['headers'] (src/a2a/server/routes/common.py:115), and validate_version reads only that dict (src/a2a/utils/version_validator.py:68). The query string is never consulted, so the request falls through to the empty-header default of 0.3.

Reproduce

pip install "a2a-sdk[http-server]==1.2.2" httpx, then run:

import asyncio

import httpx
from starlette.applications import Starlette

from a2a.server.agent_execution import AgentExecutor
from a2a.server.request_handlers import DefaultRequestHandler
from a2a.server.routes import create_jsonrpc_routes, create_rest_routes
from a2a.server.tasks import InMemoryTaskStore
from a2a.types import AgentCapabilities, AgentCard, AgentInterface


class Noop(AgentExecutor):
    async def execute(self, context, event_queue): ...
    async def cancel(self, context, event_queue): ...


card = AgentCard(
    name="probe", description="probe", version="0.0.1",
    capabilities=AgentCapabilities(),
    supported_interfaces=[AgentInterface(
        url="http://test/rpc", protocol_binding="JSONRPC", protocol_version="1.0")],
)
handler = DefaultRequestHandler(
    agent_executor=Noop(), task_store=InMemoryTaskStore(), agent_card=card)
app = Starlette(routes=[*create_jsonrpc_routes(handler, "/rpc"),
                        *create_rest_routes(handler)])

RPC = {"jsonrpc": "2.0", "id": 1, "method": "GetTask", "params": {"id": "task-123"}}
HDR = {"A2A-Version": "1.0"}


async def main():
    async with httpx.AsyncClient(transport=httpx.ASGITransport(app=app),
                                 base_url="http://test") as c:
        for label, resp in [
            ("JSON-RPC  header      ", await c.post("/rpc", json=RPC, headers=HDR)),
            ("JSON-RPC  ?A2A-Version", await c.post("/rpc?A2A-Version=1.0", json=RPC)),
            ("HTTP+JSON header      ", await c.get("/tasks/task-123", headers=HDR)),
            ("HTTP+JSON ?A2A-Version", await c.get("/tasks/task-123?A2A-Version=1.0")),
        ]:
            body = resp.json()
            err = body.get("error", body)
            print(f"{label} -> HTTP {resp.status_code}  {err.get('code')}  {err.get('message')}")


asyncio.run(main())

Actual (identical on main at e86695c, and with enable_v0_3_compat=True):

JSON-RPC  header       -> HTTP 200  -32001  Task not found
JSON-RPC  ?A2A-Version -> HTTP 200  -32009  A2A version '0.3' is not supported by this handler. Expected version '1.0'.
HTTP+JSON header       -> HTTP 404  404  Task not found
HTTP+JSON ?A2A-Version -> HTTP 400  400  A2A version '0.3' is not supported by this handler. Expected version '1.0'.

Expected: the two ?A2A-Version=1.0 requests behave like the header requests and return Task not found.

On JSON-RPC the failure is quiet: an HTTP 200 carrying -32009. A client that checks the status code and then reads an SSE stream sees an empty stream, which looks like an agent with nothing to say.

Suggested fix

When the header is absent, fall back to the A2A-Version request parameter in DefaultServerCallContextBuilder.build(). That way every transport and validate_version see the same value. The spec does not say which wins when both are present; letting the header win seems the least surprising.

A smaller related improvement: when the client sent no version at all, say so in the error. Today the message reads "A2A version '0.3' is not supported", which suggests the client sent 0.3. Something like "no A2A-Version header or parameter; defaulted to 0.3, which this handler does not support" would point straight at the cause.

Relevant log output
Version mismatch: actual='0.3', expected='1.0'
Code of Conduct
  • I agree to follow this project's Code of Conduct
主要言語
Python
スター
2.2k
フォーク
511
平均マージ
3日 10時間
マージ済み PR(30日)
47

環境構築

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

a2aproject/a2a-python のほかの issue

a2aproject/a2a-python の issue をすべて見る

似ている issue

Python の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。