Skip to content

Commit fb01bed

Browse files
committed
Merge remote-tracking branch 'upstream/main' into delete-minimal-catalog
2 parents 932f051 + 325af82 commit fb01bed

1 file changed

Lines changed: 87 additions & 0 deletions

File tree

agent_sdks/python/agent_development.md

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,3 +397,90 @@ agent_card = AgentCard(
397397
)
398398
)
399399
```
400+
401+
#### Setting or Propagating Client Capabilities on Remote A2A Agents
402+
403+
When calling remote A2A agents (such as delegating to a sub-agent or proxying to a backend A2A stubby agent) via ADK `RemoteA2aAgent`, you must ensure that the remote agent receives the client's UI capabilities in its request metadata under `a2uiClientCapabilities`.
404+
405+
You can configure an `A2aRemoteAgentConfig` with a `before_request` interceptor (`RequestInterceptor`) to inject this metadata. There are two common scenarios:
406+
407+
##### Scenario 1: Propagating Capabilities from Session State (Orchestrator)
408+
409+
When an orchestrator receives an A2A request from a client, it captures the client capabilities into session state. When calling a sub-agent via `RemoteA2aAgent`, the interceptor propagates those capabilities from `ctx.session.state`:
410+
411+
```python
412+
from a2a.types import Message as A2AMessage
413+
from a2ui.schema.constants import A2UI_CLIENT_CAPABILITIES_KEY
414+
from google.adk.a2a.agent.config import A2aRemoteAgentConfig, ParametersConfig, RequestInterceptor
415+
from google.adk.agents.invocation_context import InvocationContext
416+
from google.adk.agents.remote_a2a_agent import RemoteA2aAgent
417+
418+
async def propagate_capabilities_interceptor(
419+
ctx: InvocationContext,
420+
message: A2AMessage,
421+
params: ParametersConfig,
422+
) -> tuple[A2AMessage, ParametersConfig]:
423+
# Retrieve capabilities saved earlier in session context state
424+
if ctx.session and ctx.session.state:
425+
client_capabilities = ctx.session.state.get("client_capabilities")
426+
if client_capabilities:
427+
if message.metadata is None:
428+
message.metadata = {}
429+
message.metadata[A2UI_CLIENT_CAPABILITIES_KEY] = client_capabilities
430+
return message, params
431+
432+
remote_agent_config = A2aRemoteAgentConfig(
433+
request_interceptors=[
434+
RequestInterceptor(before_request=propagate_capabilities_interceptor)
435+
]
436+
)
437+
438+
remote_a2a_agent = RemoteA2aAgent(
439+
name="subagent_name",
440+
agent_card=subagent_card,
441+
config=remote_agent_config,
442+
# ...
443+
)
444+
```
445+
446+
##### Scenario 2: Explicitly Setting Capabilities for Proxy Agents
447+
448+
When acting as a proxy connecting a non-A2A frontend (such as Orcas UI) to a remote A2A backend stubby agent, the incoming frontend request does not have A2A metadata. The proxy agent configures a `before_request` interceptor to explicitly construct and inject the supported client capabilities on outgoing requests:
449+
450+
```python
451+
from a2a.types import Message as A2AMessage
452+
from a2ui.schema.constants import A2UI_CLIENT_CAPABILITIES_KEY
453+
from google.adk.a2a.agent.config import A2aRemoteAgentConfig, ParametersConfig, RequestInterceptor
454+
from google.adk.agents.invocation_context import InvocationContext
455+
from google.adk.agents.remote_a2a_agent import RemoteA2aAgent
456+
457+
async def set_proxy_capabilities_interceptor(
458+
ctx: InvocationContext,
459+
message: A2AMessage,
460+
params: ParametersConfig,
461+
) -> tuple[A2AMessage, ParametersConfig]:
462+
if message.metadata is None:
463+
message.metadata = {}
464+
465+
# Explicitly define what the proxy or UI client supports
466+
message.metadata[A2UI_CLIENT_CAPABILITIES_KEY] = {
467+
"supportedCatalogIds": [
468+
"https://a2ui.org/specification/v0_9/catalogs/basic/catalog.json"
469+
],
470+
"inlineCatalogs": True,
471+
}
472+
return message, params
473+
474+
proxy_agent_config = A2aRemoteAgentConfig(
475+
request_interceptors=[
476+
RequestInterceptor(before_request=set_proxy_capabilities_interceptor)
477+
]
478+
)
479+
480+
remote_stubby_agent = RemoteA2aAgent(
481+
name="stubby_backend",
482+
agent_card=agent_card,
483+
config=proxy_agent_config,
484+
# ...
485+
)
486+
```

0 commit comments

Comments
 (0)