Skip to content

feat: add bedrock as a new data source#730

Open
AlexHladin wants to merge 4 commits into
masterfrom
feature/add-bedrock-data-source-support
Open

feat: add bedrock as a new data source#730
AlexHladin wants to merge 4 commits into
masterfrom
feature/add-bedrock-data-source-support

Conversation

@AlexHladin
Copy link
Copy Markdown
Collaborator

@AlexHladin AlexHladin commented Jun 3, 2026

Proposed changes

This PR adds AWS Bedrock as a data source support.

Issue(s)

Resolves #727

Summary by CodeRabbit

  • New Features

    • Added Amazon Bedrock AppSync data source support with configurable models, region, and role options; synchronous model invocations only (10s limit).
  • Documentation

    • New Bedrock data source guide with quick-start, config options, and invocation constraints.
  • Examples

    • New datasource-bedrock example with a summarize(text: String!) query and working request/response resolver.
  • Tests

    • New unit and end-to-end tests covering Bedrock data source generation and validation.

@AlexHladin AlexHladin requested a review from sid88in June 3, 2026 13:48
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jun 3, 2026

Review Change Stack

📝 Walkthrough

Walkthrough

Adds AMAZON_BEDROCK_RUNTIME AppSync data source: types and validation, IAM role generation (bedrock:InvokeModel/Converse), esbuild bundling externals, unit and e2e tests, an example app with schema/resolvers, and user documentation.

Changes

Amazon Bedrock Runtime Data Source

Layer / File(s) Summary
Type System & Validation Schema
src/types/common.ts, src/types/plugin.ts, src/types/cloudFormation.ts, src/validation.ts, e2e/helpers/assertions.ts
Adds DsBedrockConfig and AMAZON_BEDROCK_RUNTIME to type unions and validation; defines datasourceBedrockConfig schema and updates assertion helper to recognize the new data source type.
DataSource IAM Role & Resolver Bundling
src/resources/DataSource.ts, src/index.ts, src/resources/JsResolver.ts
DataSource now safely checks optional config, generates default IAM role statements for Bedrock (bedrock:InvokeModel, bedrock:Converse) scoped to model ARNs or *, adds getBedrockModelResources(), and marks @aws-appsync/utils/ai as external for bundling.
Unit Tests: Behavior & Validation
src/__tests__/dataSources.test.ts, src/__tests__/validation/datasources.test.ts
Jest tests for Bedrock data source behavior (default role generation, model scoping, iamRoleStatements override, serviceRoleArn suppression) and schema validation cases for models shapes.
Example App, Schema & Resolvers
examples/datasource-bedrock/schema.graphql, examples/datasource-bedrock/serverless.yml, examples/datasource-bedrock/resolvers/summarize.js, examples/README.md
Example with Query.summarize(text: String!): AWSJSON; serverless config declares AMAZON_BEDROCK_RUNTIME using model amazon.nova-micro-v1:0; resolver invokes the model via invokeModel from @aws-appsync/utils/ai using the input text.
End-to-end Example Tests
e2e/datasource-bedrock.e2e.test.ts
E2E suite synthesizes the example and asserts an AMAZON_BEDROCK_RUNTIME data source named bedrock exists and that an IAM role includes bedrock:InvokeModel in its inline policy statements.
User Documentation
doc/dataSources.md
Adds a Bedrock section with a YAML quick start, notes that config fields are optional (including automatic role generation), lists supported options (models, region, serviceRoleArn, iamRoleStatements), and documents resolver invocation constraints (sync-only, 10s limit, no streaming).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐇 I hopped through code to add a key,
Bedrock models calling back to me.
Roles and schemas, tests in line,
Resolvers whisper: "invoke, align."
Hooray — new sources, small and spry!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: add bedrock as a new data source' accurately and concisely summarizes the primary change: adding Amazon Bedrock as a new data source type to the plugin.
Linked Issues check ✅ Passed All coding objectives from issue #727 are met: AMAZON_BEDROCK_RUNTIME added to DATASOURCE_TYPES and validation [#727], CloudFormation data source emission implemented [#727], default IAM role generation with bedrock:InvokeModel/Converse for model ARNs [#727], and documentation/example added [#727].
Out of Scope Changes check ✅ Passed All changes directly support the Bedrock data source feature: type definitions, validation schemas, IAM role helpers, tests, documentation, and example implementation are all in scope.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/add-bedrock-data-source-support

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (2)
src/__tests__/validation/datasources.test.ts (1)

312-390: ⚡ Quick win

Extend Bedrock validation tests to cover other optional config keys.

This block validates models well, but it does not assert schema behavior for region, serviceRoleArn, and iamRoleStatements. Adding those cases will better lock the Bedrock contract and prevent silent schema regressions.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/__tests__/validation/datasources.test.ts` around lines 312 - 390, Add
tests for AMAZON_BEDROCK_RUNTIME to assert optional keys region, serviceRoleArn,
and iamRoleStatements are validated correctly: extend the Valid assertions to
include configs with region (string), serviceRoleArn (string), and
iamRoleStatements (array/object as expected by the schema) and add corresponding
Invalid assertions where each of those keys uses an incorrect type (e.g.,
region: 123, serviceRoleArn: {}, iamRoleStatements: 'not-an-array') so
validateConfig(...) returns true for valid cases and throws (use
toThrowErrorMatchingSnapshot) for invalid cases; place these new cases alongside
the existing assertions array and reuse the same test iteration pattern that
calls validateConfig with {...basicConfig, ...config.config}.
src/__tests__/dataSources.test.ts (1)

225-226: ⚡ Quick win

Add explicit IAM policy assertions for Bedrock default-role semantics.

Line 225 currently relies on snapshot-only verification. Add direct checks that the generated default policy contains both bedrock:InvokeModel and bedrock:Converse and that scoped model/profile resources are present; this gives stronger regression protection than snapshot diffs alone.

Suggested test hardening
     it('should generate default role with scoped models', () => {
       const api = new Api(given.appSyncConfig(), plugin);
       const dataSource = new DataSource(api, {
         type: 'AMAZON_BEDROCK_RUNTIME',
         name: 'bedrock',
         description: 'My Bedrock data source',
         config: {
           models: [
             'amazon.titan-text-lite-v1',
             'arn:aws:bedrock:us-east-1:123456789012:inference-profile/us.anthropic.claude-3-5-haiku-20241022-v1:0',
           ],
         },
       });

       expect(dataSource.compile()).toMatchSnapshot();
+      const role = JSON.stringify(dataSource.compileDataSourceIamRole());
+      expect(role).toContain('bedrock:InvokeModel');
+      expect(role).toContain('bedrock:Converse');
+      expect(role).toContain('foundation-model/amazon.titan-text-lite-v1');
+      expect(role).toContain('inference-profile/us.anthropic.claude-3-5-haiku-20241022-v1:0');
     });
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/__tests__/dataSources.test.ts` around lines 225 - 226, Update the test
that calls dataSource.compile() to add explicit assertions that the generated
default IAM policy includes the Bedrock actions and scoped resources: call const
compiled = dataSource.compile() (or reuse the existing compile result), locate
the default-role policy document in compiled (e.g. the synthesized IAM
Policy/PolicyDocument for the default role name used by the datasource), and add
expects that the PolicyDocument.Statement array contains an entry whose Action
includes "bedrock:InvokeModel" and "bedrock:Converse" (use
expect.arrayContaining or toEqual(expect.arrayContaining([...]))), and that the
Statement.Resource includes resource ARNs or patterns scoped to model/profile
identifiers (use string matching or
expect.stringMatching(/model|profile|arn:.*bedrock.*model/)). Keep these
assertions alongside the existing snapshot assertion after
expect(dataSource.compile()).toMatchSnapshot().
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@doc/dataSources.md`:
- Around line 157-164: Add a short prerequisite note in the doc/dataSources.md
near the `models` and `region` bullet points (the section describing model IDs
and ARN expansion) stating that the AWS account must have access to the selected
Bedrock foundation model in the chosen region before using the plugin or copying
the quick start; reference the Bedrock access requirement and link or point to
the AWS Nova invocation docs so readers know where to request model access and
avoid first-run failures.

In `@e2e/datasource-bedrock.e2e.test.ts`:
- Around line 26-39: Narrow the IAM assertion so it targets the Bedrock
datasource role specifically (instead of any role) by enhancing the predicate in
the bedrockRole lookup: use findResourcesByType and then filter roles where the
role clearly belongs to the datasource (for example check
resource.Properties.RoleName or resource.Metadata['aws:cdk:path'] or another
datasource-specific identifier present on the role) and then assert that that
role's Policies contain both 'bedrock:InvokeModel' and 'bedrock:Converse';
update the expect to verify that this specific bedrock datasource role is
defined and that its PolicyDocument Statement Actions include both permissions.

In `@examples/datasource-bedrock/resolvers/summarize.js`:
- Around line 1-14: The request() currently sends Titan-style inputText; update
the invokeModel body for modelId 'amazon.nova-micro-v1:0' to use the Nova
messages payload: include schemaVersion: "messages-v1" and a messages array
(e.g. a single message with role "user" and content containing the text to
summarize), and optionally add an inferenceConfig if needed; in response(),
return the generated text from ctx.result.results.outputText instead of
returning ctx.result.results. Make these changes in the request and response
functions to match the Bedrock Nova messages schema and extract outputText.

In `@src/resources/DataSource.ts`:
- Around line 430-469: The Bedrock IAM resource construction currently always
turns non-ARN strings into foundation-model ARNs and uses config.region, which
breaks inference-profile selectors and can target the wrong region; update the
AMAZON_BEDROCK_RUNTIME branch and getBedrockModelResource to (1) force the
region used for the resource ARN to the AppSync/API region (e.g., use { Ref:
'AWS::Region' } instead of this.config.config?.region) so resources are created
in the same region as the API, and (2) preserve inference-profile selectors by
detecting model strings that are inference-profile IDs or start with
'inference-profile/' and build the ARN using 'inference-profile/<id>' (instead
of always 'foundation-model/<id>'); keep existing behavior of returning the
input when model is already an ARN (getBedrockModelResource) and adjust the
models -> resources mapping in the AMAZON_BEDROCK_RUNTIME case to pass the
enforced region into getBedrockModelResource.

---

Nitpick comments:
In `@src/__tests__/dataSources.test.ts`:
- Around line 225-226: Update the test that calls dataSource.compile() to add
explicit assertions that the generated default IAM policy includes the Bedrock
actions and scoped resources: call const compiled = dataSource.compile() (or
reuse the existing compile result), locate the default-role policy document in
compiled (e.g. the synthesized IAM Policy/PolicyDocument for the default role
name used by the datasource), and add expects that the PolicyDocument.Statement
array contains an entry whose Action includes "bedrock:InvokeModel" and
"bedrock:Converse" (use expect.arrayContaining or
toEqual(expect.arrayContaining([...]))), and that the Statement.Resource
includes resource ARNs or patterns scoped to model/profile identifiers (use
string matching or expect.stringMatching(/model|profile|arn:.*bedrock.*model/)).
Keep these assertions alongside the existing snapshot assertion after
expect(dataSource.compile()).toMatchSnapshot().

In `@src/__tests__/validation/datasources.test.ts`:
- Around line 312-390: Add tests for AMAZON_BEDROCK_RUNTIME to assert optional
keys region, serviceRoleArn, and iamRoleStatements are validated correctly:
extend the Valid assertions to include configs with region (string),
serviceRoleArn (string), and iamRoleStatements (array/object as expected by the
schema) and add corresponding Invalid assertions where each of those keys uses
an incorrect type (e.g., region: 123, serviceRoleArn: {}, iamRoleStatements:
'not-an-array') so validateConfig(...) returns true for valid cases and throws
(use toThrowErrorMatchingSnapshot) for invalid cases; place these new cases
alongside the existing assertions array and reuse the same test iteration
pattern that calls validateConfig with {...basicConfig, ...config.config}.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 7282a3ad-338b-4a57-b36d-18d3a6980e02

📥 Commits

Reviewing files that changed from the base of the PR and between 2fbb817 and 72b3d59.

⛔ Files ignored due to path filters (2)
  • src/__tests__/__snapshots__/dataSources.test.ts.snap is excluded by !**/*.snap
  • src/__tests__/validation/__snapshots__/datasources.test.ts.snap is excluded by !**/*.snap
📒 Files selected for processing (16)
  • doc/dataSources.md
  • e2e/datasource-bedrock.e2e.test.ts
  • e2e/helpers/assertions.ts
  • examples/README.md
  • examples/datasource-bedrock/resolvers/summarize.js
  • examples/datasource-bedrock/schema.graphql
  • examples/datasource-bedrock/serverless.yml
  • src/__tests__/dataSources.test.ts
  • src/__tests__/validation/datasources.test.ts
  • src/index.ts
  • src/resources/DataSource.ts
  • src/resources/JsResolver.ts
  • src/types/cloudFormation.ts
  • src/types/common.ts
  • src/types/plugin.ts
  • src/validation.ts

Comment thread doc/dataSources.md
Comment on lines +157 to +164
All fields are optional. When `config` is omitted entirely, the plugin still creates the data source and generates a default service role.

- `models`: Optional list of foundation model IDs or full model/inference-profile ARNs. Bare model IDs are expanded to `arn:${AWS::Partition}:bedrock:${region}::foundation-model/<id>` in the generated IAM policy. When omitted, the default role allows `bedrock:InvokeModel` and `bedrock:Converse` on `*`.
- `region`: AWS region used when expanding bare model IDs. Defaults to the stack region.
- `serviceRoleArn`: The service role ARN for this DataSource. If not provided, a new one will be created.
- `iamRoleStatements`: Statements to use for the generated IAM Role. If not provided, default statements will be used.

Resolvers invoke Bedrock through the `APPSYNC_JS` runtime using `InvokeModel` or `Converse` request objects. AppSync only supports synchronous invocations that complete within 10 seconds; streaming APIs are not supported. See the [AWS AppSync Bedrock resolver reference](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-bedrock-js.html) for request/response shapes and helper utilities.
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Call out the Bedrock model-access prerequisite.

A copied quick start can still fail until the account has access to the selected foundation model in that region. Adding that note here would prevent a pretty confusing first-run failure path for users. (docs.aws.amazon.com)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@doc/dataSources.md` around lines 157 - 164, Add a short prerequisite note in
the doc/dataSources.md near the `models` and `region` bullet points (the section
describing model IDs and ARN expansion) stating that the AWS account must have
access to the selected Bedrock foundation model in the chosen region before
using the plugin or copying the quick start; reference the Bedrock access
requirement and link or point to the AWS Nova invocation docs so readers know
where to request model access and avoid first-run failures.

Comment on lines +26 to +39
it('generates a service role with bedrock:InvokeModel permissions', () => {
const roles = findResourcesByType(result.template, 'AWS::IAM::Role');
const bedrockRole = roles.find(({ resource }) => {
const policies = resource.Properties?.Policies as Array<{
PolicyDocument?: { Statement?: Array<{ Action?: string[] }> };
}>;
return policies?.some((policy) =>
policy.PolicyDocument?.Statement?.some((statement) =>
statement.Action?.includes('bedrock:InvokeModel'),
),
);
});

expect(bedrockRole).toBeDefined();
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Tighten this IAM assertion to the Bedrock datasource role.

This passes if any synthesized role has bedrock:InvokeModel, so it can miss regressions in the datasource’s own default role. It also leaves bedrock:Converse untested even though that permission is part of the new Bedrock role contract in this PR context.

💡 Suggested fix
   it('generates a service role with bedrock:InvokeModel permissions', () => {
-    const roles = findResourcesByType(result.template, 'AWS::IAM::Role');
-    const bedrockRole = roles.find(({ resource }) => {
-      const policies = resource.Properties?.Policies as Array<{
-        PolicyDocument?: { Statement?: Array<{ Action?: string[] }> };
-      }>;
-      return policies?.some((policy) =>
-        policy.PolicyDocument?.Statement?.some((statement) =>
-          statement.Action?.includes('bedrock:InvokeModel'),
-        ),
-      );
-    });
+    const ds = expectDataSourceOfType(result.template, 'AMAZON_BEDROCK_RUNTIME');
+    const roleLogicalId = (ds.resource.Properties?.ServiceRoleArn as {
+      'Fn::GetAtt'?: [string, string];
+    })?.['Fn::GetAtt']?.[0];
+
+    expect(roleLogicalId).toBeDefined();
+
+    const bedrockRole = roleLogicalId
+      ? result.template.Resources?.[roleLogicalId]
+      : undefined;
+
+    const policies = bedrockRole?.Properties?.Policies as Array<{
+      PolicyDocument?: { Statement?: Array<{ Action?: string | string[] }> };
+    }>;
+
+    const hasBedrockPermissions = policies?.some((policy) =>
+      policy.PolicyDocument?.Statement?.some((statement) => {
+        const actions = Array.isArray(statement.Action)
+          ? statement.Action
+          : statement.Action
+            ? [statement.Action]
+            : [];
+        return (
+          actions.includes('bedrock:InvokeModel') &&
+          actions.includes('bedrock:Converse')
+        );
+      }),
+    );
 
-    expect(bedrockRole).toBeDefined();
+    expect(hasBedrockPermissions).toBe(true);
   });
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@e2e/datasource-bedrock.e2e.test.ts` around lines 26 - 39, Narrow the IAM
assertion so it targets the Bedrock datasource role specifically (instead of any
role) by enhancing the predicate in the bedrockRole lookup: use
findResourcesByType and then filter roles where the role clearly belongs to the
datasource (for example check resource.Properties.RoleName or
resource.Metadata['aws:cdk:path'] or another datasource-specific identifier
present on the role) and then assert that that role's Policies contain both
'bedrock:InvokeModel' and 'bedrock:Converse'; update the expect to verify that
this specific bedrock datasource role is defined and that its PolicyDocument
Statement Actions include both permissions.

Comment on lines +1 to +14
import { invokeModel } from '@aws-appsync/utils/ai';

export function request(ctx) {
return invokeModel({
modelId: 'amazon.nova-micro-v1:0',
body: {
inputText: `Summarize this text in less than 100 words:\n<text>${ctx.args.text}</text>`,
},
});
}

export function response(ctx) {
return ctx.result.results;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail
# Show the resolver file and any nearby examples for invokeModel usage (Titan vs Nova).
repo_root="."
file="examples/datasource-bedrock/resolvers/summarize.js"

echo "== File: $file =="
if [ -f "$file" ]; then
  nl -ba "$file" | sed -n '1,200p'
else
  echo "Missing file: $file"
fi

echo
echo "== Find other invokeModel usages under examples/datasource-bedrock/resolvers =="
# List resolver files
fd -t f -e js examples/datasource-bedrock/resolvers | sort || true
echo
# Search for invokeModel calls
rg -n "invokeModel\\(" examples/datasource-bedrock/resolvers || true

echo
echo "== Search for ctx.result usage in these resolvers =="
rg -n "ctx\\.result" examples/datasource-bedrock/resolvers || true

Repository: sid88in/serverless-appsync-plugin

Length of output: 1988


🌐 Web query:

Amazon Bedrock Nova invokeModel messages inferenceConfig response shape ctx.result.output vs results

💡 Result:

When using the Amazon Bedrock InvokeModel API with Amazon Nova models, the response body follows a specific schema where the generated content is located under the output key, not a results key [1]. The response structure returned by the model in the body of the InvokeModel response is as follows [1]: { "output": { "message": { "role": "assistant", "content": [ { "text": "string" }, { "toolUse": {... } }, { "reasoningContent": {... } } ] } }, "stopReason": "string", "usage": { "inputTokens": int, "outputTokens": int, "totalTokens": int } } Key points regarding the response structure: 1. output: This is the primary container for the assistant's response. It contains a message object, which holds the role (assistant) and a content array [1]. 2. content: This array contains the actual response blocks, such as text, toolUse, or reasoningContent [1]. 3. No results key: The Nova models' Invoke API schema does not utilize a top-level results key. If you are seeing code snippets referencing results, they likely pertain to different model providers or older legacy Bedrock response formats [2]. 4. Accessing the output: To access the generated text in Python using Boto3, you should read the response body and traverse the JSON structure [3][4]: response = client.invoke_model(modelId="amazon.nova-micro-v1:0", body=json.dumps(request_body)) response_body = json.loads(response["body"].read) text_output = response_body["output"]["message"]["content"]["text"] This schema is designed to be consistent with the Converse API, providing a unified experience for developers regardless of which Bedrock API they choose [5][6].

Citations:


🌐 Web query:

@aws-appsync/utils/ai invokeModel ctx.result structure output vs results

💡 Result:

In AWS AppSync JavaScript resolvers using @aws-appsync/utils/ai, the Bedrock model invocation response is accessed via the context object as ctx.result [1][2]. Structure of ctx.result The structure of ctx.result is determined by the specific Amazon Bedrock model being invoked [2][3]. When you use invokeModel, AppSync passes the response from the Bedrock InvokeModel API directly into ctx.result [2]. Because different models return different response bodies (e.g., Anthropic Claude, Amazon Titan, or Meta Llama), the shape of ctx.result varies [2][3]. Common Access Patterns For many legacy or specific Amazon Titan models, developers often access the output using paths such as ctx.result.results.outputText [2][4]. However, there is no single universal output structure, as it depends on the model's inference response format [2][3]. You should inspect the specific JSON response body of the model you are using in the Amazon Bedrock API documentation to determine the correct path for your data [2][3]. Key Considerations 1. Direct API Mapping: Because ctx.result reflects the Bedrock API response directly, there is no generic "output" field guaranteed across all models [2]. 2. Troubleshooting: If you are unsure of the structure, you can log the entire ctx.result object in your AppSync logs during development to inspect the returned JSON schema. 3. Converse vs. InvokeModel: If you are using the newer Converse API (often preferred for its unified interface across models), the response structure differs significantly from the older InvokeModel API, typically nesting data within response.message.content [5]. Always ensure your resolver response handler maps the model-specific response structure to the schema expected by your GraphQL type [2].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail
# Show the resolver file and any nearby examples for invokeModel usage (Titan vs Nova).
repo_root="."
file="examples/datasource-bedrock/resolvers/summarize.js"

echo "== File: $file =="
if [ -f "$file" ]; then
  nl -ba "$file" | sed -n '1,200p'
else
  echo "Missing file: $file"
fi

echo
echo "== Find other invokeModel usages under examples/datasource-bedrock/resolvers =="
# List resolver files
fd -t f -e js examples/datasource-bedrock/resolvers | sort || true
echo
# Search for invokeModel calls
rg -n "invokeModel\\(" examples/datasource-bedrock/resolvers || true

echo
echo "== Search for ctx.result usage in these resolvers =="
rg -n "ctx\\.result" examples/datasource-bedrock/resolvers || true

Repository: sid88in/serverless-appsync-plugin

Length of output: 1988


🌐 Web query:

Amazon Bedrock Nova invokeModel messages inferenceConfig response shape (outputText vs results[0].outputText)

💡 Result:

The response shape you should use depends entirely on whether you are using the Converse API or the legacy InvokeModel API. For Amazon Nova models on Amazon Bedrock, AWS recommends using the Converse API [1][2]. The InvokeModel API is supported but follows a different, model-specific response structure [1]. 1. Converse API Response Shape When using the Converse API, the response format is standardized across models [2]. The text content is accessed via a nested structure: response['output']['message']['content']['text'] [3][4][2] 2. InvokeModel API Response Shape When using the InvokeModel API, the response body structure depends on the specific model's native schema [1][5]. - If you were using older models like Amazon Titan, you might be accustomed to the results['outputText'] path [6][7]. - However, for Amazon Nova models invoked via InvokeModel, the structure aligns with the Converse schema, typically returning an output object containing the message [8][1]: response_body['output']['message']['content']['text'] Summary If you are writing code for Amazon Nova, avoid relying on results['outputText'], as this is specific to older models like Amazon Titan [6][7]. You should use the Converse API structure [1][2], which is consistent: response['output']['message']['content']['text'] [3][4][2]

Citations:


🌐 Web query:

@aws-appsync/utils/ai invokeModel response fields ctx.result output results

💡 Result:

In AWS AppSync JavaScript resolvers using @aws-appsync/utils/ai invokeModel, the Bedrock runtime response is available on the resolver response context as ctx.result. The response helper returns ctx.result.results.outputText for the first invocation result (in the examples/docs). 1) ctx.result is the container for the data returned by the data source (available in response handlers) ctx.result is described as “a container for the results of this resolver” in the AppSync resolver context reference. [1] 2) For invokeModel, the text output is typically at ctx.result.results.outputText The Bedrock JS resolver reference shows an invokeModel response handler returning ctx.result.results.outputText. [2] Also, in a community example handling invokeModel, they parse JSON from ctx.result.results.outputText. [3] 3) Where “ctx.result.output …” comes from (Converse vs invokeModel) A community thread shows accessing ctx.result.output.message.content.text in a resolver that uses converse (not invokeModel), and notes similar behavior was exhibited by invokeModel in their case. Because this is a community issue (not the official resolver-reference example), treat this “output.message…” shape as model/adapter-dependent and verify with your actual invocation output. [4] Practical guidance for response mapping - If you used invokeModel via @aws-appsync/utils/ai, start with: - ctx.result.results.outputText [2] - If you need a different field path (e.g., ctx.result.output.message.content.text), inspect/print the full ctx.result from your resolver logs first, since the exact shape can vary by operation/model. [1][4]

Citations:


🌐 Web query:

@aws-appsync/utils/ai invokeModel Amazon Nova ctx.result structure output results

💡 Result:

When using the @aws-appsync/utils/ai invokeModel helper in AWS AppSync, the structure of the returned ctx.result is determined by the underlying Amazon Bedrock InvokeModel API response [1][2]. Because invokeModel performs a low-level invocation of the model, the response is generally contained within the body field of the Bedrock API response [2]. The specific structure of the data inside ctx.result.body depends entirely on the model being called (in this case, Amazon Nova) [2][3]. For Amazon Nova, the model's response is typically returned as a JSON object [3]. Because Amazon Bedrock returns the body as a blob or a stream of bytes, you must parse the response body in your AppSync response resolver to access the data effectively [2][3]. Key points for implementation: 1. Response Access: The response from Bedrock is stored in ctx.result. When using invokeModel, you generally access the returned JSON data by parsing the body [2][3]. 2. Parsing: Depending on your runtime environment, you may need to use util.parseJson(ctx.result.body) to convert the raw response body into a usable JavaScript object [1]. 3. Model-Specific Output: Amazon Nova provides structured output based on how you prompt it (e.g., requesting JSON format) [3]. Ensure you have defined your prompt to return the desired format, as the invokeModel helper simply passes back the raw Bedrock response [1][2]. Example Resolver Structure: // response resolver export function response(ctx) { // Parse the Bedrock response body const body = util.parseJson(ctx.result.body); // Access the specific field based on the expected Nova output structure // For example, if Nova returns { "content": "..." } return body.content; } Note: If you encounter issues with ctx.result structure, ensure that you are not confusing the invokeModel helper with the converse helper [4][1]. The converse helper provides a more standardized response structure (e.g., ctx.result.output.message.content) that is abstracted from the underlying model's raw body [4]. If you require a consistent, model-agnostic response format, consider using the converse helper instead of invokeModel [4][1].

Citations:


🌐 Web query:

AppSync bedrock js invokeModel Amazon Nova request body messages inferenceConfig

💡 Result:

When invoking Amazon Nova models via AWS AppSync using the invokeModel function, you must provide a request body that adheres to the specific schema expected by the Amazon Nova Invoke API [1]. Unlike the simpler text-based prompts used for legacy models, the Amazon Nova Invoke API requires a structured JSON payload that includes the message history and configuration [1]. To perform this in an AppSync JavaScript resolver, your invokeModel request object should be structured as follows: import { invokeModel } from '@aws-appsync/utils/ai'; export function request(ctx) { return invokeModel({ modelId: 'amazon.nova-micro-v1:0', // Or your specific Nova model ID body: { schemaVersion: 'messages-v1', messages: [ { role: 'user', content: [{ text: 'Your prompt here' }] } ], inferenceConfig: { maxTokens: 500, temperature: 0.7, topP: 0.9 } } }); } Key Requirements: 1. Schema Version: You must include "schemaVersion": "messages-v1" in the body [1]. 2. Messages: The input must be provided as an array of message objects, each containing a role ("user" or "assistant") and content [1]. 3. InferenceConfig: This object holds your inference parameters, such as maxTokens, temperature, topP, and topK [1][2]. 4. System Prompts: If you need to provide system-level instructions, you can include a system array at the top level of the body: "system": [{"text": "Your system prompt here"}] [3][1]. While the AppSync @aws-appsync/utils/ai library provides convenient helpers, ensuring the body structure matches the Nova-specific Invoke API requirements is critical for successful inference [1]. Note that for conversational applications where you need to maintain state, AWS recommends using the Converse API if possible, which is also supported in AppSync via the converse helper function [4][1][5].

Citations:


🌐 Web query:

docs.aws.amazon.com nova invokeModel request body messages inferenceConfig example

💡 Result:

To invoke Amazon Nova models using the Amazon Bedrock InvokeModel API, you must provide a JSON-formatted request body that includes the messages structure and an optional inferenceConfig object [1][2][3]. The InvokeModel API requires the contentType header to be set to application/json [3][4]. Request Body Structure Example Below is a standard example of the JSON request body structure for Amazon Nova [2][5]: { "schemaVersion": "messages-v1", "messages": [ { "role": "user", "content": [ { "text": "Describe the purpose of a 'hello world' program in one line." } ] } ], "inferenceConfig": { "maxTokens": 512, "temperature": 0.5, "topP": 0.9 } } Key Components 1. messages: An array of objects representing conversational turns [1][6]. Each object must include: - role: Typically "user" or "assistant" [1][5]. - content: An array of content blocks, such as text, images, or videos [6][7]. 2. inferenceConfig: Optional parameters to control model generation [6][5]: - maxTokens: The maximum number of tokens to generate [6]. - temperature: Controls randomness (valid range: 0.00001 to 1.0) [6]. - topP: Nucleus sampling probability cutoff (valid range: 0 to 1) [6]. - topK: Limits sampling to the top K options (valid range: 0 to 128) [6]. 3. schemaVersion: Recommended as "messages-v1" to ensure correct schema interpretation [5]. Note: Amazon Nova models also support system prompts, which can be included in the request body using a top-level "system" field [1]. For more complex inputs, such as images or videos, the content block supports specific source structures (e.g., base64-encoded strings for the Invoke API) [6][7].

Citations:


🌐 Web query:

resolver-reference-bedrock-js invokeModel ctx.result.results.outputText example

💡 Result:

In AWS AppSync’s resolver reference (bedrock-js utilities), the pattern for reading the text returned from a Bedrock InvokeModel call is: return ctx.result.results.outputText from your response function. For example, the docs show response(ctx) { return ctx.result.results.outputText }. [1] Context / why this path: - The AppSync Bedrock invokeModel helper stores the Bedrock invocation’s response in ctx.result (and the docs’ response example reads from ctx.result.results.outputText). [1] - The underlying Bedrock runtime InvokeModel API returns an inference response body, but the AppSync resolver reference is what maps that into ctx.result.* fields for GraphQL resolvers. [2][1] Concrete example from the AppSync resolver reference: export function response(ctx) { return ctx.result.results.outputText } [1] If you instead want the raw mapped result object, the same page also shows a response(ctx) { return ctx.result } example. [1]

Citations:


Fix Amazon Nova Bedrock invokeModel request/response in summarize.js

  • The current request uses Titan-style inputText, but amazon.nova-micro-v1:0 InvokeModel expects a Nova messages payload (schemaVersion: "messages-v1", messages: [{ role, content: [{ text }] }], optionally inferenceConfig), so the request body is incompatible with the selected model.
  • The current response returns ctx.result.results; for Bedrock invokeModel the resolver reference maps the generated text to ctx.result.results.outputText, so extract outputText instead of returning the entire results object.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@examples/datasource-bedrock/resolvers/summarize.js` around lines 1 - 14, The
request() currently sends Titan-style inputText; update the invokeModel body for
modelId 'amazon.nova-micro-v1:0' to use the Nova messages payload: include
schemaVersion: "messages-v1" and a messages array (e.g. a single message with
role "user" and content containing the text to summarize), and optionally add an
inferenceConfig if needed; in response(), return the generated text from
ctx.result.results.outputText instead of returning ctx.result.results. Make
these changes in the request and response functions to match the Bedrock Nova
messages schema and extract outputText.

Comment thread src/resources/DataSource.ts Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

♻️ Duplicate comments (2)
examples/datasource-bedrock/resolvers/summarize.js (2)

6-13: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Add schemaVersion: "messages-v1" to the Nova InvokeModel body.

The messages payload is now correct, but Amazon Nova's InvokeModel schema requires the top-level schemaVersion field. Without it, the request body is incomplete for amazon.nova-micro-v1:0.

🐛 Proposed fix
     body: {
+      schemaVersion: 'messages-v1',
       messages: [
         {
           role: 'user',
           content: [{ text: ctx.args.text }],
         },
       ],
     },
Amazon Nova InvokeModel request body required fields schemaVersion messages-v1
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@examples/datasource-bedrock/resolvers/summarize.js` around lines 6 - 13, In
the summarize resolver, the InvokeModel request body is missing the required
top-level schemaVersion; update the body object (the one that currently contains
messages: [{ role: 'user', content: [{ text: ctx.args.text }] }]) to include
schemaVersion: "messages-v1" alongside messages so the request to the
amazon.nova-micro-v1:0 model conforms to the InvokeModel schema.

17-19: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

ctx.result.results is undefined for Nova; extract from output.message.content.

The results key is specific to legacy Titan models. Nova's InvokeModel response is shaped as { output: { message: { content: [{ text }] } }, ... } with no top-level results, so this handler returns undefined.

🐛 Proposed fix
 export function response(ctx) {
-  return ctx.result.results;
+  return ctx.result.output.message.content[0].text;
 }
Amazon Nova InvokeModel response shape output message content text appsync ctx.result
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@examples/datasource-bedrock/resolvers/summarize.js` around lines 17 - 19, The
response function currently returns ctx.result.results which is undefined for
Amazon Nova; instead read the Nova shape at ctx.result.output.message.content
(an array of content objects) and extract the text fields (e.g., map content
items to their .text or join them) to produce the same list/string the rest of
the app expects; update the response(ctx) implementation to handle both legacy
ctx.result.results and the Nova path (ctx.result.output.message.content) so it
works for either model.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Duplicate comments:
In `@examples/datasource-bedrock/resolvers/summarize.js`:
- Around line 6-13: In the summarize resolver, the InvokeModel request body is
missing the required top-level schemaVersion; update the body object (the one
that currently contains messages: [{ role: 'user', content: [{ text:
ctx.args.text }] }]) to include schemaVersion: "messages-v1" alongside messages
so the request to the amazon.nova-micro-v1:0 model conforms to the InvokeModel
schema.
- Around line 17-19: The response function currently returns ctx.result.results
which is undefined for Amazon Nova; instead read the Nova shape at
ctx.result.output.message.content (an array of content objects) and extract the
text fields (e.g., map content items to their .text or join them) to produce the
same list/string the rest of the app expects; update the response(ctx)
implementation to handle both legacy ctx.result.results and the Nova path
(ctx.result.output.message.content) so it works for either model.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d6643a0b-808e-4a15-b132-a7fd30882ecc

📥 Commits

Reviewing files that changed from the base of the PR and between 72b3d59 and 13ae025.

📒 Files selected for processing (1)
  • examples/datasource-bedrock/resolvers/summarize.js

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

♻️ Duplicate comments (1)
examples/datasource-bedrock/resolvers/summarize.js (1)

6-13: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Include schemaVersion: 'messages-v1' in the Nova invoke payload.

For Nova v1 invoke payloads, missing schemaVersion can cause request validation failures.

Suggested fix
     body: {
+      schemaVersion: 'messages-v1',
       messages: [
         {
           role: 'user',
           content: [{ text: ctx.args.text }],
         },
       ],
     },
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@examples/datasource-bedrock/resolvers/summarize.js` around lines 6 - 13, The
Nova v1 invoke payload is missing schemaVersion which can break validation;
update the request body construction (the object containing messages: [{ role:
'user', content: [{ text: ctx.args.text }] }]) to include schemaVersion:
'messages-v1' at the top level of the body object so the payload becomes {
schemaVersion: 'messages-v1', messages: [...] } before sending in the summarize
resolver.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@examples/datasource-bedrock/resolvers/summarize.js`:
- Line 5: The resolver uses invokeModel.modelId 'eu.amazon.nova-micro-v1:0'
which doesn't match the Bedrock allowlist in dataSources.bedrock.config.models;
update one side so they align: either add 'eu.amazon-nova-micro-v1:0' (or the
plugin-expected inference-profile ID format) to the serverless.yml
dataSources.bedrock.config.models allowlist, or change the resolver's
invokeModel.modelId to 'amazon.nova-micro-v1:0' so it matches the existing
allowlist; modify the modelId in
examples/datasource-bedrock/resolvers/summarize.js or the models array in
serverless.yml accordingly.

In `@src/resources/DataSource.ts`:
- Around line 466-469: The regex inferenceProfilePrefix in
getBedrockModelResources() only matches /^(us-gov|us|eu|apac)\./ so models
prefixed with "global." are missed; update the pattern to include "global"
(e.g., add "global" to the alternation) so that when you call
inferenceProfilePrefix.exec(model) it will match "global." and let the
subsequent logic that computes baseModelId = model.slice(match[0].length) and
constructs IAM ARNs include the inference-profile/global.* paths.

---

Duplicate comments:
In `@examples/datasource-bedrock/resolvers/summarize.js`:
- Around line 6-13: The Nova v1 invoke payload is missing schemaVersion which
can break validation; update the request body construction (the object
containing messages: [{ role: 'user', content: [{ text: ctx.args.text }] }]) to
include schemaVersion: 'messages-v1' at the top level of the body object so the
payload becomes { schemaVersion: 'messages-v1', messages: [...] } before sending
in the summarize resolver.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e5363e93-2f24-494c-b839-c856d37b3121

📥 Commits

Reviewing files that changed from the base of the PR and between 6c1d775 and bf54292.

⛔ Files ignored due to path filters (1)
  • src/__tests__/__snapshots__/dataSources.test.ts.snap is excluded by !**/*.snap
📒 Files selected for processing (4)
  • doc/dataSources.md
  • examples/datasource-bedrock/resolvers/summarize.js
  • src/__tests__/dataSources.test.ts
  • src/resources/DataSource.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • doc/dataSources.md
  • src/tests/dataSources.test.ts


export function request(ctx) {
return invokeModel({
modelId: 'eu.amazon.nova-micro-v1:0',
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

nl -ba examples/datasource-bedrock/resolvers/summarize.js | sed -n '1,80p'
nl -ba examples/datasource-bedrock/serverless.yml | sed -n '1,260p'
rg -n "datasourceBedrockConfig|models:|modelId" examples/datasource-bedrock -C2

Repository: sid88in/serverless-appsync-plugin

Length of output: 120


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== summarize.js (first 120 lines) ==="
cat -n examples/datasource-bedrock/resolvers/summarize.js | sed -n '1,120p'

echo
echo "=== serverless.yml (first 320 lines) ==="
cat -n examples/datasource-bedrock/serverless.yml | sed -n '1,320p'

echo
echo "=== Search bedrock datasource config for allowlist + model id ==="
rg -n "datasourceBedrockConfig|models:|modelId" examples/datasource-bedrock -C2

Repository: sid88in/serverless-appsync-plugin

Length of output: 2207


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate plugin code that handles AMAZON_BEDROCK_RUNTIME and "models" allowlist
ls -la
rg -n "AMAZON_BEDROCK_RUNTIME|bedrock.*models|config\.models|invokeModel\(" -S . --glob='*.js' --glob='*.ts' --glob='*.mjs' --glob='*.cjs'

Repository: sid88in/serverless-appsync-plugin

Length of output: 3821


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate plugin code that handles AMAZON_BEDROCK_RUNTIME and "models" allowlist
ls -la
rg -n "AMAZON_BEDROCK_RUNTIME|bedrock.*models|config\.models|invokeModel\(" -S . --glob='*.js' --glob='*.ts' --glob='*.mjs' --glob='*.cjs'

Repository: sid88in/serverless-appsync-plugin

Length of output: 3821


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Show the AMAZON_BEDROCK_RUNTIME handling and any model allowlist logic
rg -n "case 'AMAZON_BEDROCK_RUNTIME'|config\.models|models" src/resources/DataSource.ts -n
sed -n '380,520p' src/resources/DataSource.ts

Repository: sid88in/serverless-appsync-plugin

Length of output: 4207


Align invokeModel.modelId with the Bedrock models allowlist

examples/datasource-bedrock/resolvers/summarize.js calls invokeModel with modelId: 'eu.amazon.nova-micro-v1:0', but examples/datasource-bedrock/serverless.yml allows only dataSources.bedrock.config.models: ['amazon.nova-micro-v1:0']. Since eu.* is treated as an inference-profile ID by the plugin, the IAM policy won’t include the inference-profile/... resource unless that exact ID is allowlisted, which can deny bedrock:InvokeModel at runtime.

  • Add eu.amazon-nova-micro-v1:0 to serverless.yml’s dataSources.bedrock.config.models, or change the resolver to use amazon.nova-micro-v1:0.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@examples/datasource-bedrock/resolvers/summarize.js` at line 5, The resolver
uses invokeModel.modelId 'eu.amazon.nova-micro-v1:0' which doesn't match the
Bedrock allowlist in dataSources.bedrock.config.models; update one side so they
align: either add 'eu.amazon-nova-micro-v1:0' (or the plugin-expected
inference-profile ID format) to the serverless.yml
dataSources.bedrock.config.models allowlist, or change the resolver's
invokeModel.modelId to 'amazon.nova-micro-v1:0' so it matches the existing
allowlist; modify the modelId in
examples/datasource-bedrock/resolvers/summarize.js or the models array in
serverless.yml accordingly.

Comment on lines +466 to +469
const inferenceProfilePrefix = /^(us-gov|us|eu|apac)\./;
const match = inferenceProfilePrefix.exec(model);
if (match) {
const baseModelId = model.slice(match[0].length);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the cited section in DataSource.ts
sed -n '430,520p' src/resources/DataSource.ts | cat -n

# Show full function/context if possible by locating nearest function/class boundaries
echo "---- nearest context: grep for nearby markers ----"
rg -n "inferenceProfilePrefix|baseModelId|inference-profile" src/resources/DataSource.ts

# Search for other inference-profile prefix parsing / global handling in the repo
echo "---- repo search for inference profile parsing and global.* ----"
rg -n "inferenceProfilePrefix|inference[- ]profile|foundation-model|global\." src | head -n 200

# Search for any IAM resource construction related to Bedrock inference profiles
echo "---- repo search for Bedrock inference-profile IAM resources ----"
rg -n "bedrock.*inference.*profile|InvokeModel|inference-profile" src | head -n 200

Repository: sid88in/serverless-appsync-plugin

Length of output: 6672


🌐 Web query:

AWS Bedrock inference-profile ID global. prefix

💡 Result:

In Amazon Bedrock, the global. prefix is used in the IDs and Amazon Resource Names (ARNs) of system-defined inference profiles that enable Global cross-Region inference [1][2][3]. Key details regarding this prefix and global inference profiles: Functionality: Global inference profiles allow Amazon Bedrock to dynamically route inference requests to the optimal AWS commercial Region worldwide [3]. This is designed to maximize throughput and optimize resource utilization, often providing cost savings compared to single-region or geographic-constrained inference [3]. ID Format: The inference profile ID (and the corresponding segment in the ARN) follows a structure that includes the global prefix, followed by the model provider and specific model identifier [1][4]. Example format: global.anthropic.claude-sonnet-4-5-20250929-v1:0 [1][2] IAM and Security Policies: When writing IAM policies to manage access to these profiles, note that global cross-region inference requests use an unspecified value for the aws:RequestedRegion condition key [1][2][3]. Security policies often use the global prefix in the resource ARN to specifically target these profiles [1][2]. For example, to deny unauthorized global cross-region inference, a policy might use an ArnLike condition with the pattern arn:aws:bedrock:::inference-profile/global.* [2]. Usage: You can use these global inference profile IDs or their full ARNs as the modelId in supported API operations, such as InvokeModel, InvokeModelWithResponseStream, Converse, and ConverseStream [5][6][7]. For a complete list of supported models and their specific global inference profile IDs, you should consult the models at a glance page in the official Amazon Bedrock documentation [8].

Citations:


Include global. in the Bedrock inference-profile prefix matcher to expand IAM resources correctly.

getBedrockModelResources() only expands IDs prefixed with us-gov|us|eu|apac; global.* falls through and is treated as a bare foundation-model, so generated IAM ARNs won’t include the inference-profile/global.* permission (and the routed foundation-model access).

Suggested fix
-    const inferenceProfilePrefix = /^(us-gov|us|eu|apac)\./;
+    const inferenceProfilePrefix = /^(us-gov|us|eu|apac|global)\./;
🧰 Tools
🪛 OpenGrep (1.22.0)

[ERROR] 467-467: Dynamic command passed to child_process.exec/execSync. Use child_process.execFile or spawn with an argument array instead.

(coderabbit.command-injection.exec-js)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/resources/DataSource.ts` around lines 466 - 469, The regex
inferenceProfilePrefix in getBedrockModelResources() only matches
/^(us-gov|us|eu|apac)\./ so models prefixed with "global." are missed; update
the pattern to include "global" (e.g., add "global" to the alternation) so that
when you call inferenceProfilePrefix.exec(model) it will match "global." and let
the subsequent logic that computes baseModelId = model.slice(match[0].length)
and constructs IAM ARNs include the inference-profile/global.* paths.

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.

Support Amazon Bedrock runtime data source (AMAZON_BEDROCK_RUNTIME)

1 participant