Skip to content

fix(media-understanding): allow aws-sdk auth mode in image tool [AI-assisted]#72066

Closed
luyao618 wants to merge 1 commit into
openclaw:mainfrom
luyao618:fix/image-bedrock-aws-sdk-auth
Closed

fix(media-understanding): allow aws-sdk auth mode in image tool [AI-assisted]#72066
luyao618 wants to merge 1 commit into
openclaw:mainfrom
luyao618:fix/image-bedrock-aws-sdk-auth

Conversation

@luyao618

Copy link
Copy Markdown
Contributor

🤖 AI-assisted (built with Claude Code via Hermes orchestration). Test level: fully tested. Prompt summary available on request.

Summary

  • Problem: The image tool fails for all Bedrock models when using AWS SDK credential resolution (IAM role, instance profile, AWS_PROFILE). requireApiKey throws No API key resolved for provider "amazon-bedrock" (auth mode: aws-sdk) even though chat/completion with the same model works fine.
  • Why it matters: Any user relying on AWS SDK credential chains (the standard for IAM roles, EC2 instances, ECS tasks) cannot use image analysis with Bedrock models at all.
  • What changed: Added requireApiKeyAllowAwsSdk helper in model-auth-runtime-shared.ts that returns an empty string for aws-sdk mode instead of throwing. Replaced requireApiKey calls in image.ts (2 sites) and runner.entries.ts (1 site) with the new helper.
  • What did NOT change (scope boundary): requireApiKey itself is unchanged — all non-aws-sdk auth modes still throw on missing keys. The chat/completion path's existing allowMissingApiKeyModes mechanism is untouched.

Change Type (select all)

  • Bug fix

Scope (select all touched areas)

  • Media understanding (src/media-understanding/)
  • Agent auth (src/agents/model-auth*)

Linked Issue/PR

Root Cause

  • Root cause: resolveImageRuntime in image.ts unconditionally called requireApiKey, which throws when auth.apiKey is empty regardless of auth.mode. For amazon-bedrock with aws-sdk mode, no static API key exists — the AWS SDK resolves credentials at call time. The chat path already handled this via allowMissingApiKeyModes: ["aws-sdk"], but the image path did not.
  • Missing detection / guardrail: No test covered the aws-sdk auth mode path in the image tool.
  • Contributing context: The image tool auth was written before Bedrock's aws-sdk credential mode was widely used, and the escape hatch was only added to the chat path.

Regression Test Plan

  • Coverage level that should have caught this:
    • Unit test
  • Target test or file: src/media-understanding/image.test.ts
  • Scenario the test should lock in: describeImageWithModel with auth.mode === "aws-sdk" and no API key must succeed without throwing.
  • Why this is the smallest reliable guardrail: Direct unit test on the image description function with mocked aws-sdk auth — no AWS credentials needed.
  • Existing test that already covers this: N/A

User-visible / Behavior Changes

Image analysis with Bedrock models using AWS SDK credentials now works (previously always failed).

Diagram (if applicable)

N/A

Security Impact (required)

  • New permissions/capabilities? No
  • requireApiKeyAllowAwsSdk only relaxes the API key requirement for aws-sdk mode, which by definition uses the AWS SDK credential chain instead of static keys. All other auth modes still require an explicit API key. The empty string passed as apiKey is not used by the Bedrock SDK path — it resolves credentials independently.

@luyao618
luyao618 requested a review from a team as a code owner April 26, 2026 08:42
@openclaw-barnacle openclaw-barnacle Bot added agents Agent runtime and tooling size: S labels Apr 26, 2026
@greptile-apps

greptile-apps Bot commented Apr 26, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes a real bug where image.ts unconditionally called requireApiKey, which always throws for Bedrock models using AWS SDK credential chains. The image.ts fix is correct: requireApiKeyAllowAwsSdk returns "" for aws-sdk mode, which is stored in the runtime auth store and works fine because the Bedrock SDK resolves credentials independently.

  • The fix in runner.entries.ts is incomplete: requireApiKeyAllowAwsSdk returns "" for aws-sdk mode, but dedupeApiKeys inside collectProviderApiKeysForExecution filters out empty strings. If no additional static keys exist for the provider, apiKeys becomes [] and executeWithApiKeyRotation throws No API keys configured for provider "amazon-bedrock" before the execute callback is ever reached — the same failure reappears one layer deeper on the audio/video runner path.

Confidence Score: 3/5

Not safe to merge — the runner.entries.ts fix is incomplete and the aws-sdk path for audio/video still fails at runtime.

One P1 defect: the runner.entries.ts change doesn't actually fix the aws-sdk path because dedupeApiKeys drops the empty string, leaving an empty keys array that causes executeWithApiKeyRotation to throw. The image.ts fix is correct, but the scope of the stated fix exceeds what was actually repaired.

src/media-understanding/runner.entries.ts — the resolveProviderExecutionAuth function and its interaction with executeWithApiKeyRotation when apiKeys is empty

Prompt To Fix All With AI
This is a comment left during a code review.
Path: src/media-understanding/runner.entries.ts
Line: 404-408

Comment:
**`executeWithApiKeyRotation` still throws for `aws-sdk` mode**

`requireApiKeyAllowAwsSdk` returns `""` when `auth.mode === "aws-sdk"` and no static key is present. `dedupeApiKeys` in `collectProviderApiKeysForExecution` silently drops empty strings (`if (!apiKey || seen.has(apiKey)) continue`), so if no additional keys are configured for `amazon-bedrock`, `apiKeys` comes out as `[]`. `executeWithApiKeyRotation` then immediately throws `No API keys configured for provider "amazon-bedrock"` before the execute callback is ever invoked — the same failure mode that was fixed for `image.ts`, just one level deeper.

The `image.ts` fix works because it bypasses `executeWithApiKeyRotation` entirely (it sets the key in `authStorage` and calls `complete()` directly). The runner path needs a parallel fix — either by treating an empty primary key as a valid sentinel for `aws-sdk` mode in `collectProviderApiKeysForExecution` / `dedupeApiKeys`, or by short-circuiting the key-rotation layer when `auth.mode === "aws-sdk"`.

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: src/agents/model-auth.test.ts
Line: 89

Comment:
**No test cases added for `requireApiKeyAllowAwsSdk`**

`requireApiKeyAllowAwsSdk` is imported and destructured in `beforeAll`, but no test cases covering its behaviour appear in the diff. The two interesting branches — `aws-sdk` mode with a missing key (should return `""`) and a non-`aws-sdk` mode with a missing key (should throw, delegating to `requireApiKey`) — are untested at the unit level. The new `image.test.ts` case exercises the mock but doesn't reach the real implementation.

How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "fix(media-understanding): allow aws-sdk ..." | Re-trigger Greptile

Comment on lines 404 to 408
return {
apiKeys: collectProviderApiKeysForExecution({
provider: params.providerId,
primaryApiKey: requireApiKey(auth, params.providerId),
primaryApiKey: requireApiKeyAllowAwsSdk(auth, params.providerId),
}),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 executeWithApiKeyRotation still throws for aws-sdk mode

requireApiKeyAllowAwsSdk returns "" when auth.mode === "aws-sdk" and no static key is present. dedupeApiKeys in collectProviderApiKeysForExecution silently drops empty strings (if (!apiKey || seen.has(apiKey)) continue), so if no additional keys are configured for amazon-bedrock, apiKeys comes out as []. executeWithApiKeyRotation then immediately throws No API keys configured for provider "amazon-bedrock" before the execute callback is ever invoked — the same failure mode that was fixed for image.ts, just one level deeper.

The image.ts fix works because it bypasses executeWithApiKeyRotation entirely (it sets the key in authStorage and calls complete() directly). The runner path needs a parallel fix — either by treating an empty primary key as a valid sentinel for aws-sdk mode in collectProviderApiKeysForExecution / dedupeApiKeys, or by short-circuiting the key-rotation layer when auth.mode === "aws-sdk".

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/media-understanding/runner.entries.ts
Line: 404-408

Comment:
**`executeWithApiKeyRotation` still throws for `aws-sdk` mode**

`requireApiKeyAllowAwsSdk` returns `""` when `auth.mode === "aws-sdk"` and no static key is present. `dedupeApiKeys` in `collectProviderApiKeysForExecution` silently drops empty strings (`if (!apiKey || seen.has(apiKey)) continue`), so if no additional keys are configured for `amazon-bedrock`, `apiKeys` comes out as `[]`. `executeWithApiKeyRotation` then immediately throws `No API keys configured for provider "amazon-bedrock"` before the execute callback is ever invoked — the same failure mode that was fixed for `image.ts`, just one level deeper.

The `image.ts` fix works because it bypasses `executeWithApiKeyRotation` entirely (it sets the key in `authStorage` and calls `complete()` directly). The runner path needs a parallel fix — either by treating an empty primary key as a valid sentinel for `aws-sdk` mode in `collectProviderApiKeysForExecution` / `dedupeApiKeys`, or by short-circuiting the key-rotation layer when `auth.mode === "aws-sdk"`.

How can I resolve this? If you propose a fix, please make it concise.

@@ -88,6 +88,7 @@ let applyAuthHeaderOverride: typeof import("./model-auth.js").applyAuthHeaderOve
let applyLocalNoAuthHeaderOverride: typeof import("./model-auth.js").applyLocalNoAuthHeaderOverride;
let hasUsableCustomProviderApiKey: typeof import("./model-auth.js").hasUsableCustomProviderApiKey;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 No test cases added for requireApiKeyAllowAwsSdk

requireApiKeyAllowAwsSdk is imported and destructured in beforeAll, but no test cases covering its behaviour appear in the diff. The two interesting branches — aws-sdk mode with a missing key (should return "") and a non-aws-sdk mode with a missing key (should throw, delegating to requireApiKey) — are untested at the unit level. The new image.test.ts case exercises the mock but doesn't reach the real implementation.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/agents/model-auth.test.ts
Line: 89

Comment:
**No test cases added for `requireApiKeyAllowAwsSdk`**

`requireApiKeyAllowAwsSdk` is imported and destructured in `beforeAll`, but no test cases covering its behaviour appear in the diff. The two interesting branches — `aws-sdk` mode with a missing key (should return `""`) and a non-`aws-sdk` mode with a missing key (should throw, delegating to `requireApiKey`) — are untested at the unit level. The new `image.test.ts` case exercises the mock but doesn't reach the real implementation.

How can I resolve this? If you propose a fix, please make it concise.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3fe2cca346

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".


export function requireApiKeyAllowAwsSdk(auth: ResolvedProviderAuth, provider: string): string {
if (auth.mode === "aws-sdk") {
return normalizeSecretInput(auth.apiKey) ?? "";

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 Badge Use non-empty runtime token for aws-sdk auth

Returning "" for aws-sdk leaves callers with an empty credential even when they immediately register it in auth storage (for example src/media-understanding/image.ts:205-206). The existing aws-sdk handling in src/agents/pi-embedded-runner/run/auth-controller.ts uses a non-empty sentinel specifically so pi's auth check treats the provider as configured; writing an empty value bypasses that safeguard and can still fail Bedrock image calls that rely on IAM/instance-role credentials. Use a non-empty sentinel (or avoid setting runtime auth for this mode) instead of returning an empty string.

Useful? React with 👍 / 👎.

The image tool unconditionally called requireApiKey which throws when
no static API key is present. For amazon-bedrock using IAM role or
instance profile credentials (auth.mode === 'aws-sdk'), the AWS SDK
resolves credentials at call time and no static key exists.

Add requireApiKeyAllowAwsSdk helper that returns an empty string for
aws-sdk mode instead of throwing, and use it in resolveImageRuntime,
resolveMinimaxVlmFallbackRuntime, and resolveProviderExecutionAuth.

AI-assisted (Claude Code via Hermes orchestration).
Fixes openclaw#72031
@luyao618
luyao618 force-pushed the fix/image-bedrock-aws-sdk-auth branch from 3fe2cca to bd00adc Compare April 26, 2026 08:56
@clawsweeper

clawsweeper Bot commented Apr 26, 2026

Copy link
Copy Markdown
Contributor

Closing this as duplicate or superseded after Codex automated review.

PR #72066 should close as superseded by the broader open PR #72092, which tracks the same linked bug #72031 and carries the media-understanding aws-sdk work through image plus audio/video paths. Current main still has the bug, but #72066's own review discussion identifies concrete correctness gaps in its implementation, while #72092 is the better canonical path.

Best possible solution:

Close #72066 as superseded and continue review on #72092 as the canonical fix for #72031. The implementation that should land needs to preserve the aws-sdk no-static-key contract across image, MiniMax fallback, and audio/video media runner paths, including the empty-key rotation/runtime-auth semantics and regression tests.

What I checked:

So I’m closing this here and keeping the remaining discussion on the canonical linked item.

Codex Review notes: model gpt-5.5, reasoning high; reviewed against 7e13f3f51401.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling size: S

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: image tool fails for Bedrock with auth mode: aws-sdkrequireApiKey throws even when AWS SDK creds are available

1 participant