Skip to content

Conversation

@nan-yu
Copy link
Collaborator

@nan-yu nan-yu commented Jan 27, 2026

Tested:

  • The contact_lookup client successfully connected to the contact_lookup agent and rendered the response correctly

Description

Replace this paragraph with a description of what this PR is changing or adding, and why. Consider including before/after screenshots.

List which issues are fixed by this PR. For larger changes, raising an issue first helps reduce redundant work.

Pre-launch Checklist

If you need help, consider asking for advice on the discussion board.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a significant and well-structured refactoring to create a centralized a2ui-agent package for managing A2UI schemas. The changes include a build-time hook to package schema files, a robust schema manager with fallback loading mechanisms, and a validator. The contact lookup sample has been updated to use this new package, which greatly improves maintainability and decouples the agent from hardcoded schemas. The overall approach is excellent. I've identified a few critical and high-severity issues related to exception handling and a NameError that could break the code at runtime, along with some medium-severity suggestions to improve the robustness of the build script and validation logic.

# See the License for the specific language governing permissions and
# limitations under the License.

from ..inference_strategy import InferenceStrategy
Copy link
Contributor

Choose a reason for hiding this comment

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

critical

The type hint List is used for selected_components on line 25, but it's not imported from the typing module. This will cause a NameError at runtime when this method is called.

Suggested change
from ..inference_strategy import InferenceStrategy
from typing import List
from ..inference_strategy import InferenceStrategy

Comment on lines 128 to 131
try:
repo_root = find_repo_root(os.path.dirname(__file__))
except Exception:
pass
Copy link
Contributor

Choose a reason for hiding this comment

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

critical

This try...except Exception: pass block is problematic. It swallows all exceptions, which can hide bugs, and if an exception does occur, repo_root will be undefined, leading to a NameError on the subsequent if repo_root: check. The find_repo_root function is safe and not expected to raise exceptions, making this block unnecessary and potentially buggy.

    repo_root = find_repo_root(os.path.dirname(__file__))

Comment on lines 103 to 104
except Exception:
pass
Copy link
Contributor

Choose a reason for hiding this comment

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

high

Using a broad except Exception: pass is a dangerous pattern as it can hide unexpected errors (e.g., TypeError, AttributeError) and make debugging difficult. The intended purpose is likely to handle cases where package resources are not found. It's better to catch a more specific exception. The PackageLoader.load method raises FileNotFoundError in case of failure, so catching that would be safer.

    except FileNotFoundError:
      # This is an expected failure when the package is not installed,
      # so we fall back to other loading mechanisms.
      pass

Comment on lines 120 to 121
except Exception:
pass
Copy link
Contributor

Choose a reason for hiding this comment

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

high

Similar to a previous point, this broad except Exception: pass can hide unexpected errors. The FileSystemLoader.load method is expected to raise a FileNotFoundError if the asset is not found, which is a valid fallback scenario. Catching this specific exception is safer and makes the code's intent clearer.

    except FileNotFoundError:
      # This is an expected failure when assets are not in the local src,
      # so we fall back to other loading mechanisms.
      pass

Comment on lines +12 to +15
# Add src to sys.path to import the constant
src_path = os.path.join(project_root, "src")
if src_path not in sys.path:
sys.path.insert(0, src_path)
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

Modifying sys.path directly, especially in a build script, is generally discouraged as it can lead to unpredictable behavior and make the build process fragile. A more robust approach would be to avoid this manipulation. Consider refactoring the shared constants (SPEC_VERSION_MAP, etc.) into a separate, simple configuration file (e.g., a JSON file or a simple Python file at the project root) that can be accessed by both the build hook and the runtime code without path manipulation.

Comment on lines 210 to 215
if self._validator:
self._validator.validate(parsed_json_data)
else:
# Fallback if validator failed to init but UI is on (shouldn't happen ideally)
logger.warning("Validator not initialized, skipping detailed schema validation.")
# We could choose to fail here, but let's just warn to avoid blocking if just validation setup failed.
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The fallback logic here, which logs a warning and skips validation if self._validator is not initialized, could mask a significant configuration or initialization error. If UI is enabled (self.use_ui is true), the validator should be considered essential. Instead of silently skipping validation, it would be safer to raise a RuntimeError to make the failure explicit and prevent the agent from producing potentially invalid UI responses.

                        if not self._validator:
                            raise RuntimeError("UI is enabled but A2UI validator is not initialized.")
                        self._validator.validate(parsed_json_data)

@nan-yu nan-yu force-pushed the update-contact-lookup-sample branch 2 times, most recently from ee5c8e9 to b6e614b Compare January 28, 2026 18:28
- Add a base InferenceStrategy class
- Add PackSpecsBuildHook to copy JSON schemas into the package during
  build time.
- Update pyproject.toml to include assets and configure the build hook.
- Implement A2uiSchemaManager for robust schema loading,  pruning, and
  prompt generation.
@nan-yu nan-yu force-pushed the update-contact-lookup-sample branch from b6e614b to 6bc12ec Compare January 28, 2026 18:36
Tested:
- [x] The contact_lookup client successfully connected to the contact_lookup
agent and rendered the response correctly.
@nan-yu nan-yu force-pushed the update-contact-lookup-sample branch from 6bc12ec to 6714d4f Compare January 28, 2026 20:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

1 participant