[A2A] RemoteA2aAgent(use_legacy=False): extension header written to state['http_kwargs'], ignored by a2a-sdk 1.x transports
维护者通常 5 天内回复
还没有人认领这个 Issue。
评估
调研方向
从 google/adk/a2a/agent/interceptors/new_integration_extension.py:43-51 开始,并将其上下文更新与 issue 中描述的 a2a-sdk 1.x 传输行为进行比较。保留现有的服务参数,同时将 A2A-Extensions 标头放置在 HTTP 和 gRPC 传输读取它的位置,然后运行提供的进程内复现,并确认服务器捕获了该标头。
由索引模型根据 Issue 内容生成。
描述
Describe the Bug
With RemoteA2aAgent(use_legacy=False), ADK installs a request interceptor that is supposed to negotiate the new A2A-ADK integration extension (the one documented as the a2a-extension / v2 A2aAgentExecutor). The interceptor (google/adk/a2a/agent/interceptors/new_integration_extension.py:43-51, same code on main @ eb1a002 and on 2.7.1–2.10.0) writes the A2A-Extensions header into:
params.client_call_context.state['http_kwargs']
But on a2a-sdk 1.x, HTTP transports build outbound headers exclusively from ClientCallContext.service_parameters (a2a/client/transports/http_helpers.py:46-47 in 1.1.2):
if context and context.service_parameters:
http_kwargs['headers'] = context.service_parameters.copy()
Nothing in a2a-sdk 1.x reads client_call_context.state['http_kwargs'], so the extension header never reaches the server. The server therefore keeps running the legacy executor even though the client asked for the new integration. (The gRPC transport likewise reads service_parameters, a2a/client/transports/grpc.py:304-305.)
For reference, a2a-sdk 1.x's own auth interceptor writes Authorization into context.service_parameters (a2a/client/auth/interceptor.py:47-84), which is the convention downstream users follow too.
Steps to Reproduce
Self-contained, in-process, no network or credentials:
import asyncio
import httpx
from google.adk.a2a.utils.agent_to_a2a import to_a2a
from google.adk.agents import LlmAgent
from google.adk.agents.remote_a2a_agent import RemoteA2aAgent
from google.adk.models.base_llm import BaseLlm
from google.adk.models.llm_response import LlmResponse
from google.adk.runners import Runner
from google.adk.sessions import InMemorySessionService
from google.genai import types
CAPTURED: dict[str, str] = {}
class CaptureMiddleware:
def __init__(self, app):
self.app = app
async def __call__(self, scope, receive, send):
if scope["type"] == "http":
headers = {k.decode().lower(): v.decode() for k, v in scope["headers"]}
if "a2a-extensions" in headers:
CAPTURED[headers["a2a-extensions"]] = headers["a2a-extensions"]
await self.app(scope, receive, send)
class Scripted(BaseLlm):
async def generate_content_async(self, req, stream=False):
yield LlmResponse(content=types.Content(role="model", parts=[types.Part(text="ok")]))
async def main():
server = to_a2a(LlmAgent(name="remote", model=Scripted(model="x"), instruction="x"))
async with server.router.lifespan_context(server):
remote = RemoteA2aAgent(
name="remote",
agent_card="http://localhost:8000/.well-known/agent-card.json",
use_legacy=False,
httpx_client=httpx.AsyncClient(
transport=httpx.ASGITransport(app=CaptureMiddleware(server))
),
)
runner = Runner(
app_name="caller",
agent=remote,
session_service=InMemorySessionService(),
auto_create_session=True,
)
async for _ in runner.run_async(
user_id="u", session_id="s",
new_message=types.Content(role="user", parts=[types.Part(text="hi")]),
):
pass
print("A2A-Extensions seen by server:", CAPTURED or "NOT RECEIVED")
asyncio.run(main())
Observed Behavior
A2A-Extensions seen by server: NOT RECEIVED
Adding a custom request_interceptors entry that puts the header into params.client_call_context.service_parameters instead makes the server receive it, which confirms the interceptor pipeline runs and the failure is specifically the state['http_kwargs'] write target.
Expected Behavior
RemoteA2aAgent(use_legacy=False) causes the A2A-Extensions: https://google.github.io/adk-docs/a2a/a2a-extension/ header to actually reach the remote server on a2a-sdk 1.x.
Environment Details
- google-adk: 2.7.1 (pinned in my project); the interceptor source hasn't been updated since
- a2a-sdk: 1.1.2, 1.1.5 also affected
- Python: 3.14
- OS: macOS 15
Impact / Suggested direction
Impact is silent: no error, the server just keeps legacy behavior. This specifically blocks use_legacy=False from doing anything on the 1.x client stack, and it masks verification of the v2-executor bugs tracked in #7247 / #6343 (their suggested workaround of activating the v2 path via use_legacy=False is a no-op on a2a-sdk 1.x).
Suggested fix: in new_integration_extension.py, write the header into params.client_call_context.service_parameters (initializing ClientCallContext if absent) and merge with any existing mapping.
- 主要语言
- Python
- 星标
- 21.6k
- 派生
- 4k
- 平均合并
- 12 小时 6 分钟
- 30 天内合并 PR
- 4
环境准备
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
google/adk-python 的其他 Issue
-
Redis append_event stamps last_update_time with the wall clock, not the event timestamp可能已有人在做 @sanketpatil06 于 1 天前认领。 未关闭services
难度 2/5 1-3 小时 新手友好度 88/100
google/adk-python#7292 · 2 条评论 · 已指派 1 人 ·
维护者通常 5 天内回复
-
GoogleOidcVerifier treats string "false" as a verified email claim可能已有人在做 @surajksharma07 于 1 天前认领。 未关闭core
难度 2/5 1-3 小时 新手友好度 82/100
google/adk-python#7289 · 5 条评论 · 已指派 1 人 ·
维护者通常 5 天内回复
-
RestApiTool raises uncaught KeyError when a required path param is omitted可能已有人在做 @llalitkumarrr 于 1 天前认领。 未关闭tools
难度 2/5 1-3 小时 新手友好度 78/100
google/adk-python#7282 · 2 条评论 · 已指派 1 人 ·
维护者通常 5 天内回复
-
CredentialsManager should also extract scopes when populating auth schemes可能已有人在做 @sanketpatil06 于 4 天前认领。 未关闭core needs review
难度 2/5 1-3 小时 新手友好度 78/100
google/adk-python#7266 · 2 条评论 · 已指派 1 人 ·
维护者通常 5 天内回复
-
OAuth2 Discovery method fails because FastMCP with GoogleProvider (OAuth) returns issuerUrl with trailing slash可能已有人在做 @sanketpatil06 于 4 天前认领。 未关闭mcp
难度 2/5 1-3 小时 新手友好度 78/100
google/adk-python#7265 · 3 条评论 · 已指派 1 人 ·
维护者通常 5 天内回复
查看 google/adk-python 的全部 Issue
相似的 Issue
-
ACK_WAITING HELP_WANTED UPDATE_CS
难度 2/5 1-3 小时 新手友好度 78/100
OWASP/CheatSheetSeries#2458 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 82/100
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 90/100
BasedHardware/omi#19711 ·
维护者通常 1 天内回复
-
Qwen3_5MoeModel no longer returns router_logits, breaking aux loss with output_router_logits=True未关闭
难度 2/5 1-3 小时 新手友好度 78/100
huggingface/transformers#49172 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 82/100
vllm-project/vllm-metal#885 ·
维护者通常 1 天内回复