Skip to content

Conversation

@steven10a
Copy link
Collaborator

Fixes this reported BUG:

  • apiKey passed in via client initialization is not properly passed to moderation check

The fix:

  • Default to using the guardrail_llm, if the moderation endpoint does not exist with that client, fall back to creating a compatible OpenAI client via env variable
  • Documentation already mentions how an OpenAI API key is required for the Moderation check
  • Added tests

Future PR to allow configuring an api_key specific to the moderation check via the config file (will only be needed for users who are using non-openai models as their base client).

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR refactors the OpenAI moderation client handling logic to support third-party OpenAI-compatible providers. The key change is replacing the complex client reuse logic with a simpler approach that attempts to use the context client first and falls back to the default OpenAI client if the moderation endpoint returns a 404 error.

  • Simplified client selection logic by removing URL-based filtering
  • Added fallback mechanism for third-party providers that don't support moderation endpoints
  • Extracted API call logic into a dedicated helper function

Reviewed Changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

File Description
src/checks/moderation.ts Refactored client handling to use context client with 404-based fallback, added callModerationAPI helper function
src/tests/unit/checks/moderation-secret-keys.test.ts Added tests for context client usage and third-party provider fallback behavior

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +73 to +74
const contextCreateMock = vi.fn().mockImplementation(async () => {
contextClientUsed = true;
Copy link

Copilot AI Oct 31, 2025

Choose a reason for hiding this comment

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

[nitpick] The contextClientUsed flag is unnecessary. You can check if the mock was called using expect(contextCreateMock).toHaveBeenCalled() instead of tracking this manually.

Copilot uses AI. Check for mistakes.
Comment on lines +113 to +114
createMock.mockImplementation(async () => {
fallbackUsed = true;
Copy link

Copilot AI Oct 31, 2025

Choose a reason for hiding this comment

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

[nitpick] The fallbackUsed flag is unnecessary. You can verify fallback behavior by checking that createMock was called, which already indicates the fallback client was used.

Copilot uses AI. Check for mistakes.
@steven10a steven10a requested a review from Copilot October 31, 2025 14:46
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@steven10a steven10a requested a review from Copilot October 31, 2025 14:53
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 129 to 137
// Get client from context if available
let client: OpenAI | null = null;
if (ctx) {
const contextObj = ctx as Record<string, unknown>;
const candidate = contextObj.guardrailLlm;
if (candidate && candidate instanceof OpenAI) {
client = candidate;
}
};

const client = reuseClientIfOpenAI(ctx) ?? new OpenAI();
}
Copy link

Copilot AI Oct 31, 2025

Choose a reason for hiding this comment

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

[nitpick] The removal of base URL validation means the code will now attempt to use any OpenAI client from context, regardless of whether it points to the official API. While the 404 fallback handles providers without moderation support, this could lead to unnecessary API calls and latency when using third-party providers. Consider documenting this behavioral change or adding a configuration option to skip the initial attempt for known incompatible providers.

Copilot uses AI. Check for mistakes.
@steven10a steven10a requested a review from Copilot October 31, 2025 15:33
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@steven10a steven10a requested a review from Copilot October 31, 2025 15:39
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 151 to 153
if (isNotFoundError(error)) {
try {
resp = await callModerationAPI(new OpenAI(), data);
Copy link

Copilot AI Oct 31, 2025

Choose a reason for hiding this comment

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

A new OpenAI client is instantiated on every fallback. If multiple moderation checks occur with third-party providers, this creates unnecessary client instances. Consider caching the fallback client or instantiating it once at the module level.

Copilot uses AI. Check for mistakes.
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Only one moderation check will be called

Comment on lines 156 to 158
const errorMessage = fallbackError instanceof Error
? fallbackError.message
: String(fallbackError);
Copy link

Copilot AI Oct 31, 2025

Choose a reason for hiding this comment

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

The error message extraction logic is duplicated here and in the outer catch block (line 222). Consider extracting this into a helper function to reduce code duplication.

Copilot uses AI. Check for mistakes.
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

[nit]

Comment on lines 160 to 161
// Check if it's an API key error
if (errorMessage.includes('api_key') || errorMessage.includes('OPENAI_API_KEY')) {
Copy link

Copilot AI Oct 31, 2025

Choose a reason for hiding this comment

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

String-based error detection using includes is fragile and may produce false positives or miss variations in error messages. Consider checking for specific error types or status codes if the OpenAI SDK provides them.

Suggested change
// Check if it's an API key error
if (errorMessage.includes('api_key') || errorMessage.includes('OPENAI_API_KEY')) {
// Check if it's an API key error (HTTP 401 Unauthorized)
if (typeof fallbackError === 'object' && fallbackError !== null && 'status' in fallbackError && fallbackError.status === 401) {

Copilot uses AI. Check for mistakes.
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I'm okay with this. It is still throwing an appropriate error regardless, this check just adds more useful information for the user.

@gabor-openai gabor-openai changed the title Correctly use context model for moderation Fix: Correctly use context model for moderation Oct 31, 2025
Copy link
Collaborator

@gabor-openai gabor-openai left a comment

Choose a reason for hiding this comment

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

TY!

@gabor-openai gabor-openai merged commit 134eeb0 into main Oct 31, 2025
1 check passed
@steven10a steven10a deleted the dev/steven/api_key_bug branch November 10, 2025 16:02
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.

runGuardrails ignores provided OpenAI client and requires OPENAI_API_KEY environment variable

3 participants