Hacktoberfest 2026 : les issues que les mainteneurs ont marquées pour octobre, ouvertes et accessibles aux débutants. Parcourir les issues Hacktoberfest

[A2A] RemoteA2aAgent(use_legacy=False): extension header written to state['http_kwargs'], ignored by a2a-sdk 1.x transports

Ouverte Adaptée aux débutants
#7,334 2 commentaires 0 réactions 1 personne assignée Voir sur GitHub

Les mainteneurs répondent en général sous 5 jours

Personne n'a encore pris cette issue.

Évaluation

Difficulté
2/5
Temps estimé
1-3 heures
Accessibilité débutants
84/100
Type d'issue
Bug
Clarté
Clairement spécifiée
Activité
Active
Stack technique
python
Domaine
api

Piste de recherche

Commencez dans google/adk/a2a/agent/interceptors/new_integration_extension.py:43-51 et comparez sa mise à jour du contexte avec le comportement du transport de a2a-sdk 1.x décrit dans l’issue. Préservez les paramètres de service existants et placez l’en-tête A2A-Extensions à l’endroit où les transports HTTP et gRPC le lisent, puis exécutez la reproduction in-process fournie et confirmez que le serveur capture l’en-tête.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Description

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.

Langage dominant
Python
Étoiles
21.6k
Forks
4k
Merge moyen
12 h 6 min
PR mergées (30 j)
4

Préparer son environnement

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Autres issues de google/adk-python

Toutes les issues de google/adk-python

Issues similaires

Plus d'issues Python

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.