Skip to content

[bot] AzureOpenAI: GetOpenAIResponseClient not delegated or instrumented in InstrumentedAzureOpenAIClient #74

Description

@braintrust-bot

Summary

InstrumentedAzureOpenAIClient does not override GetOpenAIResponseClient() or GetOpenAIResponseClient(string deploymentName). Since the instrumented client uses the protected no-arg (mock) constructor of AzureOpenAIClient rather than a real HTTP pipeline, calling either overload on the instrumented client will not correctly delegate to _client — making the Responses API effectively inaccessible through a Braintrust-wrapped Azure OpenAI client and producing no spans.

This is distinct from issue #30, which covers InstrumentedOpenAIClient (the plain OpenAI integration). InstrumentedAzureOpenAIClient is a separate class that also needs an override.

What is missing

AzureOpenAIClient (from Azure.AI.OpenAI v2.9.0-beta.1, the version pinned in this repo) exposes:

public override OpenAI.Responses.OpenAIResponseClient GetOpenAIResponseClient();
public override OpenAI.Responses.OpenAIResponseClient GetOpenAIResponseClient(string deploymentName);

InstrumentedAzureOpenAIClient overrides several methods by delegating to _client, but GetOpenAIResponseClient is not among them:

// src/Braintrust.Sdk.AzureOpenAI/InstrumentedAzureOpenAIClient.cs
public override ChatClient GetChatClient(string deploymentName)
    => InstrumentedChatClient.Create(_client.GetChatClient(deploymentName), ...); // ✅

public override EmbeddingClient GetEmbeddingClient(string deploymentName)
    => _client.GetEmbeddingClient(deploymentName); // ✅ (untraced, tracked in #71)

// GetOpenAIResponseClient — ❌ not overridden at all

Because InstrumentedAzureOpenAIClient is constructed with:

: base() // uses the protected no-arg constructor (designed for mocking/subclassing)

…the inherited AzureOpenAIClient.GetOpenAIResponseClient() implementation (called when the method is not overridden) runs against an empty base-class state with no real HTTP pipeline, credentials, or Azure endpoint. The returned OpenAIResponseClient will be misconfigured and calls through it will fail.

The fix needs both a delegation to _client.GetOpenAIResponseClient(deploymentName) and wrapping the result with an instrumented client (analogous to how GetChatClient wraps the returned ChatClient with InstrumentedChatClient).

Impact

Any user who wraps an AzureOpenAIClient with BraintrustAzureOpenAI.WithBraintrust(client) and then calls GetOpenAIResponseClient() to use the Azure Responses API will get a broken client rather than a working but uninstrumented one. The Responses API on Azure OpenAI is documented as a production-ready endpoint for latest OpenAI models like gpt-4o and o1.

Braintrust docs status

not_found — the Braintrust Azure OpenAI integration docs document chat completion instrumentation but do not mention the Responses API. Issue #30 tracks the plain OpenAI side. This is the Azure-specific gap.

Upstream sources

Local files inspected

  • src/Braintrust.Sdk.AzureOpenAI/InstrumentedAzureOpenAIClient.cs — overrides GetChatClient, GetOpenAIFileClient, GetEmbeddingClient, GetImageClient, GetAudioClient; GetOpenAIResponseClient is absent
  • src/Braintrust.Sdk.AzureOpenAI/InstrumentedAzureOpenAIClient.cs line 38: base() call uses the no-arg protected constructor, so unoverridden virtual methods run against an empty pipeline
  • src/Braintrust.Sdk.AzureOpenAI/Braintrust.Sdk.AzureOpenAI.csprojAzure.AI.OpenAI v2.9.0-beta.1
  • Related: issue [BOT ISSUE] OpenAI Responses API not instrumented #30 covers InstrumentedOpenAIClient.GetResponsesClient() for the plain OpenAI integration
  • Related: issue [bot] AzureOpenAI EmbeddingClient calls are not instrumented #71 covers InstrumentedAzureOpenAIClient.GetEmbeddingClient() (same delegation-without-instrumentation pattern)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions