Skip to content

Conversation

@jonsharkey
Copy link
Collaborator

No description provided.

@jonsharkey jonsharkey force-pushed the python_sdk branch 2 times, most recently from 8acb82e to c44b5e8 Compare January 6, 2026 21:58
@jonsharkey
Copy link
Collaborator Author

Closes #375

@jonsharkey jonsharkey requested a review from wrenj January 6, 2026 22:02
@@ -0,0 +1,273 @@
# Copyright 2025 Google LLC
Copy link
Collaborator

@wrenj wrenj Jan 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we call this file

send_a2ui_to_client_toolset.py

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done



@experimental
class A2uiToolset(base_toolset.BaseToolset):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SendA2uiToClientToolset

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

from google.genai import types as genai_types

logger = logging.getLogger(__name__)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs a lot of documentation at the top to explain how to use it, with examples

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

raise ValueError("A2UI schema is empty")
return {"type": "array", "items": a2ui_schema}

async def canonical_a2ui_enabled(self, ctx: ReadonlyContext) -> bool:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

follow a2aagentexecutorpattern

_resolve_a2ui_enabled
_resolve_a2ui_schema

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

A2UI_JSON_ARG_NAME = "a2ui_json"

def __init__(self, toolset: A2uiToolset):
self._toolset = toolset
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oof maybe just pass the

a2ui_schema: Union[dict[str, Any], A2uiSchemaProvider]

in

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

return {"error": err}

@experimental
class A2uiPartConverter:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SendA2uiToClientPartConverter

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

def __init__(self):
self._a2ui_schema = None

def set_a2ui_schema(self, a2ui_schema: dict[str, Any]):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we base this off the schema provider pattern above?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not possible, because this function is passed to A2aAgentExecutor in the config.
The somewhat hacky solution (which already existed) is to call set_a2ui_schema on every request in _prepare_session. This is also where the schema is recreated based on the incoming request, so it works.

Yesterday you mentioned we could do part conversion elsewhere: but still, we want A2aAgentExecutor to have a working part converter whenever it decides to use it, which is not controlled by this code directly.

Let me know what you think: is this good enough for now?

@classmethod
def load_example(cls, path: str, a2ui_schema: dict[str, Any]) -> dict[str, Any]:
example_str = Path(path).read_text()
def __init__(self, a2ui_enabled_provider: A2uiToolset.A2uiEnabledProvider, a2ui_schema_provider: A2uiToolset.A2uiSchemaProvider):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think don't nest the provider in the toolset

A2uiEnabledProvider
A2uiSchemaProvider

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

The wrapped A2UI schema.
"""
a2ui_schema = self._a2ui_schema_provider(ctx)
return A2uiToolset.wrap_schema(a2ui_schema)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

feels outside of the A2uiToolset, also clarify name

maybe wrap_as_json_array(a2ui_schema)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I moved it to a2ui_extension.py and renamed it. WDYT?

@jonsharkey jonsharkey force-pushed the python_sdk branch 2 times, most recently from 7050d5b to 3bab73e Compare January 8, 2026 17:24
@jonsharkey jonsharkey requested a review from wrenj January 8, 2026 17:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants