Skip to content

feat(export): export harnesses to standalone Strands agents with connections#1630

Merged
padmak30 merged 8 commits into
mainfrom
feat/harness-export-connections
Jun 25, 2026
Merged

feat(export): export harnesses to standalone Strands agents with connections#1630
padmak30 merged 8 commits into
mainfrom
feat/harness-export-connections

Conversation

@padmak30

Copy link
Copy Markdown
Contributor

Description

Extend agentcore export harness to faithfully export harnesses that reference external AgentCore resources — in-project (--name) or by ARN (--arn) — with no manual IAM/wiring overrides.

  • Auto-populate connections[] (memory/gateway/runtime/browser/codeInterpreter) on the exported runtime instead of emitting IAM prose notes. Discovery env-var names are derived from a single source of truth in schemas/connections.ts, kept in lockstep with @aws/agentcore-cdk, so the names baked into the generated agent code match what deploy injects.
  • New --arn source: fetch a harness from the control plane and map it (fetch-harness-spec.ts) — model (incl. LiteLLM), memory, runtime environment, skills (git auth carried through), and tools.
  • LiteLLM model-provider support: provider-prefixed model_ids (keyless via IAM for bedrock/, apiKeyArn otherwise) across schema, template, and telemetry.
  • Gateway outbound-auth (awsIam | none | oauth{providerArn, scopes, grantType, customParameters}) threaded end-to-end; customParameters rendered as valid Python via safeJson and grantTypeauth_flow.
  • Path-skill directory copy for generated-Dockerfile Container builds; verify-note when the path isn't local.

Related Issue

Closes #

Dependent change

Requires the CDK construct PR: aws/agentcore-l3-cdk-constructs#291 (the connections wiring + lockstep schema). That should merge and publish first.

Type of Change

  • New feature

Testing

  • I ran npm run test:unit (946 export + schema tests pass)
  • I ran npm run typecheck (clean)
  • I ran npm run lint (clean)
  • Modified src/assets/ → ran npm run test:update-snapshots and committed the updated snapshot
  • Live end-to-end (account 053460373529, us-east-1): for every export path (memory+gateway, LiteLLM, browser/code-interpreter, S3/path/git skills, OAuth gateway), exported both in-project (--name) and out-of-project (--arn), deployed, and invoked. In-project and out-of-project produce identical connection wiring. Verified runtime behavior: gateway tool executes, memory recall works, code-interpreter runs, S3/path/private-git skills load, and the OAuth connection's IAM + token-fetch wiring is correct.

Checklist

  • I have added tests that prove the feature works
  • My changes generate no new warnings
  • Any dependent changes have been merged and published (blocked on agentcore-l3-cdk-constructs#291)

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

padmak30 added 2 commits June 24, 2026 00:17
…ections

Extend `agentcore export harness` to faithfully export harnesses that reference
EXTERNAL AgentCore resources, in-project (--name) or by ARN (--arn), with no
manual IAM/wiring overrides.

- Auto-populate `connections[]` (memory/gateway/runtime/browser/codeInterpreter)
  on the exported runtime instead of emitting IAM prose notes. Discovery env-var
  names are derived from a single source of truth in schemas/connections.ts and
  kept in lockstep with @aws/agentcore-cdk, so the names baked into the generated
  agent code match what deploy injects.
- New --arn source: fetch a harness from the control plane and map it
  (fetch-harness-spec.ts) — model (incl. LiteLLM), memory, runtime environment,
  skills (git auth carried through), and tools.
- Add LiteLLM model-provider support (provider-prefixed model_ids; keyless via
  IAM for bedrock/, apiKeyArn otherwise) across schema, template, and telemetry.
- Carry gateway outbound-auth (awsIam | none | oauth{providerArn, scopes,
  grantType, customParameters}) end-to-end; render customParameters as valid
  Python via safeJson and thread grantType -> auth_flow.
- Copy path-skill directories for generated-Dockerfile Container builds.

Verified live end-to-end: create harness -> export (in-project and by ARN) ->
deploy -> invoke; the agent reaches the external memory + gateway at runtime.
@padmak30 padmak30 requested a review from a team June 24, 2026 05:34
@github-actions github-actions Bot added the size/xl PR size: XL label Jun 24, 2026
@agentcore-devx-automation agentcore-devx-automation Bot added the claude-security-reviewing Claude Code /security-review in progress label Jun 24, 2026
@github-actions github-actions Bot added the agentcore-harness-reviewing AgentCore Harness review in progress label Jun 24, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Package Tarball

aws-agentcore-0.20.2.tgz

How to install

gh release download pr-1630-tarball --repo aws/agentcore-cli --pattern "*.tgz" --dir /tmp/pr-tarball
npm install -g /tmp/pr-tarball/aws-agentcore-0.20.2.tgz

@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 Jun 24, 2026
@github-actions

github-actions Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Coverage Report

Status Category Percentage Covered / Total
🔵 Lines 37.42% 13771 / 36800
🔵 Statements 36.69% 14646 / 39910
🔵 Functions 32% 2356 / 7362
🔵 Branches 31.46% 9180 / 29173
Generated in workflow #3825 for commit 840ca99 by the Vitest Coverage Report Action

@agentcore-cli-automation agentcore-cli-automation 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 PR end-to-end. Looks good to merge.

Highlights of what I checked:

  • Test quality — No excessive mocking. The new unit tests (fetch-harness-spec.test.ts, arn-s3-chain.test.ts, harness-mapper.test.ts, harness-action.test.ts) use pure data fixtures and exercise the real mappers/builders without stubbing fs or the AWS SDK; the network boundary (getHarness) is correctly drawn at the wrapper rather than mocked inside the unit tests.
  • Telemetryexport.harness is registered in COMMAND_SCHEMAS with build_type, model_provider (incl. lite_llm), has_memory, has_gateway, has_container, has_execution_limits, notes_count. The action wraps execution in withCommandRunTelemetry and records attrs after work is done, with a correct LiteLLM → lite_llm normalization before standardize().
  • Connection-name handshake — env-var name derivation (connectionIdForTarget, connectionEnvToken, connectionEnvVarName) lives in one place (schema/schemas/connections.ts) and is consumed by both the CLI mapper and (per the description) the CDK wiring, which is the right shape for keeping the two repos in lockstep.
  • --arn fidelitymapApiHarnessToSpec defensively handles both control-plane (PascalCase) and lowercased skill shapes, the SDK_UNKNOWN_MEMBER managed-memory fallback, and explicitly does NOT carry executionRoleArn (with a clear comment explaining why CDK needs to own the role for Container/connection grants).
  • External-resource modeling — Memory/gateway/runtime/browser/codeInterpreter all flow through typed Connection entries on AgentEnvSpec instead of prose IAM notes; malformed browser/CI ARNs fall back to the AWS-managed default with a clear note rather than silently using the wrong target. S3 skills generate an inline policy + additionalPolicies entry, with malformed-URI warnings rather than silent AccessDenied.
  • OAuth gateway end-to-endgrantType → auth_flow mapping (CLIENT_CREDENTIALS→M2M, USER_FEDERATION→USER_FEDERATION) is correct; TOKEN_EXCHANGE is surfaced as a manual-step note since the decorator can't express it. customParameters rendered via safeJson is valid Python because the schema constrains values to Record<string,string>.
  • Path-skill copy — Correctly rejects absolute paths and traversal, only copies dirs that resolve under the harness dir, and emits a verify-note for the unresolved case (which is the expected outcome for --arn-fetched harnesses).

Caveats already called out in the PR description:

  • The schema additions (AgentEnvSpec.connections, AgentEnvSpec.additionalPolicies) require the CDK construct PR (aws/agentcore-l3-cdk-constructs#291) to merge and publish first — that checkbox is correctly left unchecked.

Nothing blocking from my read.

@github-actions github-actions Bot removed the agentcore-harness-reviewing AgentCore Harness review in progress label Jun 24, 2026
…dead helper

Review fixes for the harness-export connections feature:

- main.py template: emit `import os` when browserIdentifierEnvVar or
  codeInterpreterIdentifierEnvVar is set. A custom browser/code-interpreter
  ARN renders `os.getenv(...)` at module scope, but `import os` was gated only
  on filesystem mounts / file_operations / git-cred skills — so a Container
  export with a custom tool ARN and none of those produced a main.py that
  crashed at import with NameError. Snapshot updated.

- fetch-harness-spec: throw an early ValidationError when an --arn VPC harness
  is missing explicit subnets/securityGroups, instead of emitting
  networkMode:'VPC' with no networkConfig and crashing later in
  writeProjectSpec's schema validation after the agent dir/code were written.

- connections.ts: drop the dead exported `connectionEnvVarName` (imported by
  neither repo) and correct the "single source of truth" comment to name the
  helpers actually shared across repos (connectionEnvToken / connectionTokenFor).

- harness-action: move the inline `import('../../../schema').HarnessSpec` type
  to the top-of-file import (AGENTS.md: no inline imports).
@github-actions github-actions Bot added size/xl PR size: XL and removed size/xl PR size: XL labels Jun 24, 2026
@agentcore-devx-automation agentcore-devx-automation Bot added the claude-security-reviewing Claude Code /security-review in progress label Jun 24, 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 Jun 24, 2026
@github-actions github-actions Bot added the size/xl PR size: XL label Jun 24, 2026
@agentcore-devx-automation agentcore-devx-automation Bot added the claude-security-reviewing Claude Code /security-review in progress label Jun 24, 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 Jun 24, 2026
…ng it

A harness-owned ("managed") memory is a real resource with a service-populated
ARN once the harness is READY. mapMemory previously collapsed it to a bare
`{ mode: 'managed' }`, which resolveMemoryProviders ignores — so the exported
agent silently got no memory at all.

Map managedMemoryConfiguration.arn to `{ mode: 'existing', arn }` so it flows
through the existing external-memory path: a `memory` connection with
access: readwrite (IAM scoped to the ARN + discovery env var at deploy). The
bare `{ mode: 'managed' }` is now only a fallback for the no-ARN case
(unprovisioned harness, or an SDK-unknown variant); comments call out that this
fallback is not resolved downstream and where to wire it if needed.

- Type managedMemoryConfiguration on the harness client interface (was read via
  `as Record<string, unknown>`); agentCoreMemoryConfiguration is now optional
  since exactly one arm is populated.
- Tests: provisioned managed memory (with arn) -> existing-by-arn; managed
  without arn -> managed; SDK-unknown -> managed.

Verified live: re-exporting a code-interpreter harness whose managed memory has
an ARN now emits a memory connection in agentcore.json (previously absent).
@github-actions github-actions Bot removed the size/xl PR size: XL label Jun 24, 2026
@github-actions github-actions Bot added the size/xl PR size: XL label Jun 24, 2026
@agentcore-devx-automation agentcore-devx-automation Bot added the claude-security-reviewing Claude Code /security-review in progress label Jun 24, 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 Jun 24, 2026
padmak30 added 2 commits June 24, 2026 15:55
A harness bedrockModelConfig whose apiFormat is `responses`/`chat_completions`
(e.g. openai.gpt-5.5, openai.gpt-oss-120b) is served via the Bedrock Mantle
OpenAI-compatible endpoint, NOT the Converse API. Export previously keyed only on
the provider, generating a plain BedrockModel for these — so invocation failed at
runtime with "ConverseStream ... The provided model identifier is invalid".

Generate an OpenAI-style Mantle client instead:
- load.py: build OpenAIModel (chat_completions) / OpenAIResponsesModel
  (proprietary responses) / MantleCompatResponsesModel (open-source responses),
  against the Mantle base URL (/openai/v1 for proprietary, /v1 for gpt-oss),
  authenticated with a short-lived Bedrock bearer token (region from AWS_REGION).
- harness-mapper: detect Mantle, thread apiFormat/proprietary/params into the
  render config, and emit a bedrock-mantle IAM policy (CreateInference +
  CallWithBearerToken) via additionalPolicies — the runtime role's default
  bedrock:InvokeModel grant does not cover the bedrock-mantle service.
- Add openai + aws-bedrock-token-generator deps and vend model/mantle_compat.py.

Verified live end-to-end: export by ARN -> deploy -> invoke an openai.gpt-5.5
Mantle harness returns a real completion (previously the ConverseStream error).
Removed the "No AWS deployment target configured" note. It warned that
`agentcore deploy` would fail with `Target "default" not found` when
aws-targets.json is empty, but deploy already handles that case interactively
(ensure-target.ts prompts for account/region and writes a default target). The
note described a failure the deploy flow prevents, so it was noise.
@agentcore-devx-automation

Copy link
Copy Markdown
Contributor

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

@agentcore-devx-automation

Copy link
Copy Markdown
Contributor

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

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

Labels

size/xl PR size: XL

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants