Skip to content

fix(import): harden Bedrock Agent runtime imports - #2153

Open
aidandaly24 wants to merge 3 commits into
aws:refactorfrom
aidandaly24:fix/bedrock-agent-import
Open

fix(import): harden Bedrock Agent runtime imports#2153
aidandaly24 wants to merge 3 commits into
aws:refactorfrom
aidandaly24:fix/bedrock-agent-import

Conversation

@aidandaly24

Copy link
Copy Markdown
Contributor

Context

PR #2146 added project create --type import and project add runtime --type import to wrap an existing Amazon Bedrock Agent in an AgentCore Runtime proxy. Post-merge testing found eight defects in the import path. This PR fixes those defects without changing --type create.

Bugs fixed

Service discovery and readiness

  1. Malformed GetAgent responses were validated too late. The CLI requested the alias before validating the agent response. An alias-not-found response therefore replaced the earlier malformed-agent error. The control-plane client now validates required agent identity fields before requesting the alias, then validates that the returned alias belongs to the requested agent and alias ID.

  2. Readiness checked the mutable agent draft instead of the selected alias. The generated proxy invokes agentId plus agentAliasId, but the CLI warned on agentStatus. It now warns when agentAliasStatus is not PREPARED and does not warn when a prepared alias points to a version while the mutable draft is NOT_PREPARED.

  3. Four predecessor-supported regions were rejected. The import allowlist now includes ap-southeast-2, eu-central-2, eu-west-2, and eu-west-3.

Runtime configuration

  1. Non-HTTP imports called AWS before local validation. --type import --protocol MCP previously described the agent before the template rejected the protocol. The handler now rejects non-HTTP protocols before any Bedrock Agent API call.

  2. Caller-owned roles appeared to receive a policy that CDK did not attach. AgentCore CDK imports executionRoleArn roles without modifying them, but the generated runtime still listed bedrock-agent-policy.json in additionalPolicies. The CLI now:

    • emits a warning that the existing role must already allow bedrock:InvokeAgent on the selected alias;
    • omits the generated policy from additionalPolicies when executionRoleArn is supplied; and
    • keeps bedrock-agent-policy.json as the exact document the user must attach, with matching generated README guidance.

Generated proxy runtime

  1. Valid non-object JSON payloads crashed. Payloads such as [] reached payload.get and raised AttributeError. The proxy now returns a controlled validation response and does not call Bedrock.

  2. AgentCore session IDs were forwarded without adapting the Bedrock Agent contract. AgentCore Runtime accepts session IDs longer than the Bedrock Agent maximum of 100 characters. The proxy now preserves IDs that already satisfy the Bedrock pattern and deterministically hashes incompatible IDs to a 64-character value. This preserves multi-turn continuity for repeated AgentCore session IDs.

  3. Synchronous boto3 work blocked the async runtime loop. The async entrypoint called invoke_agent and iterated its event stream synchronously. Both operations now run through asyncio.to_thread, while the response remains streamed one event at a time.

Validation

Automated

  • bun test src/core/project/bedrockAgent.test.ts src/handlers/project/importBedrockAgent.test.ts src/handlers/project/add/runtime/index.test.ts src/handlers/project/project.test.ts
    • 148 passed, 0 failed
  • bun test src
    • 2,594 passed, 0 failed across 189 files
  • bun run typecheck
  • bun run lint:check
  • bun run format:check
  • bun run build
  • Python syntax compilation of the generated proxy template

Executable Python proxy probe

The generated proxy template was executed with stubbed AgentCore and boto3 modules:

  • compatible session IDs remained unchanged;
  • a 101-character session ID normalized to the same 64-character value on repeated calls;
  • a non-object payload returned the validation response and made zero service calls; and
  • two simulated 200 ms synchronous service calls completed concurrently in 202 ms.

Live AWS lifecycle

Using AWS_PROFILE=deploy in account 603141041947, region us-east-1:

  • created and prepared Bedrock Agent NFGNHKMZXK and alias WABJLTQRXC;
  • imported the alias with the bundled CLI, installed dependencies, and generated the alias-scoped bedrock:InvokeAgent policy;
  • deployed stack AgentCore-ImportFix0831-default to CREATE_COMPLETE;
  • normal runtime invocation returned The capital of France is Paris.;
  • a 101-character AgentCore runtime session returned LONG_SESSION_OK instead of a Bedrock validation error;
  • payload [] returned Invalid payload; expected a JSON object with a non-empty 'prompt' field. instead of AttributeError; and
  • exercised the caller-owned-role path against the live alias and verified the warning, runtime spec, policy document, and README guidance.

The stack, AgentCore Runtime, Bedrock Agent alias, Bedrock Agent, inline policy, and IAM role were deleted after testing. No test AWS resources remain.

Out of scope

--type create behavior is intentionally unchanged. Existing project-manager dependency-install rollback behavior and the runtime invoke HTTP-200 error-event contract are also unchanged because they predate Bedrock Agent import.

@github-actions github-actions Bot added the size/m PR size: M label Aug 31, 2026
@agentcore-devx-automation agentcore-devx-automation Bot added agentcore-harness-reviewing AgentCore Harness review in progress claude-security-reviewing Claude Code /security-review in progress labels Aug 31, 2026
@agentcore-devx-automation

Copy link
Copy Markdown
Contributor

Claude Security Review: no high-confidence findings. (run)

@agentcore-devx-automation agentcore-devx-automation Bot removed the claude-security-reviewing Claude Code /security-review in progress label Aug 31, 2026
@codecov-commenter

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 95.23810% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 97.37%. Comparing base (d304147) to head (3022a49).

Files with missing lines Patch % Lines
src/core/project/bedrockAgent.ts 94.11% 4 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##           refactor    #2153      +/-   ##
============================================
+ Coverage     97.22%   97.37%   +0.14%     
============================================
  Files           507      507              
  Lines         33809    33841      +32     
============================================
+ Hits          32872    32951      +79     
+ Misses          937      890      -47     

☔ 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.

@agentcore-devx-automation agentcore-devx-automation 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.

AgentCore Harness Review

Verdict: Looks good

Reviewed the eight fixes against bedrockAgent.ts, importBedrockAgent.ts, templates/runtime.ts, and the Python proxy template. The changes are well-scoped, all failure modes are covered by tests at real I/O boundaries (control-plane client injection, in-memory describeBedrockAgent fakes), and the live-lifecycle validation in the description confirms the caller-owned-role and long-session-id paths end-to-end.

A few things I looked at and am comfortable with:

  • Session-id normalization (main.py): 64-char SHA-256 hex matches the ^[0-9A-Za-z._:-]{2,100}$ pattern, non-string/empty inputs correctly fall through to a fresh UUID, and empty context.session_id short-circuits to payload.get("sessionId") as intended.
  • Response validation (bedrockAgent.ts): agent.agentId / agent.agentName are now checked before getAgentAlias, and the alias response is cross-checked against the requested IDs, which is what the description promised.
  • additionalPolicies omission with executionRoleArn (templates/runtime.ts): the generated bedrock-agent-policy.json file is preserved for the user to attach manually, and the README template branches on usesExistingExecutionRole to match — I traced both branches through importBedrockAgentResolver and the rendered README.
  • Protocol pre-check in add/runtime/index.ts correctly runs before resolveImportBedrockAgentInput, so --protocol MCP no longer triggers a Bedrock describe call (verified by the new rejects a non-HTTP protocol before describing the agent test).

One minor observation, not blocking: bedrockAgent.ts switched from await import("@aws-sdk/client-bedrock-agent") to a top-level static import. This is consistent with src/core/invokeRuntime.ts (which also statically imports an AWS SDK command class on a hot handler path), so it's aligned with existing convention — just noting the deviation from the previous lazy-load pattern in case CLI cold-start latency is being tracked.

Nice work.

@agentcore-devx-automation agentcore-devx-automation Bot removed the agentcore-harness-reviewing AgentCore Harness review in progress label Aug 31, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/m PR size: M

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants