Repository navigation
Conversation
Contributor
There was a problem hiding this comment.
Code Review
This pull request updates the Gemini Enterprise A2UI agent samples (v0.8 and v0.9) to integrate with the latest a2ui-agent-sdk and a2ui-a2a libraries, refactoring the agent, executor, and prompt building logic to support dynamic catalog negotiation and validation. The review feedback highlights critical issues that need to be addressed: consecutive user messages in the session history during retries can violate Gemini API role requirements and cause 400 errors; direct dictionary lookups on unsupported UI versions can trigger KeyErrors; and the retry loops do not catch general exceptions, which could crash the handlers on transient runner or API errors.
nan-yu
force-pushed
the
docs/python-agent-renderer-state
branch
from
October 16, 2026 19:34
0df8f19 to
cf5db13
Compare
nan-yu
force-pushed
the
refactor/samples-gemini-enterprise-per-request-processors
branch
from
October 16, 2026 19:34
084621d to
2c45a66
Compare
nan-yu
force-pushed
the
docs/python-agent-renderer-state
branch
from
October 16, 2026 19:51
cf5db13 to
6e471f6
Compare
nan-yu
force-pushed
the
refactor/samples-gemini-enterprise-per-request-processors
branch
2 times, most recently
from
October 16, 2026 19:53
4ea0308 to
e956965
Compare
nan-yu
force-pushed
the
docs/python-agent-renderer-state
branch
from
October 16, 2026 19:53
6e471f6 to
74fb3d8
Compare
nan-yu
force-pushed
the
refactor/samples-gemini-enterprise-per-request-processors
branch
3 times, most recently
from
October 16, 2026 20:23
f9f8e20 to
3a1b670
Compare
nan-yu
force-pushed
the
docs/python-agent-renderer-state
branch
from
October 16, 2026 22:57
229788b to
7b4baed
Compare
nan-yu
force-pushed
the
refactor/samples-gemini-enterprise-per-request-processors
branch
from
October 16, 2026 22:57
5dae2a5 to
7d075de
Compare
…mples The v0.8 Agent Engine and Cloud Run samples and the v0.9 sample now follow the SDK's per-request model, as the core samples do. 1. Each request gets its own `A2uiRequestProcessor`, negotiated from the capabilities the client sent, passed through unchanged. Gemini Enterprise doesn't name the catalogs it renders, so a request without capabilities gets `GEMINI_ENTERPRISE_CAPABILITIES`. In the v0.8 samples these use the unkeyed shape the v0.8 specification defines. 2. The system prompt is built from that processor, and responses are read with `open_stream` or `parse_response` and turned into A2A parts with `stream_response_to_parts` and `to_a2a_parts`. On a validation error the agent asks the model to try again. 3. The v0.9 sample builds a Material catalog and the Gemini Enterprise composite catalog in `catalogs.py`, instead of using the basic catalog. Its examples use the Material catalog. 4. The pins move to `a2ui-agent-sdk>=0.9.0` and `a2ui-a2a>=0.1.0`, in `pyproject.toml` and the Agent Engine `deploy.py`, and the unused `jsonschema` dependency is dropped. Requires the SDK to read unkeyed v0.8 capabilities. Signed-off-by: Nan Yu <nanyu@google.com>
When the model returns no text, the v0.8 samples sent another user message to retry. That adds a second user turn with no model turn between them, so they now stop and send the text-only error instead. Signed-off-by: Nan Yu <nanyu@google.com>
…epository The samples now use a2ui-a2a and APIs of a2ui-agent-sdk that aren't on PyPI yet, so their dependencies didn't resolve. Each sample points a2ui-a2a, a2ui-agent-sdk and a2ui-core at the packages in this repository with [tool.uv.sources] until they are published. The v0.9 lock file follows. Signed-off-by: Nan Yu <nanyu@google.com>
nan-yu
force-pushed
the
docs/python-agent-renderer-state
branch
from
October 16, 2026 23:07
7b4baed to
eebbda5
Compare
nan-yu
force-pushed
the
refactor/samples-gemini-enterprise-per-request-processors
branch
from
October 16, 2026 23:07
7d075de to
106b29a
Compare
…' into refactor/samples-gemini-enterprise-per-request-processors Signed-off-by: Nan Yu <nanyu@google.com>
- An empty model response no longer becomes a final message without parts. The agent stops without retrying and sends the error text, as the v0.8 samples do. - The agent's final item holds the whole response again, also when streaming, since Gemini Enterprise renders only the parts of the final message. The executor sends the final item's parts instead of collecting the parts of every item, so the parts of a failed streamed attempt aren't sent along with the retry. - A streamed response that fails after sending parts isn't retried, since the client may already show those parts. - In SSE mode, the final aggregated ADK event, which repeats the partial text, is skipped. - The examples are read from the sample directory rather than the working directory, in the agent and in `prompt_builder.py`. - The executor logs the protocol version string instead of the enum repr. Signed-off-by: Nan Yu <nanyu@google.com>
…ecutor The executor activates the A2UI extension when the client requests it, and otherwise answers with A2UI v0.8, as the v0.9 executor does, instead of a hardcoded version. This removes the unused imports, and the unused `contact_agent` in deploy.py. Signed-off-by: Nan Yu <nanyu@google.com>
… SDKs The samples need SDK releases that aren't on PyPI yet. Their `[tool.uv.sources]` path entries point outside the sample directory, which Cloud Run's `--source .` doesn't upload, and the Agent Engine deploy.py installed `a2ui-a2a` from PyPI, where it doesn't exist. - `build_sdk_wheels.sh` builds wheels of a2ui-core, a2ui-agent-sdk and a2ui-a2a from this repository. With `--use-wheels` it also points a project's sources at them and relocks it. - Both deploy.sh scripts deploy a temporary copy of the sample with the wheels, its sources pointed at them and a fresh uv.lock. The path sources stay for local development. - deploy.py builds the wheels into `wheels/` and lists them in both `requirements` and `extra_packages`. - The pins move to `a2ui-agent-sdk>0.9.0` and `a2ui-a2a>0.1.0`. 0.9.0 and 0.1.0 have no `open_stream` or `to_a2a_parts`, and the `>` pins also admit this repository's dev builds. `a2ui-core` is listed directly, since the samples import it and uv only applies the source of a direct dependency. - The Agent Engine sample requires `a2a-sdk[http-server]`, locally and on the engine, since the A2A agent template's `set_up()` needs `sse-starlette`. - The Agent Engine README names deploy.py instead of main.py and runs `uv sync` instead of `uv sync --locked`, since the sample has no uv.lock. Signed-off-by: Nan Yu <nanyu@google.com>
The v0.9 README says when the agent doesn't retry and that its final item holds the whole response. The overlong lines in the v0.8 and v0.9 READMEs are rewrapped to 80 columns. Signed-off-by: Nan Yu <nanyu@google.com>
…' into refactor/samples-gemini-enterprise-per-request-processors Signed-off-by: Nan Yu <nanyu@google.com>
…ls.sh Signed-off-by: Nan Yu <nanyu@google.com>
…-gemini-enterprise-per-request-processors Signed-off-by: Nan Yu <nanyu@google.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #3271. The unkeyed v0.8 capabilities need #3265, which has merged.
The v0.8 Agent Engine and Cloud Run samples and the v0.9 sample now follow the per-request model from #3269 and #3270, as the core samples do.
A2uiRequestProcessor, negotiated from the capabilities the client sent, passed through unchanged. Gemini Enterprise doesn't name the catalogs it renders, so a request without capabilities getsGEMINI_ENTERPRISE_CAPABILITIES. In the v0.8 samples these use the unkeyed shape the v0.8 specification defines.open_streamorparse_responseand turned into A2A parts withstream_response_to_partsandto_a2a_parts. On a validation error the agent asks the model to try again. It doesn't retry an empty response, or a streamed response that already sent parts, and sends an error message instead. Inv0_9/agent.pythe final item holds the whole response, also when streaming, because Gemini Enterprise renders only the final message's parts, and the executor sends that item's parts.catalogs.py, instead of using the basic catalog. Its examples use the Material catalog. The README explains how the agent uses the SDK.a2ui-agent-sdk>0.9.0anda2ui-a2a>0.1.0, since 0.9.0 and 0.1.0 have noopen_streamorto_a2a_parts.a2ui-coreis listed directly, since the samples import it. The unusedjsonschemadependency is dropped.Deployment
These SDK releases aren't on PyPI yet (a2ui-a2a has no release there at all), so the samples run on the SDKs in this repository through
[tool.uv.sources]path entries, and the v0.9uv.lockrecords them as editable paths. A deployment can't reach those paths, so:build_sdk_wheels.shbuilds wheels of a2ui-core, a2ui-agent-sdk and a2ui-a2a. With--use-wheelsit points a project's sources at them and relocks it.deploy.shscripts (v0.9, v0.8 Cloud Run) deploy a temporary copy of the sample that holds the wheels, with its sources pointed at them and a freshuv.lock.deploy.pybuilds the wheels intowheels/and lists them in bothrequirementsandextra_packages. It also requiresa2a-sdk[http-server], since the A2A agent template'sset_up()needssse-starlette.Once the SDKs are released, the path sources and the wheel step can go.
Testing
uv sync --all-packages, andimport agent, agent_executorin each sample.uv run pytest samples/agent/adk/testspasses. ruff (0.15.20) and pyink are clean on the changed Python files.createSurface, the SSE aggregated event isn't read twice, and all 13 examples come back as valid parts, streaming and not.uv lock --check,uv sync --lockedanduv exportpluspip installinto fresh venvs, and imports the agent with the local SDK wheels. For Agent Engine,deploy.main()runs with Vertex AI faked out. Itsextra_packagesare packed the way the Vertex AI SDK packs them, and itsrequirementsinstall with pip into a fresh Python 3.13 venv, where the agent imports.