AgentCore Harness
Generate an Amazon Bedrock AgentCore Harness project. A Harness is a managed agent loop powered by Strands Agents: it owns deployment defaults for the model, system prompt, tools, memory, skills, environments, truncation, authorization, and execution limits, while the service accepts per-invocation overrides for supported fields. Reusing the same Runtime Session ID continues the same Harness session.
Generate an AgentCore Harness
Section titled “Generate an AgentCore Harness”Run this generator@aws/nx-plugin:agentcore-harness
pnpm nx g @aws/nx-plugin:agentcore-harness yarn nx g @aws/nx-plugin:agentcore-harness npx nx g @aws/nx-plugin:agentcore-harness bunx nx g @aws/nx-plugin:agentcore-harness- Install the Nx Console VSCode Plugin if you haven't already
- Open the Nx Console in VSCode
- Click
Generate (UI)in the "Common Nx Commands" section - Search for
@aws/nx-plugin - agentcore-harness - Fill in the required parameters
- Click
Generate
Build your command6
Required
Options
Section titled “Options”nameRequiredstringThe name of your AgentCore Harness project. Must contain at least one non-whitespace character which can be normalized into a kebab-case project name (eg. my-harness).
directorystringParent directory where the harness project is placed. Defaults to packages. Must be a relative path which does not contain parent directory (..) segments.
subDirectorystringThe sub directory the project is placed in. Defaults to the kebab-case harness name. Must be a relative path which does not contain parent directory (..) segments.
infraenumDefault:agentcoreThe type of infrastructure to generate for hosting your harness. Defaults to agentcore. Select none for no hosting.
agentcorenoneiacenumDefault:inheritThe preferred IaC provider for generated harness infrastructure. Defaults to inherit, which uses the provider configured for your workspace.
inheritcdkterraformpreferInstallDependenciesbooleanWhether to prefer installing dependencies after the generator runs. Defaults to true. Set to false to defer installing when batching multiple generators (an install still runs if needed so subsequent generators can compute the Nx project graph); install once at the end.
Generator Output
Section titled “Generator Output”The generator creates a standalone project at packages/<name>/. Because AWS runs the agent loop for you, the project holds only the prompt that shapes it and a script for talking to it:
Directorypackages/<name>/
- src/PROMPT.md The Harness system prompt
- scripts/chat.ts Multi-turn chat client for the deployed Harness
- tsconfig.json TypeScript configuration used by the
typechecktarget - project.json Adds the
chat,build,lint,formatandtypechecktargets - README.md Chat and customization instructions
Infrastructure
Section titled “Infrastructure”Infrastructure is generated when infra is agentcore (the default). With infra: none no infrastructure is generated — set HARNESS_ARN to invoke a Harness managed elsewhere, and re-run the generator with infra: agentcore later to add infrastructure; existing project files (including your edits) are preserved.
Since this generator vends infrastructure as code based on your chosen iac, it will create a project in packages/common which includes the relevant CDK constructs or Terraform modules.
The common infrastructure as code project is structured as follows:
Directorypackages/common/constructs
Directorysrc
Directoryapp/ Constructs for infrastructure specific to a project/generator
- …
Directorycore/ Generic constructs which are reused by constructs in
app- …
- index.ts Entry point exporting constructs from
app
- project.json Project build targets and configuration
Directorypackages/common/terraform
Directorysrc
Directoryapp/ Terraform modules for infrastructure specific to a project/generator
- …
Directorycore/ Generic modules which are reused by modules in
app- …
- project.json Project build targets and configuration
Directorypackages/common/constructs/src/app/harnesses/<name>/
- <name>.ts CDK construct containing the Harness and execution role
Directorypackages/common/terraform/src/app/harnesses/<name>/
- <name>.tf Terraform module containing the Harness and execution role
The generated infrastructure manages the Harness through the native resource (CDK aws_bedrockagentcore.CfnHarness, Terraform aws_bedrockagentcore_harness) with your generated defaults, creates an IAM execution role with the baseline permissions described below, and uses IAM inbound authorization (no custom JWT authorizer is configured by default).
The Harness ARN is registered at agentcore.harnesses.<ClassName> in Runtime Configuration, preserving any existing entries.
Deploying your AgentCore Harness
Section titled “Deploying your AgentCore Harness”The generator creates CDK or Terraform infrastructure as code based on your selected iac provider. You can use this to deploy your Harness through your usual infrastructure workflow.
The CDK construct for deploying your Harness lives in the common/constructs folder. Instantiate it from a CDK application:
import { MyHarness } from '@my-scope/common-constructs';import { Stack, type StackProps } from 'aws-cdk-lib';import type { Construct } from 'constructs';
export class ApplicationStack extends Stack { constructor(scope: Construct, id: string, props?: StackProps) { super(scope, id, props);
new MyHarness(this, 'MyHarness'); }}The construct’s props interface (MyHarnessProps) extends Partial<Omit<CfnHarnessProps, 'executionRoleArn' | 'allowedTools'>>, so any native Harness property can be supplied and takes precedence over the generated defaults:
const harness = new MyHarness(this, 'MyHarness', { maxIterations: 20, timeoutSeconds: 600,});The construct also accepts:
allowedTools— the tools the Harness may use. Defaults to none, see Configuring tools.executionRole— an existing IAM role to use instead of the generated role. A supplied role is used as-is: the baseline permissions are not added to it, and its ARN always feeds the Harness (the rawexecutionRoleArnstring cannot be overridden).modelResourceArns— the Bedrock model and inference-profile ARNs the generated execution role may invoke, replacing the default list.vpc,vpcSubnetsandsecurityGroups— run the Harness in a VPC so it can reach private resources, see Running in a VPC.
Its public members are harness (the CfnHarness), executionRole, grantPrincipal, the harnessArn getter, connections (in a VPC), addToRolePolicy(statement) for execution role extensions, and grantInvokeAccess(grantee) for authorizing callers.
Deploy the stack with your infrastructure project as usual — see the CDK infrastructure guide.
The Terraform module for deploying your Harness is in the common/terraform folder. Reference it from a Terraform configuration:
module "my_harness" { source = "../../common/terraform/src/app/harnesses/my-harness"}The module exposes the following variables:
model_id— the Bedrock model or inference profile the Harness uses by default.allowed_tools— the tools the Harness may use. Defaults to none, see Configuring tools.memory— the Harness memory configuration, see Configuring memory.environment_variables,max_iterations,timeout_seconds— the corresponding native Harness fields.execution_role_arn— an existing IAM role to use instead of the generated role. A supplied role is used as-is: neither the role nor its baseline policy is created, somodel_resource_arnsandadditional_execution_role_policy_statementscannot be combined with it.model_resource_arns— the Bedrock model and inference-profile ARNs the generated execution role may invoke, replacing the default list.additional_execution_role_policy_statements— a list of IAM statement objects (Effect,Action,Resource, optionalSidandCondition) appended to the generated execution role policy.enable_vpc,vpc_id,subnet_ids— run the Harness in a VPC so it can reach private resources, see Running in a VPC.tags— tags applied to the resources the module creates.
Other provider-native fields are configured by editing the generated aws_bedrockagentcore_harness resource in the module itself, see Customizing your Harness.
The module outputs harness_id, harness_arn, execution_role_arn and security_group_id.
Deploy with your Terraform project’s plan/apply workflow as usual — see the Terraform project guide.
Granting access to invoke the harness
Section titled “Granting access to invoke the harness”You can grant a caller permissions to invoke the harness as follows:
const harness = new MyHarness(this, 'MyHarness');
harness.grantInvokeAccess(caller);# Attach to the calling principal's roleresource "aws_iam_role_policy" "invoke_my_harness" { name = "InvokeMyHarness" role = aws_iam_role.caller.id
policy = jsonencode({ Version = "2012-10-17" Statement = [{ Effect = "Allow" Action = [ "bedrock-agentcore:InvokeHarness", "bedrock-agentcore:InvokeAgentRuntime", ] Resource = [module.my_harness.harness_arn] }] })}A caller needs both bedrock-agentcore:InvokeHarness and bedrock-agentcore:InvokeAgentRuntime on the Harness ARN, which is exactly what grantInvokeAccess grants.
Chatting with your Harness
Section titled “Chatting with your Harness”The generated chat target runs scripts/chat.ts, dropping you into an interactive terminal chat with your deployed Harness:
pnpm nx run <project>:chatyarn nx run <project>:chatnpx nx run <project>:chatbunx nx run <project>:chatEvery turn of a run shares one session, so the Harness keeps the conversation context until you exit. Credentials come from the standard AWS SDK credential provider chain, and the AWS Region is derived from the Harness ARN.
The Harness ARN is resolved in this order:
-
HARNESS_ARN(non-empty): used directly, without reading Runtime Configuration:Terminal window HARNESS_ARN=<harness-arn> pnpm nx run <project>:chatTerminal window HARNESS_ARN=<harness-arn> yarn nx run <project>:chatTerminal window HARNESS_ARN=<harness-arn> npx nx run <project>:chatTerminal window HARNESS_ARN=<harness-arn> bunx nx run <project>:chat -
RUNTIME_CONFIG_APP_ID: resolves the ARN from theagentcore.harnesses.<ClassName>entry published by the deployed infrastructure:Terminal window RUNTIME_CONFIG_APP_ID=<application-id> pnpm nx run <project>:chatTerminal window RUNTIME_CONFIG_APP_ID=<application-id> yarn nx run <project>:chatTerminal window RUNTIME_CONFIG_APP_ID=<application-id> npx nx run <project>:chatTerminal window RUNTIME_CONFIG_APP_ID=<application-id> bunx nx run <project>:chat
With neither set, the script fails with an error naming both options.
Customizing your Harness
Section titled “Customizing your Harness”src/PROMPT.md is the Harness system prompt: edit it and redeploy to change how the Harness behaves. Everything else is configured where you instantiate the infrastructure, or by editing the generated construct or module directly. Re-running the generator never overwrites existing files (it only adds missing files and merges project metadata), so your edits to the prompt and to the generated infrastructure are preserved.
Every native Harness property of the pinned aws-cdk-lib/aws-bedrockagentcore module is available through the construct’s props — alternate model providers, tool definitions, memory, skills, environment configuration, truncation, custom JWT authorization, and execution limits — and explicit props take precedence over the generated defaults. Alternatively, edit the generated construct in packages/common/constructs/src/app/harnesses/<name>/<name>.ts.
The module’s variables cover the fields most deployments configure — model_id, allowed_tools, memory, environment_variables, max_iterations, timeout_seconds — plus the execution role and VPC placement. Terraform has no equivalent of the CDK construct’s prop spread, so the remaining provider-native fields are configured by editing the aws_bedrockagentcore_harness resource in packages/common/terraform/src/app/harnesses/<name>/<name>.tf: alternate model providers (gemini_model_config, openai_model_config), tool blocks, skill blocks, environment_artifact, filesystem and lifecycle configuration under environment, truncation, and authorizer_configuration with a custom_jwt_authorizer.
Omitting authorizer configuration (the default) means IAM inbound authorization; configure a custom JWT authorizer through the native field to change that.
Configuring tools
Section titled “Configuring tools”The Harness deploys with no tools, so it starts with the least capability. Opt in to the tools it may use:
new MyHarness(this, 'Harness', { allowedTools: ['@builtin'] });module "my_harness" { source = "../../common/terraform/src/app/harnesses/my-harness" allowed_tools = ["@builtin"]}Narrow @builtin to specific patterns such as @builtin/file_operations to restrict what the agent loop can do. See Harness tools for the built-in tools you can add.
Configuring memory
Section titled “Configuring memory”The service provisions managed memory for the Harness by default, and the generated execution role is granted access to it — scoped to the memory ARN the service assigns, and only granted while the Harness uses managed memory the infrastructure created. Configure memory explicitly to tune that managed memory, point the Harness at a memory resource you own, or turn memory off:
new MyHarness(this, 'MyHarness', { memory: { managedMemoryConfiguration: { strategies: ['SUMMARIZATION'] } },});Supplying memory at all replaces the default managed memory, so the construct leaves the memory grant off the execution role: add whatever the configuration needs with addToRolePolicy.
module "my_harness" { source = "../../common/terraform/src/app/harnesses/my-harness" memory = { managed_memory_configuration = { strategies = ["SUMMARIZATION"] } }}Set exactly one of managed_memory_configuration (tune the service’s managed memory), agentcore_memory_configuration (use a memory resource you own, by ARN) or disabled (no memory). Choosing agentcore_memory_configuration or disabled drops the managed-memory grant from the execution role; for your own memory resource, grant access through additional_execution_role_policy_statements.
Running in a VPC
Section titled “Running in a VPC”Supply a vpc to run the Harness inside it, so it can reach private resources such as a database. The construct implements IConnectable, so those resources grant it access the same way they would any other:
const harness = new MyHarness(this, 'MyHarness', { vpc });
database.connections.allowDefaultPortFrom(harness, 'Harness to database');The Harness is placed in the VPC’s private subnets with egress, in a security group created for it. Override either with vpcSubnets and securityGroups. Both require vpc, and connections is only available when the Harness runs in a VPC.
Set enable_vpc alongside vpc_id and subnet_ids to run the Harness inside a VPC, so it can reach private resources such as a database:
module "my_harness" { source = "../../common/terraform/src/app/harnesses/my-harness" enable_vpc = true vpc_id = var.vpc_id subnet_ids = var.private_subnet_ids}The module creates a security group for the Harness, allowing outbound HTTPS only. Its security_group_id output is what resources the Harness must reach reference in their own ingress rules:
resource "aws_vpc_security_group_ingress_rule" "harness_to_database" { security_group_id = aws_security_group.database.id referenced_security_group_id = module.my_harness.security_group_id from_port = 5432 to_port = 5432 ip_protocol = "tcp" description = "Harness to database"}security_group_id is null unless enable_vpc is true, and vpc_id and subnet_ids are both required when it is.
Per-invocation overrides
Section titled “Per-invocation overrides”The values configured in infrastructure are deployment defaults. The service also accepts per-invocation overrides for supported Harness fields (such as models, tools, and skills) in the InvokeHarness request; deployment defaults apply wherever a field is not overridden.