Bedrock AgentCore Harness lets us create a simple AI agent by just specifying what we need to get done. This is a great tool for building GenAI applications, but it can also be used to integrate AI into various AWS services, adding a smart layer to our everyday workflows.
Bedrock AgentCore Harness
AgentCore Harness is a GenAI service that lets you run a configuration-defined agent in an isolated MicroVM environment in AWS. You basically define the task, and AgentCore Harness takes care of the rest. When I think about this, I can't avoid comparing it with the Claude Agent SDK, it is very similar in the way agents are defined. However, AgentCore Harness also simplifies the execution, as the serverless infrastructure and deployment is automatically handled by AgentCore.
The Harness agent has access to several different tools:
- File and Shell Operations
- Short and long-term memory
- AgentCore gateway
- MCP servers
- Built-in browser
- Code interpreter
- S3 or EFS mounts
- AWS skills from Git, S3, or the curated AWS skills catalog
You can use a wide range of Model providers such as Amazon Bedrock, OpenAI, Google Gemini, or any other providers through LiteLLM.
CodePipeline
The first thing I wanted to try was a code review step inside a pipeline. Why? With so much vibe coding going on, it is a good idea to add a code review step into the pipeline to catch any bugs that the coding tool may introduce. That is a great job for an agent.
I added a ReleaseReview action after the typical Source, Build and Test steps.
The action is a Lambda that first collects the facts by itself: changed paths, test summary, and a grep of the diff looking for risk signals (DB migrations, IAM changes, IaC, feature flags). Then it sends those facts to the release_review harness, and the agent replies with a JSON verdict: a decision, a risk score, and a list of findings.
ReleaseReviewHarness:
Type: AWS::BedrockAgentCore::Harness
Properties:
HarnessName: release_review
ExecutionRoleArn: !GetAtt HarnessExecutionRole.Arn
Model:
BedrockModelConfig:
ModelId: us.amazon.nova-2-lite-v1:0
Temperature: 0.0
AllowedTools: []
Memory:
Disabled: {}
MaxIterations: 4
TimeoutSeconds: 120
SystemPrompt:
- Text: |-
You are a release-review agent embedded in a CI/CD pipeline. You are given
facts that were already gathered deterministically: a git diff, changed
files, a test summary, and pre-computed risk signals. You DO NOT deploy
anything and you DO NOT run commands. Reason over the facts and return a
release verdict. Be conservative: when unsure, prefer "concerns" over "pass".
Return a JSON object that conforms EXACTLY to this JSON Schema:
{"type":"object","required":["decision","risk_score","findings","release_note"],
"properties":{
"decision":{"enum":["pass","concerns","block"]},
"risk_score":{"type":"integer","minimum":0,"maximum":100},
"findings":{"type":"array","items":{"required":["severity","file","message"]}},
"release_note":{"type":"string"}}}
StepFunctions
The second one is a document extraction workflow. Step Functions ingests and validates the document, and then calls the extract_and_judge harness using the native bedrockagentcore:invokeHarness integration (no Lambda needed for the invoke). The agent returns the extracted fields, a confidence score and a list of flags, so it is also grading its own work. A ParseVerdict step validates that output, and the Choice state does the routing:
- confidence >= 0.8 and no hard flags: the extraction is persisted.
- low confidence or a hard flag: it goes to human review.
ReleaseReviewHarness:
Type: AWS::BedrockAgentCore::Harness
Properties:
HarnessName: release_review
ExecutionRoleArn: !GetAtt HarnessExecutionRole.Arn
Model:
BedrockModelConfig:
ModelId: us.amazon.nova-2-lite-v1:0
Temperature: 0.0
AllowedTools: []
Memory:
Disabled: {}
MaxIterations: 4
TimeoutSeconds: 120
SystemPrompt:
- Text: |-
You are a release-review agent embedded in a CI/CD pipeline. You are given
facts that were already gathered deterministically: a git diff, changed
files, a test summary, and pre-computed risk signals. You DO NOT deploy
anything and you DO NOT run commands. Reason over the facts and return a
release verdict. Be conservative: when unsure, prefer "concerns" over "pass".
Return a JSON object that conforms EXACTLY to this JSON Schema:
{"type":"object","required":["decision","risk_score","findings","release_note"],
"properties":{
"decision":{"enum":["pass","concerns","block"]},
"risk_score":{"type":"integer","minimum":0,"maximum":100},
"findings":{"type":"array","items":{"required":["severity","file","message"]}},
"release_note":{"type":"string"}}}
EventBridge
The third one is the easiest to add to something you already have. A rule matches an event, a Lambda calls the harness, and the answer is written down. This amplifies troubleshooting or cloud-generated events with an AI layer.
I built two variants:
security-responder: GuardDuty or Security Hub findings enhanced into an incident summary with a severity and a suggested remediation.
deploy-annotator: CloudWatch alarms and deploy events enhanced into a report with what changed, what fired, and what to check first.
SecurityResponderHarness:
Type: AWS::BedrockAgentCore::Harness
Properties:
HarnessName: security_responder
ExecutionRoleArn: !GetAtt HarnessExecutionRole.Arn
Model:
BedrockModelConfig:
ModelId: us.amazon.nova-2-lite-v1:0
Temperature: 0.0
AllowedTools: []
Memory:
Disabled: {}
MaxIterations: 4
TimeoutSeconds: 120
SystemPrompt:
- Text: |-
You are a security-finding responder triggered by an EventBridge rule when a
GuardDuty or Security Hub finding lands on the bus. Your job is STRICTLY
ADVISORY: correlate the signals and draft an incident summary with suggested
remediation. You do NOT remediate, quarantine, or change anything. A human
reads your summary and decides.
Return a JSON object that conforms EXACTLY to this JSON Schema:
{"type":"object",
"required":["summary","correlated_signals","suggested_remediation","severity"],
"properties":{
"summary":{"type":"string"},
"correlated_signals":{"type":"array","items":{"type":"string"}},
"suggested_remediation":{"type":"array","items":{"type":"string"}},
"severity":{"enum":["low","medium","high","critical"]}}}
A few things I ran into
- The harness invoke API (
invoke_harness) needs boto3 >= 1.43.36, newer than the version bundled in Lambda. I had to build it into a layer. - Every invocation spins up a fresh session microVM, so the first response takes around 20-25 seconds before streaming starts (the model itself is fast). Keep that in mind with your Lambda and Task timeouts.
Source Code
All of these architectures have been implemented using CloudFormation. You can check the source code in this repo.



Top comments (0)