Python: Add User-Agent to google-genai#13703
Conversation
…Client This adds the standard Semantic Kernel User-Agent to the Google AI and Vertex AI connectors when telemetry is enabled, matching the pattern used by the OpenAI connector.
There was a problem hiding this comment.
Automated Code Review
Reviewers: 4 | Confidence: 81%
✓ Correctness
This PR adds User-Agent header support to Google AI services by introducing a
_get_http_options()method onGoogleAIBaseand passing it to allClientconstructor calls. The implementation is correct, follows the same telemetry pattern used by other connectors (OpenAI, Azure AI Search, etc.), and properly handles the telemetry-disabled case by returningNone. The new tests cover both the enabled and disabled telemetry scenarios. No correctness issues found.
✓ Security Reliability
✗ Test Coverage
The PR adds User-Agent header propagation to all Google AI service classes via a shared
_get_http_options()method inGoogleAIBase. However, the test file only coversGoogleAIChatCompletion(non-streaming, non-VertexAI path). The samehttp_optionsplumbing was added toGoogleAITextCompletionandGoogleAITextEmbedding, plus VertexAI and streaming code paths in all three services, but none of those paths have test coverage. Additionally, the ``@pytest.mark.asynciodecorators are unnecessary per project convention (`asyncio_mode = 'auto'`), though harmless.
✗ Design Approach
The change correctly adds User-Agent header propagation to the Google AI connector by introducing
_get_http_options()on the base class. Two design issues stand out. First,_get_http_optionsbuilds its headers dict by copyingAPP_INFO({"semantic-kernel-version": "python/x.x.x"}) and then appending theUser-Agentkey. This leaks an Azure/OpenAI-specific telemetry key (semantic-kernel-version) into Google AI HTTP requests where it has no meaning and Google's API will ignore it. The method should construct the headers directly fromSEMANTIC_KERNEL_USER_AGENTrather than starting from the OpenAI-orientedAPP_INFOblob. Second, both test functions carry ``@pytest.mark.asynciodecorators, which the project explicitly discourages since `asyncio_mode = 'auto'` is already configured in `pyproject.toml`.
Flagged Issues
-
_get_http_optionscopies the entireAPP_INFOdict into HTTP headers sent to Google AI, including thesemantic-kernel-versionkey which is an OpenAI/Azure telemetry convention with no meaning at Google's API endpoint. The method should build headers using onlySEMANTIC_KERNEL_USER_AGENT(e.g.,{"headers": {USER_AGENT: SEMANTIC_KERNEL_USER_AGENT}}) to avoid leaking provider-specific metadata. - No tests for
GoogleAITextCompletionorGoogleAITextEmbedding, despite both receiving identicalhttp_optionschanges. At minimum, add a user-agent test for each service class to verify the header is passed through.
Suggestions
- Remove the ``@pytest
.mark.asynciodecorators — the project's pyproject.toml sets `asyncio_mode = 'auto'`, making them redundant. Other async tests in the same directory omit them. - Add a direct unit test for
GoogleAIBase._get_http_options()covering the enabled and disabled telemetry branches to decouple base-method testing from service-level integration. - Add tests for the VertexAI code path (
use_vertexai=True) and the streaming path (get_streaming_chat_message_contents) since both create separateClientinstances with their ownhttp_options=kwarg.
Automated review by markmcd's agents
Motivation and Context
Currently, the Python connectors for Google AI and Vertex AI don't pass the standard semantic-kernel user agent string. This PR adds the user agent header so that the Google API calls properly identify Semantic Kernel.
This aligns with the dotnet implementation, and our (Google DeepMind's) best practices.
Description
Sends the
User-Agentheader conditionally inGoogleAIChatCompletion,GoogleAITextCompletion, andGoogleAITextEmbedding, matching the OpenAI implementation as much as possible (gated behind telemetry flag, usingSEMANTIC_KERNEL_USER_AGENT).Contribution Checklist