Skip to content

feat(create): Declare the Bedrock target on the runtime's Box gateway - #2789

Open
mquang-amazon wants to merge 5 commits into
box-integrationfrom
create-box-gateway
Open

mquang-amazon wants to merge 5 commits into
box-integrationfrom
create-box-gateway

Conversation

@mquang-amazon

@mquang-amazon mquang-amazon commented Nov 13, 2026 •

Copy link
Copy Markdown
Contributor

Description

Stacked on #2787. This branch contains #2787's three commits; this PR is the commits after them (feat(create): Declare the Bedrock target on the runtime's Box gateway and feat(create): Target Bedrock in the resolved region, and on add runtime too). I will rebase once #2787 merges.

With #2787, every new project is a Box project and each runtime gets its own Box gateway, <runtime>-box (aws/agentcore-l3-cdk-constructs#454). This PR makes agentcore create, and agentcore add runtime --agent-id in a Box project, also declare the Bedrock model target on that gateway when the runtime's agent calls Bedrock.

Limitation: the target signs with the Box gateway's role (GATEWAY_IAM_ROLE), and nothing grants that role Bedrock permissions yet, so a call through the target gets AccessDenied until a follow-up adds a Bedrock policy to the entry's additionalPolicies (aws/agentcore-l3-cdk-constructs#456 adds that field on Box entries; the CLI side is in #2791).

For the default runtime agent, with the resolved region us-west-2, agentcore.json gets:

{
  "projectType": "box",
  "agentCoreGateways": [
    {
      "name": "agent-box",
      "protocolType": "None",
      "authorizerType": "AWS_IAM",
      "enableSemanticSearch": true,
      "exceptionLevel": "NONE",
      "targets": [
        {
          "name": "bedrock",
          "targetType": "passthrough",
          "passthrough": { "endpoint": "https://bedrock-runtime.us-west-2.amazonaws.com", "protocolType": "CUSTOM" },
          "outboundAuth": { "type": "GATEWAY_IAM_ROLE", "service": "bedrock", "region": "us-west-2" }
        }
      ]
    }
  ]
}
Template <runtime>-box entry with bedrock
agent-python-minimal, agent-python-strands(-container), agent-typescript-strands, a2a/agui-python-strands, agent-python-langchain, agent-typescript-vercel yes, when the agent calls Bedrock (Bedrock provider, or LiteLLM on a bedrock/ model)
the same templates with another model provider no: that endpoint takes an API key create has no credential for
mcp-python-fastmcp, environment-python-bma (no model provider), empty no
  • The entry has the settings agentcore add gateway-target gives a <runtime>-box entry (feat(project): mark new projects as Box projects and manage Box gateway targets #2787), which are the only ones the CDK library accepts. remove gateway-target of the last target removes it, and remove runtime removes it with the runtime.
  • Each runtime keeps its Box gateway without an entry: projectType alone makes it, so an MCP server can add targets later.
  • The Bedrock target uses the region the command resolved (--region, AWS_REGION, then the profile), which is the region a first deploy uses when aws-targets.json is empty; GovCloud gets its own endpoint. us-west-2 is only the fallback for a caller that passes none.
  • boxGatewayEntryForRuntime() derives the entry where the spec is written, so create and add runtime give a runtime the same entry; it is not carried on ScaffoldRuntimeInput.

Depends on #2787 and aws/agentcore-l3-cdk-constructs#454, and on the @aws/agentcore-cdk pin bump that #2787 needs.

Related Issue

Closes #

Documentation PR

Not applicable; the Box gateway is documented in aws/agentcore-l3-cdk-constructs#454.

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • Documentation update
  • Other (please describe):

Testing

  • I ran bun test (failures only in tests that fail on this host without the change: toolAvailable, requireTool, SourceResolver bytes ... under node)
  • I ran the relevant end-to-end tests with bun run test:e2e: not run; they need the unreleased CDK library
  • I ran bun run typecheck
  • I ran bun run lint:check
  • I ran bun run format:check
  • I ran bun run audit
  • I ran bun run secrets:check
  • I ran bun run build
  • If I modified src/assets/, I updated affected snapshots: no src/assets/ change
  • If I re-recorded fixtures or golden files: none re-recorded

New tests: the entry per template, model provider and region (shortcuts.test.ts), what create writes per template and with --region (project.test.ts), that the create wizard passes the resolved region, and that an imported Bedrock agent gets the target in --region (add/runtime/index.test.ts). The affected suites also pass with AWS_REGION=eu-west-1. Gateway, policy-engine, remove and deploy tests, including #2787's project remove in a Box project, now account for the agent-box entry a templated project starts with. Manually: a project created with this branch and synthesized against a packed build of aws/agentcore-l3-cdk-constructs#454 (9ab7489) gets the gateway BoxApp-agent-box (AWS_IAM) with the bedrock target, and the runtime gets AGENTCORE_GATEWAY_BOX_*.

agentcore create now writes "box": {} into every new project. The CDK
library then adds the Box gateway (logical name box, AWS_IAM auth).

- Add the optional box field to ProjectSpecSchema, with no default, so
  a write-back never adds it to an existing project.
- add gateway-target --gateway box makes the box entry with AWS_IAM in
  a Box project. When its last target goes, the entry goes too.
- remove gateway --name box removes only the entry, and says that the
  Box gateway stays.
- remove all also deletes the marker, so the next deploy shows only the
  existing teardown confirmation.
- A deploy records the Box gateway in deployed-state.json. A later
  deploy with no marker but with other resources stops with an error,
  unless the user confirms or passes --yes.
- A project with only the marker is a deploy, not a teardown.
…sthrough Box targets

- Replace the "box": {} marker with "projectType": "box". create writes
  it, remove all removes it, and no other command adds it.
- add gateway-target --gateway box writes the box entry with
  protocolType "None" and refuses any target that is not passthrough,
  before it changes agentcore.json.
- add gateway refuses the name box, in any letter case, in a Box
  project, and points to add gateway-target --gateway box.
- The deploy check and its messages now name "projectType": "box".
@codecov-commenter

codecov-commenter commented Nov 13, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 99.62264% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 96.52%. Comparing base (eb165b5) to head (3d2203f).
⚠️ Report is 6 commits behind head on box-integration.

Files with missing lines Patch % Lines
src/handlers/project/deploy/index.ts 97.36% 1 Missing ⚠️
Additional details and impacted files
@@                 Coverage Diff                 @@
##           box-integration    #2789      +/-   ##
===================================================
+ Coverage            96.50%   96.52%   +0.02%     
===================================================
  Files                  709      709              
  Lines                58941    59159     +218     
===================================================
+ Hits                 56881    57105     +224     
+ Misses                2060     2054       -6     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

A Box project now has one Box gateway for each runtime (1:1), named
<runtime>-box, with _ changed to -.

- add gateway-target --gateway <runtime>-box writes the entry of that
  runtime's gateway. An unknown gateway name in a Box project lists the
  Box gateways in the error.
- add gateway refuses each name that ends in -box, in any letter case,
  in a Box project.
- remove runtime also removes the entry of its Box gateway.
- Deploy records all Box gateways of a target (resources.boxGateways)
  and the deploy check names all of them.
A template whose agent calls Bedrock (the Bedrock provider, or LiteLLM
on a bedrock/ model) now writes the extension entry <runtime>-box with a
us-west-2 "bedrock" passthrough target, so the agent's model calls go
through its Box gateway from the first deploy. The entry has the
settings that `agentcore add gateway-target` gives one. Templates with
no model provider (MCP server, BMA), other model providers and the
empty template write no entry; their runtimes still get a Box gateway
from "projectType": "box".

Builds on #2787 (projectType and the <runtime>-box
entries) and aws/agentcore-l3-cdk-constructs#454 (one Box gateway per
runtime).
@mquang-amazon mquang-amazon changed the title feat(create): Declare a Box project with the Box gateway entry feat(create): Declare the Bedrock target on the runtime's Box gateway Nov 13, 2026

@leo237 leo237 left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Reviewed the last commit (feat(create): Declare the Bedrock target on the runtime's Box gateway) only; #2787's commits are excluded. bun test on shortcuts/project/core-project passes locally (1175 pass).

Findings:

  1. High: the bedrock target's gateway role gets no Bedrock permissions, so calls through the target would get AccessDenied after the first deploy (inline on shortcuts.ts:68).
  2. Medium: the region is hardcoded to us-west-2, but create already resolves a region, and that is the region the first deploy uses by default (inline on shortcuts.ts:40).
  3. Low: boxGatewayEntry is on the shared ScaffoldRuntimeInput, but only createProjectTree reads it. A Bedrock runtime added later with agentcore add runtime gets no bedrock target (inline on types.ts:92).

— 🤖 Abhilash's Claude Bot

endpoint: `https://bedrock-runtime.${region}.amazonaws.com`,
protocolType: "CUSTOM",
},
outboundAuth: { type: "GATEWAY_IAM_ROLE", service: "bedrock", region },

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The gateway role has no permission to call Bedrock. This target signs with the Box gateway's role (GATEWAY_IAM_ROLE, service bedrock). In aws/agentcore-l3-cdk-constructs#454, addPassthroughTarget → addL1Target only calls GatewayCredentialProvider.fromIamRole(...).grantNeededPermissionsToRole. That grants nothing service-specific. The description of aws/agentcore-l3-cdk-constructs#456 says the same: "The construct grants that role nothing for the service". So once deployed, a call through AGENTCORE_GATEWAY_BOX_URL to bedrock fails with AccessDenied on bedrock:InvokeModel*. That contradicts the PR's "can go through its Box gateway from the first deploy".

#2791 fixes the same gap for Memory by writing agentcore/box-memory-policy.json and listing it in the entry's additionalPolicies. Consider doing the same for Bedrock here: bedrock:InvokeModel, bedrock:InvokeModelWithResponseStream, scoped to the target region's foundation-model and inference-profile ARNs. Since global. profiles route across regions, the foundation-model resource would need * for region. Otherwise, state in the PR that the target cannot be used until a follow-up adds the policy.

— 🤖 Abhilash's Claude Bot

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Agreed, the gateway role has no Bedrock permission yet. additionalPolicies on a Box entry comes with aws/agentcore-l3-cdk-constructs#456 and the CLI schema in #2791, neither of which is in this stack, so I left the policy to a follow-up on top of those. The PR description now states the limitation, and the "from the first deploy" claim is gone.

Comment thread src/handlers/project/shortcuts.ts Outdated
* elsewhere still calls Bedrock in this region until the target is edited in
* agentcore.json.
*/
export const BOX_GATEWAY_BEDROCK_REGION = "us-west-2";

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The region is hardcoded, though create already has one. The docstring says "create does not know the deploy region". But create/index.ts calls ctx.require(RegionKey) (flag → AWS_REGION → profile) before projectManager.create, and screen.tsx does the same. When aws-targets.json is empty, deploy falls back to that same resolution, so for a first deploy this is the deploy region in practice. With the hardcoded value, an eu-* or ap-* user's model traffic crosses to us-west-2 without any notice. That can be a data-residency issue, and it differs from what the same agent does without Box.

Suggestion: pass the resolved region into resolveRuntimeTemplateShortcut / getBoxGatewayBedrockEntry, and keep us-west-2 only as a fallback. Or at least write a stderr notice when the resolved region differs, the way stripCreateRegionUnavailableDefaults does. Either way, the docstring should be reworded. Also note: China is already rejected for Bedrock agents, but GovCloud is not. There, this commercial bedrock-runtime.us-west-2.amazonaws.com endpoint is in the wrong partition.

— 🤖 Abhilash's Claude Bot

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 3d2203f: the target now uses the region the command resolved (--region, AWS_REGION, then the profile), with us-west-2 only as the fallback for a caller that passes none. GovCloud gets its own bedrock-runtime.us-gov-* endpoint. The docstring is reworded.

Comment thread src/handlers/project/types.ts Outdated
* The entry that adds the template's targets (the Bedrock model endpoint) to this runtime's Box
* gateway, `<runtime>-box`; absent when the agent calls no Bedrock model.
*/
boxGatewayEntry: AgentCoreGatewaySchema.optional(),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This field is create-only, but it sits on the shared input type. Only createProjectTree reads boxGatewayEntry. add runtime takes the same ScaffoldRuntimeInputSchema (add/runtime/types.ts:27) and silently ignores it. So in a Box project, a second Bedrock runtime added with agentcore add runtime gets a <runtime>-box gateway with no bedrock target, while the first runtime has one. If that is intended for now, a line in the doc comment would help. Otherwise, derive the entry from runtimeName/modelProvider/modelId where the spec is written (e.g. with callsBedrockModel), so create and add behave the same and the input type doesn't carry a derived value.

— 🤖 Abhilash's Claude Bot

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 3d2203f: boxGatewayEntry is no longer on ScaffoldRuntimeInput. boxGatewayEntryForRuntime() derives the entry where the spec is written, in createProjectTree and in addResource for a runtime (Box projects only), so add runtime --agent-id gives an imported Bedrock agent the same bedrock target. Covered in add/runtime/index.test.ts.

…me too

The Bedrock target of a runtime's Box gateway entry now uses the region
the command resolved (flag, AWS_REGION, then the profile), which is the
region a first deploy uses when aws-targets.json is empty, instead of a
fixed us-west-2. us-west-2 stays only as the fallback for a caller that
passes no region. A GovCloud region gets its own endpoint.

The entry is derived where the spec is written, by
boxGatewayEntryForRuntime(), instead of being carried on
ScaffoldRuntimeInput, so `create` and `add runtime` give a runtime the
same entry. In a Box project, a Bedrock Agent imported with
`add runtime --agent-id` now gets the Bedrock target on its Box gateway.

This branch has not been deployed

No deployments
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.

4 participants