google / google/adk-python

build_agent_card(): agent_registry cards stay streaming:false after #6673, and the streaming= parameter becomes unreachable

オープン
#6,778 コメント 4 件 リアクション 0 件 担当者 2 名 @wuliang229 が担当を希望しています GitHub で見る
agent config needs review
主要言語
Python
スター
21.5k
フォーク
4k
平均マージ
1日 14時間
マージ済み PR(30日)
37

説明

Splitting this out of #6672 as suggested there, so it does not block #6673.

Two things, one root cause. In `_compat.build_agent_card()`:

```python
default_capabilities = {"streaming": streaming, "push_notifications": False}
...
"capabilities": _as_dict(capabilities) or default_capabilities,
```

The `streaming=` parameter only reaches the card through `default_capabilities`, and that is consulted only when `capabilities` is falsy. The two call sites take different branches, and #6673 changes which branch each one takes.

### 1. Cards built through `agent_registry` stay `streaming: false`

`src/google/adk/integrations/agent_registry/agent_registry.py:640` passes neither `capabilities` nor `streaming`:

```python
agent_card = _compat.build_agent_card(
name=name,
description=description,
version=version,
url=url,
protocol_binding=getattr(binding, "value", binding),
protocol_version=protocol_version,
skills=skills,
default_input_modes=["text"],
default_output_modes=["text"],
)
```

So it falls to `default_capabilities`, where `streaming` defaults to `False`. #6673 changes `AgentCardBuilder`'s default, which this call site does not go through, so a card built here advertises `streaming: false` after that fix as well as before it.

### 2. `streaming=` becomes unreachable

`src/google/adk/a2a/utils/agent_card_builder.py:85` passes `capabilities=self._capabilities` (line 94) and never passes `streaming=`. #6673 changes that field to:

```python
self._capabilities = capabilities or AgentCapabilities(streaming=True)
```

which is always truthy, so `_as_dict(capabilities)` wins and `default_capabilities` is never evaluated from this caller. Together with (1), no call site in the repository can reach the `streaming=` parameter, and a caller who sets it gets no effect and no warning.

### Reproduced

`google-adk 2.6.1`, `a2a-sdk 1.1.2`, Python 3.13.5, clean venv. `build_agent_card` is byte-identical between 2.6.1 and current main, so this applies to main.

```python
from google.adk.a2a import _compat
from a2a.types import AgentCapabilities

binding = getattr(_compat.TP_HTTP_JSON, "value", _compat.TP_HTTP_JSON)
common = dict(name="x", description="d", version="1", url="http://h/a",
skills=[], default_input_modes=["text"],
default_output_modes=["text"])

# the agent_registry call shape
card = _compat.build_agent_card(protocol_binding=binding, **common)
print(card.capabilities.streaming) # False

# streaming= is honoured, but only when capabilities is absent
card = _compat.build_agent_card(protocol_binding=binding, streaming=True, **common)
print(card.capabilities.streaming) # True

# once capabilities is passed, which is what #6673 makes the default, it is ignored
card = _compat.build_agent_card(protocol_binding=binding,
capabilities=AgentCapabilities(streaming=True),
streaming=False, **common)
print(card.capabilities.streaming) # True, streaming= had no effect
```

### Possible shapes

1. Thread `capabilities` through the `agent_registry` call site the way `AgentCardBuilder` does, and drop `streaming=` from `build_agent_card` once nothing reaches it.
2. Keep `streaming=` and make it compose rather than fall back, so it applies on top of a passed `capabilities`. This changes the meaning of an existing parameter for anyone already passing both.
3. Keep `streaming=` and document it as the no-capabilities convenience path only.

I have not opened a pull request because (2) changes the behaviour of an existing parameter and (1) removes public surface, so the choice looks like yours rather than mine. Happy to send whichever you prefer.

コントリビューションガイド

コントリビューションガイドを開く

評価

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

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

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