A Developer’s Guide to AgentCore’s Managed Agent Harness
Building an agent from scratch means making a lot of decisions that have nothing to do with what the agent actually does: which model provider to call, which orchestration framework to wrap it in, how to stand up a runtime environment, how to wire in memory, and how to deploy the whole thing. Add a tool or upgrade the memory setup later, and it often means redeploying, sometimes redesigning the architecture to fit the new piece in.
The managed agent harness in AgentCore exists to take that off your plate. It’s a managed, secure agent loop, running on AgentCore Runtime, already wired to the AgentCore capabilities most agents end up needing anyway: Browser, Code Interpreter, Gateway, Identity, Observability, and Memory, with support for multiple model providers out of the box.
Creating a harness
The minimum configuration is genuinely minimal, two parameters:
import boto3
client = boto3.client("bedrock-agentcore-control")
harness = client.create_harness(
harness_name="MyFirstAgentWithHarness",
executionRoleArn="<your_harness_execution_role>"
)
Everything else, system prompt, model choice, tools, skills, memory, advanced configuration like VPC and timeouts, can be added later rather than designed up front:
harness = client.create_harness(
harness_name="MyFirstAgentWithHarness",
executionRoleArn="<your_harness_execution_role>",
system_prompt={"text": "You are a helpful assistant"},
model={"bedrockModelConfig": {
"modelId": "us.anthropic.claude-sonnet-4-6"
}},
skills={"path": "<path_to_skill>"},
tools=[{
"type": "agentcore_gateway",
"name": "mygatewaytools",
"config": {"agentCoreGateway": {"arn": "<gateway_arn>"}}
}]
)
From the CLI, agentcore create defaults to a harness configuration when you haven’t specified a framework or language, and agentcore add harness, agentcore invoke --harness, and agentcore delete harness round out the basic lifecycle.
Invoking it
Invocation needs a harness ARN, a session ID, and message content:
import boto3, uuid
client = boto3.client("bedrock-agentcore")
session_id = str(uuid.uuid4()).upper()
response = client.invoke_harness(
harnessArn=harness_arn,
runtimeSessionId=session_id,
messages=[{"role": "user", "content": [{"text": "what can you do?"}]}],
)
You can override system prompt, model, tools, memory, or any other configuration at invocation time rather than at creation, which is useful for testing a configuration change against a live harness without redeploying it.
What you get once it’s running
A few things are worth understanding before you rely on this in production.
Session lifecycle is governed by two independent timers: idleRuntimeSessionTimeout and maxLifetime. A session with a 15-minute idle timeout and an 8-hour max lifetime gets terminated the moment either condition hits, whichever comes first, not just at the 8-hour mark. Plan around both, not just the one that sounds more relevant to your use case.
Not everything needs to go through the agent loop. InvokeAgentRuntimeCommand gives you direct shell access to the harness’s microVM, which is the right tool for deterministic pre- or post-invocation scripts, preparing the environment before a run, acting on whatever the agent produced, or installing a skill without routing it through the model.
You can bring your own container image (ECR, linux/arm64) instead of the default Python environment, but there’s a real gotcha here: the harness overrides your image’s ENTRYPOINT and CMD, so your normal startup command simply won’t run. Use InvokeAgentRuntimeCommand for session-specific setup or to kick off background processes instead of relying on your image’s own boot sequence.
Filesystem options have genuinely different trade-offs, so pick deliberately rather than defaulting. Local session storage is ephemeral and isolated, destroyed when the session ends, which is what you want for anything that shouldn’t persist or leak between sessions. An S3 Files Access Point is shared, persistent, and cheap relative to the alternative. An EFS Access Point (coming soon at time of writing) trades a bit of cost for lower-latency mounting when sharing matters and speed matters more than price.
Memory integrates directly into the harness config, with per-user personalisation handled through actorId at invocation:
harness = client_control.create_harness(
harness_name="HarnessWithMemo",
executionRoleArn="<your_harness_execution_role>",
memory={
"agentCoreMemoryConfiguration": {
"arn": "<memory_arn>",
"messageCount": 10,
"retrievalConfig": {
"user_preference_config": {"strategyId": "<strategy_id>"}
}
}
}
)
response = client_data.invoke_harness(
harnessArn=harness["arn"],
runtimeSessionId=session_id,
messages=[{"role": "user", "content": [{"text": "Hi"}]}],
actorId="user123"
)
Tools attach the same way regardless of source: a remote MCP server by URL, an AgentCore Gateway target (IAM, OAuth, or no auth), or the built-in Browser and Code Interpreter tools, all declared in the same tools array shown above.

Where this actually earns its place
A managed harness isn’t the right call for a simple, single-purpose script, that’s more overhead than the job needs. It earns its place once an agent needs to hold state across a long-running or genuinely conversational session, personalise behaviour to a specific user, serve multiple tenants of the same application safely, manage context and tool selection across a larger toolset, or act as a coding agent with shell and filesystem access. Those are exactly the cases where a hand-rolled setup tends to break down first, usually right when someone other than the original developer starts depending on it.
What this means for ANZ engineering teams
The networkConfiguration options on the runtime environment matter more than they might look at first glance if your organisation has real network segmentation requirements, which is common across ANZ financial services and healthcare. Before you rely on harness sessions for anything touching regulated data, it’s worth confirming with your AWS partner exactly how harness networking integrates with your existing VPC design and IAM setup, rather than assuming the defaults fit.
We help ANZ engineering teams architect and configure a managed harness for their first production agent, memory, tools, and identity included, so the team spends its time on what the agent does rather than the plumbing underneath it. If you’ve got an agent idea that’s stalled on infrastructure, we’re happy to talk it through.



