Skip to content

Commit c44c86d

Browse files
committed
fix: update A2A extension HTTP header
1 parent 174d58d commit c44c86d

File tree

6 files changed

+24
-12
lines changed

6 files changed

+24
-12
lines changed

src/a2a/extensions/common.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
from a2a.types import AgentCard, AgentExtension
44

55

6-
HTTP_EXTENSION_HEADER = 'X-A2A-Extensions'
6+
HTTP_EXTENSION_HEADER = 'A2A-Extensions'
7+
HTTP_EXTENSION_HEADER_DEPRECATED = 'X-A2A-Extensions'
78

89

910
def get_requested_extensions(values: list[str]) -> set[str]:
@@ -33,7 +34,7 @@ def update_extension_header(
3334
http_kwargs: dict[str, Any] | None,
3435
extensions: list[str] | None,
3536
) -> dict[str, Any]:
36-
"""Update the X-A2A-Extensions header with active extensions."""
37+
"""Update the A2A-Extensions header with active extensions."""
3738
http_kwargs = http_kwargs or {}
3839
if extensions is not None:
3940
headers = http_kwargs.setdefault('headers', {})

src/a2a/server/apps/jsonrpc/jsonrpc_app.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
from a2a.auth.user import User as A2AUser
1414
from a2a.extensions.common import (
1515
HTTP_EXTENSION_HEADER,
16+
HTTP_EXTENSION_HEADER_DEPRECATED,
1617
get_requested_extensions,
1718
)
1819
from a2a.server.context import ServerCallContext
@@ -136,12 +137,15 @@ def build(self, request: Request) -> ServerCallContext:
136137
user = StarletteUserProxy(request.user)
137138
state['auth'] = request.auth
138139
state['headers'] = dict(request.headers)
140+
extension_values = request.headers.getlist(HTTP_EXTENSION_HEADER)
141+
if not extension_values:
142+
extension_values = request.headers.getlist(
143+
HTTP_EXTENSION_HEADER_DEPRECATED
144+
)
139145
return ServerCallContext(
140146
user=user,
141147
state=state,
142-
requested_extensions=get_requested_extensions(
143-
request.headers.getlist(HTTP_EXTENSION_HEADER)
144-
),
148+
requested_extensions=get_requested_extensions(extension_values),
145149
)
146150

147151

src/a2a/server/request_handlers/grpc_handler.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
from a2a.auth.user import UnauthenticatedUser
2727
from a2a.extensions.common import (
2828
HTTP_EXTENSION_HEADER,
29+
HTTP_EXTENSION_HEADER_DEPRECATED,
2930
get_requested_extensions,
3031
)
3132
from a2a.grpc import a2a_pb2
@@ -72,12 +73,15 @@ def build(self, context: grpc.aio.ServicerContext) -> ServerCallContext:
7273
state = {}
7374
with contextlib.suppress(Exception):
7475
state['grpc_context'] = context
76+
extension_values = _get_metadata_value(context, HTTP_EXTENSION_HEADER)
77+
if not extension_values:
78+
extension_values = _get_metadata_value(
79+
context, HTTP_EXTENSION_HEADER_DEPRECATED
80+
)
7581
return ServerCallContext(
7682
user=user,
7783
state=state,
78-
requested_extensions=get_requested_extensions(
79-
_get_metadata_value(context, HTTP_EXTENSION_HEADER)
80-
),
84+
requested_extensions=get_requested_extensions(extension_values),
8185
)
8286

8387

tests/client/transports/test_jsonrpc_client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -847,7 +847,7 @@ async def test_send_message_streaming_with_new_extensions(
847847
mock_httpx_client: AsyncMock,
848848
mock_agent_card: MagicMock,
849849
):
850-
"""Test X-A2A-Extensions header in send_message_streaming."""
850+
"""Test A2A-Extensions header in send_message_streaming."""
851851
new_extensions = ['https://example.com/test-ext/v2']
852852
extensions = ['https://example.com/test-ext/v1']
853853
client = JsonRpcTransport(

tests/client/transports/test_rest_client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ async def test_send_message_streaming_with_new_extensions(
9696
mock_httpx_client: AsyncMock,
9797
mock_agent_card: MagicMock,
9898
):
99-
"""Test X-A2A-Extensions header in send_message_streaming."""
99+
"""Test A2A-Extensions header in send_message_streaming."""
100100
new_extensions = ['https://example.com/test-ext/v2']
101101
extensions = ['https://example.com/test-ext/v1']
102102
client = RestTransport(

tests/integration/test_client_server_integration.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import asyncio
2+
23
from collections.abc import AsyncGenerator
34
from typing import NamedTuple
45
from unittest.mock import ANY, AsyncMock, patch
@@ -7,6 +8,7 @@
78
import httpx
89
import pytest
910
import pytest_asyncio
11+
1012
from grpc.aio import Channel
1113

1214
from a2a.client import ClientConfig
@@ -38,6 +40,7 @@
3840
TransportProtocol,
3941
)
4042

43+
4144
# --- Test Constants ---
4245

4346
TASK_FROM_STREAM = Task(
@@ -819,9 +822,9 @@ async def test_base_client_sends_message_with_extensions(
819822
call_args, _ = mock_send_request.call_args
820823
kwargs = call_args[1]
821824
headers = kwargs.get('headers', {})
822-
assert 'X-A2A-Extensions' in headers
825+
assert 'A2A-Extensions' in headers
823826
assert (
824-
headers['X-A2A-Extensions']
827+
headers['A2A-Extensions']
825828
== 'https://example.com/test-ext/v1,https://example.com/test-ext/v2'
826829
)
827830

0 commit comments

Comments
 (0)