Skip to content

Python: Add User-Agent to google-genai#13703

Open
markmcd wants to merge 4 commits intomicrosoft:mainfrom
markmcd:python-google-user-agent
Open

Python: Add User-Agent to google-genai#13703
markmcd wants to merge 4 commits intomicrosoft:mainfrom
markmcd:python-google-user-agent

Conversation

@markmcd
Copy link

@markmcd markmcd commented Mar 24, 2026

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-Agent header conditionally in GoogleAIChatCompletion, GoogleAITextCompletion, and GoogleAITextEmbedding, matching the OpenAI implementation as much as possible (gated behind telemetry flag, using SEMANTIC_KERNEL_USER_AGENT).

Contribution Checklist

…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.
@markmcd markmcd changed the title Python: Conditionally add semantic-kernel User-Agent to google-genai … Python: Conditionally add semantic-kernel User-Agent to google-genai Mar 24, 2026
@markmcd markmcd changed the title Python: Conditionally add semantic-kernel User-Agent to google-genai Python: Add User-Agent to google-genai Mar 24, 2026
Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

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 on GoogleAIBase and passing it to all Client constructor 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 returning None. 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 in GoogleAIBase. However, the test file only covers GoogleAIChatCompletion (non-streaming, non-VertexAI path). The same http_options plumbing was added to GoogleAITextCompletion and GoogleAITextEmbedding, plus VertexAI and streaming code paths in all three services, but none of those paths have test coverage. Additionally, the ``@pytest.mark.asyncio decorators 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_options builds its headers dict by copying APP_INFO ({"semantic-kernel-version": "python/x.x.x"}) and then appending the User-Agent key. 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 from SEMANTIC_KERNEL_USER_AGENT rather than starting from the OpenAI-oriented APP_INFO blob. Second, both test functions carry ``@pytest.mark.asyncio decorators, which the project explicitly discourages since `asyncio_mode = 'auto'` is already configured in `pyproject.toml`.

Flagged Issues

  • _get_http_options copies the entire APP_INFO dict into HTTP headers sent to Google AI, including the semantic-kernel-version key which is an OpenAI/Azure telemetry convention with no meaning at Google's API endpoint. The method should build headers using only SEMANTIC_KERNEL_USER_AGENT (e.g., {"headers": {USER_AGENT: SEMANTIC_KERNEL_USER_AGENT}}) to avoid leaking provider-specific metadata.
  • No tests for GoogleAITextCompletion or GoogleAITextEmbedding, despite both receiving identical http_options changes. At minimum, add a user-agent test for each service class to verify the header is passed through.

Suggestions

  • Remove the ``@pytest.mark.asyncio decorators — 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 separate Client instances with their own http_options= kwarg.

Automated review by markmcd's agents

@markmcd markmcd requested a review from a team as a code owner March 25, 2026 09:00
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.

1 participant