
Advanced AgentCore Patterns: Harnesses, Human-in-the-Loop, and Container Agents
Part 3 of 3: From POC to Production with AWS Bedrock AgentCore
Series: From POC to Production with AWS Bedrock AgentCore (3 articles)
- 3Advanced AgentCore Patterns: Harnesses, Human-in-the-Loop, and Container Agents This article
Beyond the Single Agent
In Parts 1 and 2, I built a customer support agent, gave it memory, secured it with gateways and policies, and set up monitoring. That's a solid single-agent system.
But real-world workflows aren't one agent doing everything. They're more like a team: a front-line agent that handles common questions, a specialist that digs into complex research, a manager that approves high-stakes decisions, and an analyst that crunches numbers and produces reports.
This is where AgentCore's advanced features shine. Let me show you what happens when you stop thinking "agent" and start thinking "agent team."
Chapter 1: Harness Agents - Agents Without Code
The Concept
What if I told you that you could deploy a fully functional agent with tool access, secure gateway integration, code execution capabilities, and external skills, without writing a single line of Python?
That's what a Harness is. It's a declarative agent definition: you describe what you want (model, tools, system prompt), and AgentCore handles the rest.
Building the OrderResearchAgent
Bash
agentcore add harness \--name OrderResearchAgent \--model-provider bedrock \--model-id us.anthropic.claude-sonnet-4-6 \--system-prompt "You are an order research specialist. Help customers investigate order issues, check warranties, and produce detailed analysis reports. Always be thorough and provide structured summaries. Save reports to /tmp/ when asked." \--tools agentcore_code_interpreter
No
main.py . No framework imports. No deployment config. Just a declaration: "I want an agent that can research orders, write code, and produce reports."Then I gave it access to the same secure gateway my main agent uses:
Bash
agentcore add tool --harness OrderResearchAgent --type agentcore_gateway \--name my-gateway-secure \--gateway-arn "$GATEWAY_ARN" \--outbound-auth oauth \--provider-arn "$PROVIDER_ARN" \--scopes "$COGNITO_SCOPE" \--grant-type CLIENT_CREDENTIALS
Notice the CLIENT_CREDENTIALS grant type: this is machine-to-machine authentication. The harness agent authenticates itself (not on behalf of a user) to access the warranty and refund tools through the gateway. It stores its OAuth credentials in AgentCore's Token Vault.
Testing It
Bash
agentcore invoke --harness OrderResearchAgent \--session-id "$SESSION" \--actor-id "analyst-1" \"Check the warranty for PROD-001 and PROD-003. Save a comparison report to /tmp/warranty_report.md summarizing which products are still covered."
The agent:
- Called the warranty check tool for PROD-001 (via the gateway)
- Called the warranty check tool for PROD-003 (via the gateway)
- Used the code interpreter to write a structured markdown report
- Saved it to
/tmp/warranty_report.md
Then I could retrieve the report:
Bash
agentcore invoke --exec --harness OrderResearchAgent \--session-id "$SESSION" \"cat /tmp/warranty_report.md"
The
--exec flag means "just run this command in the agent's environment." Direct shell access to the code interpreter sandbox.The Analogy
If custom-code agents are like hiring a full-time employee (you write their entire job description, training materials, and workflows), harness agents are like hiring from a staffing agency. You say "I need someone who can do X, Y, and Z" and they show up ready to work. Less control, but dramatically faster time to value.
Chapter 2: Human-in-the-Loop: The Approval Gate
When Agents Shouldn't Decide Alone
Here's a scenario: a customer wants a $500 refund. Your policy says automated refunds cap at $100 (remember our Cedar policy from Part 2). But maybe a manager would approve this exception.
You don't want the agent to:
- Refuse outright ("Sorry, I can't help"): bad customer experience
- Approve it autonomously: too much risk
- Hallucinate an answer: dangerous
You want it to pause and ask a human.
Adding the Inline Function
Bash
agentcore add tool --harness OrderResearchAgent --type inline_function \--name approve_exception \--description "Request manager approval for a refund that exceeds the automated limit. Returns approved or denied with approver name." \--input-schema '{"type":"object","properties":{"order_id":{"type":"string"},"amount":{"type":"number"},"reason":{"type":"string"}},"required":["order_id","amount","reason"]}'
An inline function is a tool that doesn't execute code: it pauses the agent and waits for external input. When the agent decides it needs manager approval, it "calls" this tool, and the execution suspends until a human responds.
The Flow in Practice
I tested this with a script that simulates the operator experience:
Bash
agentcore invoke --harness OrderResearchAgent \--session-id "$(uuidgen)" \--actor-id "analyst-1" \'Process a refund of $500 for order ORD-12345 because the customer is unhappy.'
What happens:
- The agent recognizes $500 exceeds the automated limit
- It calls
approve_exceptionwith the order details
- The invocation pauses returns a "pending" status with the tool call details
- An operator (human or system) reviews the request
- The operator responds with approval or denial
- The agent resumes and communicates the outcome to the customer
The Analogy
This is exactly how a real call center works. The frontline agent handles what they can. When something exceeds their authority, they don't hang up on the customer, they say "let me check with my manager," put you on a brief hold, get the approval, and come back. HITL is that "hold" button for AI agents.
Why This Changes Everything
Most agent frameworks treat human-in-the-loop as an afterthought: something you bolt on with webhooks and polling loops. AgentCore makes it a first-class primitive. The agent's execution state is durably stored while paused. It can wait minutes, hours, or days. When the approval comes, it resumes exactly where it left off with full context intact.

Chapter 3: Code Interpreter - The Agent's Workbench
More Than Just Running Python
The Code Interpreter gives your agent a sandboxed environment to:
- Execute Python code
- Read and write files
- Install packages
- Generate visualizations
- Process data
It's not "let me calculate 2+2." It's "let me analyze this warranty data, cross-reference it with product categories, generate a summary table, and save it as an Excel file."
Adding External Skills
I added the
xlsx skill from Anthropic's public skills repository:Bash
agentcore add skill --harness OrderResearchAgent \--git https://github.com/anthropics/skills \--git-path skills/xlsx
Then asked the agent to produce a real report:
Bash
agentcore invoke --harness OrderResearchAgent \--session-id "$SESSION" \--actor-id "analyst-1" \"Create an Excel (.xlsx) report summarizing the warranty status of PROD-001 and PROD-003, then tell me where you saved it."
The agent queried the warranties, wrote Python code to create an Excel workbook with proper formatting, and saved it all within the sandboxed code interpreter.
Model Flexibility
One thing that impressed me: you can swap models mid-session for different tasks:
Bash
agentcore invoke --harness OrderResearchAgent \--model-id us.amazon.nova-2-lite-v1:0 \--session-id "$SESSION" \--actor-id "analyst-1" \"Summarize the warranty report in exactly 3 bullet points."
Same session, same context, but using a lighter (cheaper, faster) model for a simple summarization task. This is how you optimize cost in production; use the big model for complex reasoning, the small model for simple formatting.
Persistent Storage
For agents that need to keep files across invocations:
Bash
agentcore add harness \--name PersistentReportAgent \--model-provider bedrock --model-id us.anthropic.claude-sonnet-4-6 \--system-prompt "You are a report writer. Save all reports to /mnt/reports/ for persistent storage." \--tools agentcore_code_interpreter \--session-storage /mnt/reports/
The
--session-storage flag means files written to /mnt/reports/ survive across invocations. Monday's report is still there on Tuesday. This is huge for agents that build up artifacts over time; think weekly dashboards, cumulative logs, or evolving documentation.
Chapter 4: Container Agents - Bring Your Own Environment
When Python Isn't Enough
What if your agent needs Node.js? Or git? Or some specific system library? Container agents let you specify a Docker image:
Bash
agentcore add harness \--name ContainerAgent \--model-provider bedrock --model-id us.anthropic.claude-sonnet-4-6 \--system-prompt "You are a development assistant with access to git and node." \--container public.ecr.aws/docker/library/node:slim
Now your agent runs inside a Node.js container. It can
npm install , run JavaScript, use git; whatever that container supports. The agent isn't limited to Python's ecosystem anymore.The Analogy
If the code interpreter is a desk with a calculator and a notepad, a container agent is a fully equipped workshop. You choose what tools are on the wall (by picking the container image), and the agent can use any of them.
Chapter 5: The Frontend - Making It Real
A Chat UI That Talks to Production
All the CLI invocations are great for development, but customers don't use terminals. I built a Flask-based chat UI that connects directly to the deployed AgentCore runtime:
The frontend authenticates via Cognito, streams responses using Server-Sent Events, manages sessions, and provides quick-action buttons for common queries (Products, Returns, Warranty, Memory).
The key technical detail: the frontend calls the AgentCore runtime endpoint directly:
Plain text
POST https://bedrock-agentcore.{REGION}.amazonaws.com/runtimes/{ARN}/invocationsAuthorization: Bearer {cognito_token}
No intermediary API. No Lambda proxy. The frontend talks straight to AgentCore, with Cognito handling authentication. This is the simplest possible production architecture for an agent-powered UI.

The Full Picture
Let me zoom out and show what we've built across all three posts:
Plain text
[Chat Frontend]|[Cognito JWT]|[AgentCore Runtime - CustomerSupport]/ | \/ | \[Memory] [Local Tools] [MCP Gateway]/ | \[Cedar Policies] [Warranty λ] [Refund λ]|[Online Evaluation][OrderResearchAgent Harness]/ | \[Code Interp] [Gateway] [HITL: approve_exception][ContainerAgent Harness] [PersistentReportAgent Harness]
From a single
agentcore create command to a multi-agent system with memory, security, governance, monitoring, code execution, human oversight, and a production frontend. Each capability was added incrementally never requiring a rewrite of what came before.
What I Learned: The Meta-Lessons
1. Infrastructure as a Solved Problem
The gap between "agent works locally" and "agent works in production" used to be months of engineering. AgentCore compresses it to minutes. This fundamentally changes who can build production AI systems.
2. Security Belongs at the Platform Level
Trying to make an LLM enforce security rules through its system prompt is like locking your door by asking the burglar nicely not to enter. Cedar policies enforce rules at the infrastructure level therefore the agent literally cannot bypass them.
3. Agents Are Teams, Not Individuals
The harness pattern taught me to think in terms of agent specialization. Instead of one mega-agent that does everything, you compose specialists: a customer-facing agent, a research agent, a report writer. Each is simple, testable, and replaceable.
4. Human-in-the-Loop Is Not a Failure Mode
Pausing for human approval isn't admitting your agent isn't smart enough. It's recognizing that some decisions carry stakes that justify human judgment. The best systems blend AI speed with human oversight.
5. Observability Is Not Optional
You cannot improve what you cannot measure. Online evaluation isn't a nice-to-have and it's how you catch quality degradation before your customers do.
Closing Thoughts
When people ask me "what does it take to go from an AI agent POC to production?" my answer used to be: "about 3-6 months and a platform team." After this workshop, my answer is: "about a day, and you probably don't need that platform team."
That's not because the problems disappeared. Memory, security, authorization, monitoring, tool integration; those challenges are all still real. They're just solved. Pre-packaged. Ready to use.
The question is no longer "can we deploy this?" It's "what should our agent actually do?" And that's a much better question to be asking.
This was Part 3 of my series on AWS Bedrock AgentCore, written as part of the BeSA (Become a Solutions Architect) Agentic AI program. If you're interested in hands-on agentic AI development on AWS, I highly recommend the AgentCore Getting Started Workshop.
About the Author
Pauline Namwakira - Building with AWS.
- GitHub: github.com/kira-PJ
- LinkedIn: linkedin.com/in/paulinenamwakira
- Source code for this project: github.com/kira-PJ/bedrock-agentcore-workshop
Series:
- Part 1: From Zero to Deployed - The 15-Minute Agent
- Part 2: Making It Production-Ready - Memory, Gateways, and Governance
- Part 3: Advanced Patterns (you are here)
Series: From POC to Production with AWS Bedrock AgentCore (3 articles)
- 3Advanced AgentCore Patterns: Harnesses, Human-in-the-Loop, and Container Agents This article
Enjoyed reading this content? Let the author know!
Your likes, comments, shares, and saves help creators reach more builders.
Loading recommendations
Loading article