Aws Harness logo

Aws Harness

Community
hoodini
aws-harness

Build a new AI agent on AWS and deploy it easily, OR wrap and deploy an agent you already have, using the Amazon Bedrock AgentCore harness. Explains what an "agent harness" is (the runtime scaffolding around a model - agent loop, tool execution, memory, identity, observability), then gives two fully-working, verified paths - (A) scaffold + ship a new agent with the AgentCore CLI (create/dev/deploy/invoke), and (B) deploy a prepared agent (Strands, LangGraph, or custom) via the SDK wrapper or a FastAPI + Docker + ECR container. Every import and command is verified against official AWS/Strands docs. Use when the goal is to create, wrap, or deploy an agent on AWS AgentCore. Triggers on agent harness, AWS harness, AgentCore, AgentCore CLI, agentcore create, agentcore deploy, deploy agent on AWS, bring your own agent, Bedrock AgentCore runtime, serverless agent.

Overview

Publisherhoodini
Repositoryai-agents-skills
Skill nameaws-harness
Stars
280
Forks
62
Bundled files
Instructions only
Links
  • Markdown instructions

    A SKILL.md file the model loads on demand, so it only costs tokens when a request actually matches.

  • Works with any LLM

    AI skills are plain Markdown, not provider-specific code, so this works with GPT, Claude, Gemini, Grok, or a local model.

  • Self-contained

    Everything the model needs lives in the instructions — no extra files to sync.

  • Open source

    Published by hoodini on GitHub. Read the source before you install it.

Installation

Install the Aws Harness AI skill in TypingMind to use it with any LLM, or drop it into another agent that reads SKILL.md.

1

Install in TypingMind

TypingMind installs a skill straight from its GitHub folder — it reads SKILL.md, bundles the resource files, and stores the result locally.

  1. Open the app and go to Plugins → Skills.
  2. Choose "Install from GitHub".
  3. Paste the skill folder URL below and confirm.
  4. Enable the skill in any chat where you want it available.
Plugins → Skills → Add skill → From GitHub URL, then paste the folder URL and press Continue.
2

Install in another agent

Any agent that reads the Agent Skills format can use this skill — copy the folder into that agent's skills directory.

Claude Code — .claude/skills
git clone --depth 1 https://github.com/hoodini/ai-agents-skills.git /tmp/ai-agents-skills
mkdir -p .claude/skills
cp -r /tmp/ai-agents-skills/skills/aws-harness .claude/skills/aws-harness
Restart Claude Code after copying so it picks up the new skill.

Use it in TypingMind

Enable Aws Harness in any TypingMind chat and the model takes it from there. Its name and description sit in the system prompt, and the moment a request matches, the model loads the full instructions itself — you never invoke it by hand, and it costs no tokens until it is actually used.

The model loads Aws Harness on its own as soon as a request matches it.

Works with any AI model

AI skills are plain Markdown instructions rather than provider-specific code, so Aws Harness is not tied to the model it was written for. Install it once in TypingMind and use it with GPT-5, Claude, Gemini, Grok, DeepSeek, Mistral, Llama, or a local model you run yourself — all on your own API keys.

  • Loaded only when it is needed

    The system prompt carries just the name and description. The instructions are fetched on the first matching request, so an idle skill costs nothing.

  • Switch models mid-chat

    Because the skill is instructions rather than code, changing model does not break it — the next model reads the same SKILL.md.

Skill instructions

This is the SKILL.md content the model loads. Read it before installing — a skill is instructions your model will follow.

AWS Agent Harness (Bedrock AgentCore)

Take an AI agent from an empty folder - or from code you already have - to a live, serverless endpoint on AWS. Every command and import below is verified against official docs (sources at the bottom).

Companion skill: aws-strands is the agent framework (the "brain" - how to write the agent). This skill is the harness: how to run and deploy that agent on AWS. Write with Strands, ship with AgentCore.

What "harness" means (read this first)

A language model, alone, only turns text into text. It cannot call an API, remember yesterday, run code, or browse the web. The harness is the scaffolding around the model that makes it act:

  • Agent loop - call the model, read the tool it wants, run that tool, feed the result back, repeat until done. The model decides; the harness executes and loops.
  • Tool execution, memory, identity, guardrails, sandboxing, observability - everything that makes it useful and production-safe.

Amazon Bedrock AgentCore is AWS's managed set of these harness pieces. You bring the agent (built with Strands, LangGraph, or anything); AgentCore hosts, secures, and scales it. The components, composable and framework-agnostic:

ComponentWhat it gives you
RuntimeServerless, isolated agent execution (any framework, any model)
MemoryShort-term (session) + long-term (cross-session) memory
IdentityLet the agent act on behalf of a user (Cognito, Okta, Google, EntraID, OAuth)
GatewayTurn APIs / Lambda functions into agent tools (MCP)
Code InterpreterSandboxed code execution
BrowserManaged headless browser for web tasks
ObservabilityTracing, logs, metrics (CloudWatch / OpenTelemetry)

You adopt these one at a time via agentcore add (Path A) or the SDK/API (Path B) - not all-or-nothing.

Which path are you on?

You want to...Go to
Path ABuild a NEW agent from scratch, easiest possiblePath A - the AgentCore CLI
Path BDeploy an agent you ALREADY have (Strands / LangGraph / anything)Path B - wrap + ship

Prerequisites

Both paths need:

RequirementWhy
AWS account + aws configure credentialsEverything below provisions real, billable infrastructure in your account.
Bedrock model accessEnable a Claude model (for example Claude Sonnet 4) in the Bedrock console, in your target region, before the agent can call it.
Python 3.10+The agent code is Python.

Path A also needs: Node.js 20+ (the CLI is an npm package) and AWS CDK (npm i -g aws-cdk, then cdk bootstrap once per account/region - the CLI deploys via CDK).

Path B (container option) also needs: Docker with buildx (for ARM64 images).


Path A - Build and deploy a new agent (CLI)

The AgentCore CLI scaffolds a working agent, runs it locally, and deploys it.

Two CLIs exist. Use the new one: @aws/agentcore (npm), commands create/dev/deploy/invoke. The older bedrock-agentcore-starter-toolkit (pip) uses configure/launch and is marked legacy - it is handy for Path B (wrapping an existing file), shown later.

1. Install

bash
npm install -g @aws/agentcore
agentcore --help

2. Create the project

bash
# interactive wizard:
agentcore create

# or non-interactive:
agentcore create --name MyAgent --framework Strands --model-provider Bedrock --memory none

# or accept all defaults (Python, Strands, Bedrock, no memory):
agentcore create --name MyAgent --defaults

Each flag shapes the agent:

FlagVerified optionsMeaning
--frameworkStrands, LangChain_LangGraph, GoogleADK, OpenAIAgentsThe brain. Strands is AWS-native and simplest.
--model-providerBedrock, Anthropic, OpenAI, GeminiBedrock = Claude inside AWS (no external key). Others call out with an API key.
--memorynone, shortTerm, longAndShortTermnone = amnesiac; shortTerm = within a session; longAndShortTerm = across sessions.
--protocolHTTP, MCP, A2AHTTP for normal request/response; MCP to expose the agent as tools; A2A for agent-to-agent.
--buildCodeZip, ContainerCodeZip = zip to S3, no Docker. Container = Docker image, for custom system deps.

It generates:

MyAgent/
  agentcore/
    agentcore.json      # project + agent config
    aws-targets.json    # AWS account / region
    .env.local          # local secrets (gitignored)
  app/
    MyAgent/
      main.py           # your starter agent, in the chosen framework
      pyproject.toml
  README.md

3. The agent code (this is all an AgentCore agent is)

The scaffolded main.py follows this verified minimal shape - a framework agent wrapped by the harness:

python
from bedrock_agentcore import BedrockAgentCoreApp   # the harness wrapper
from strands import Agent                           # the framework (brain)

app = BedrockAgentCoreApp()
agent = Agent()

@app.entrypoint                       # every request lands here
def invoke(payload):
    user_message = payload.get("prompt", "Hello! How can I help you today?")
    result = agent(user_message)      # this one call IS the entire agent loop
    return {"result": result.message}

if __name__ == "__main__":
    app.run()                         # `agentcore dev` runs exactly this

To give the agent a real capability, add a tool. The @tool decorator turns a function into something the model can call, and the docstring is read by the model to decide when to call it and what to pass (Strands parses the first paragraph as the description and the Args: section as parameter docs):

python
from bedrock_agentcore import BedrockAgentCoreApp
from strands import Agent, tool

app = BedrockAgentCoreApp()

@tool
def word_count(text: str) -> str:
    """Count the number of words in a piece of text.

    Args:
        text: The text to count words in.
    """
    return f"The text has {len(text.split())} words."

agent = Agent(tools=[word_count])     # add/remove tools here = change abilities

@app.entrypoint
def invoke(payload):
    user_message = payload.get("prompt", "Hello!")
    result = agent(user_message)
    return {"result": result.message}

if __name__ == "__main__":
    app.run()

Design note: a tool's return value is read by the model. Return recoverable strings on failure ("Error: no city 'X'. Ask the user to rephrase.") rather than raising an unhandled exception, which crashes the turn. Prebuilt tools are available too: pip install strands-agents-tools, then from strands_tools import calculator and pass it in Agent(tools=[calculator]).

4. Test locally (free) before deploying

bash
cd MyAgent
agentcore dev                         # hot-reload server on localhost:8080 + browser inspector
agentcore dev "count the words here"  # invoke the local agent

5. Deploy to AWS

bash
agentcore deploy --plan   # dry run: preview the infra
agentcore deploy          # provision for real

Under the hood this reads agentcore.json, packages app/ (CodeZip or Docker) built for ARM64/Graviton (required by the runtime; the CLI handles the arch), uses CDK to synthesize CloudFormation provisioning the Runtime + an IAM execution role + S3 staging, and returns an Agent ARN.

6. Invoke

bash
agentcore invoke "Tell me a joke" --stream
agentcore invoke --session-id my-session "and another"   # continuity across calls

From application code (verified verbatim pattern):

python
import json, uuid, boto3

client = boto3.client("bedrock-agentcore")
response = client.invoke_agent_runtime(
    agentRuntimeArn="<AGENT_ARN>",         # from `agentcore status`
    runtimeSessionId=str(uuid.uuid4()),    # must be 33+ chars; uuid4 is 36
    payload=json.dumps({"prompt": "Tell me a joke"}).encode(),
    qualifier="DEFAULT",
)
content = []
for chunk in response.get("response", []):
    content.append(chunk.decode("utf-8"))
print(json.loads("".join(content)))

7. Add production harness components

Snap pieces in with agentcore add, then re-deploy (run agentcore add --help for the full list):

bash
agentcore add memory --name MyMemory --strategies SEMANTIC       # long-term recall
agentcore add agent  --name SecondAgent --framework Strands       # multi-agent
# also available: identity, target (gateway), evaluator
agentcore deploy                                                  # provision the additions

Observability is built in:

bash
agentcore logs           # stream runtime logs
agentcore traces list    # inspect steps, tokens, latency

8. Clean up (do NOT skip - this costs money)

bash
agentcore remove all   # mark resources for deletion
agentcore deploy       # apply teardown via CloudFormation

Path B - Deploy an agent you already have

You already wrote an agent (Strands, LangGraph, OpenAI Agents, or plain Python). Two ways to ship it.

Option B1 - Wrap it with the SDK (fewest lines)

AgentCore Runtime just needs your agent behind an entrypoint. Wrap your existing agent object:

python
# main.py - the only new file you write
from bedrock_agentcore import BedrockAgentCoreApp
from my_agent import agent          # <-- your already-built agent (any framework)

app = BedrockAgentCoreApp()

@app.entrypoint
def invoke(payload):
    result = agent(payload.get("prompt", ""))
    return {"result": result.message if hasattr(result, "message") else str(result)}

if __name__ == "__main__":
    app.run()
bash
pip install bedrock-agentcore

Then deploy it. Easiest: agentcore create a project (Path A) and paste your logic into the generated entrypoint - you reuse all of Path A's deploy/invoke tooling. Alternatively, the legacy starter toolkit points straight at an existing file:

bash
pip install bedrock-agentcore-starter-toolkit
agentcore configure --entrypoint main.py    # generates IAM role, ECR repo, Dockerfile
agentcore launch                             # build + deploy
agentcore invoke '{"prompt": "hello"}'       # note: JSON string argument

Option B2 - Full container control (no SDK, no CLI)

For maximum control, meet the runtime contract yourself: an HTTP server exposing /invocations (POST) and /ping (GET) on port 8080, packaged as an ARM64 Docker image. This is the verified official path.

1. Project setup (uv):

bash
mkdir my-custom-agent && cd my-custom-agent
uv init --python 3.11
uv add fastapi 'uvicorn[standard]' pydantic httpx strands-agents

2. agent.py (FastAPI meeting the runtime contract):

python
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from typing import Dict, Any
from datetime import datetime
from strands import Agent

app = FastAPI(title="Strands Agent Server", version="1.0.0")
strands_agent = Agent()   # replace with your prepared agent

class InvocationRequest(BaseModel):
    input: Dict[str, Any]

class InvocationResponse(BaseModel):
    output: Dict[str, Any]

@app.post("/invocations", response_model=InvocationResponse)
async def invoke_agent(request: InvocationRequest):
    user_message = request.input.get("prompt", "")
    if not user_message:
        raise HTTPException(status_code=400, detail="No 'prompt' in input.")
    result = strands_agent(user_message)
    return InvocationResponse(output={
        "message": result.message,
        "timestamp": datetime.utcnow().isoformat(),
    })

@app.get("/ping")
async def ping():
    return {"status": "healthy"}

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8080)

3. Dockerfile (ARM64 - required):

dockerfile
FROM --platform=linux/arm64 ghcr.io/astral-sh/uv:python3.11-bookworm-slim
WORKDIR /app
COPY pyproject.toml uv.lock ./
RUN uv sync --frozen --no-cache
COPY agent.py ./
EXPOSE 8080
CMD ["uv", "run", "uvicorn", "agent:app", "--host", "0.0.0.0", "--port", "8080"]

4. Build for ARM64, push to ECR:

bash
docker buildx create --use
aws ecr create-repository --repository-name my-strands-agent --region us-west-2
aws ecr get-login-password --region us-west-2 \
  | docker login --username AWS --password-stdin <account-id>.dkr.ecr.us-west-2.amazonaws.com
docker buildx build --platform linux/arm64 \
  -t <account-id>.dkr.ecr.us-west-2.amazonaws.com/my-strands-agent:latest --push .

5. Create the runtime (boto3, bedrock-agentcore-control):

python
import boto3

client = boto3.client("bedrock-agentcore-control", region_name="us-west-2")
response = client.create_agent_runtime(
    agentRuntimeName="strands_agent",
    agentRuntimeArtifact={"containerConfiguration": {
        "containerUri": "<account-id>.dkr.ecr.us-west-2.amazonaws.com/my-strands-agent:latest"
    }},
    networkConfiguration={"networkMode": "PUBLIC"},
    roleArn="arn:aws:iam::<account-id>:role/AgentRuntimeRole",
)
print(response["agentRuntimeArn"], response["status"])

6. Invoke (note the input wrapper matches the FastAPI contract):

python
import boto3, json

client = boto3.client("bedrock-agentcore", region_name="us-west-2")
response = client.invoke_agent_runtime(
    agentRuntimeArn="<AGENT_RUNTIME_ARN>",
    runtimeSessionId="a" * 40,   # must be 33+ chars
    payload=json.dumps({"input": {"prompt": "Explain machine learning simply"}}),
    qualifier="DEFAULT",
)
print(json.loads(response["response"].read()))

7. Stop the session to avoid runaway cost:

python
import boto3
boto3.client("bedrock-agentcore", region_name="us-west-2").stop_runtime_session(
    agentRuntimeArn="<AGENT_RUNTIME_ARN>",
    runtimeSessionId="a" * 40,
    qualifier="DEFAULT",
)

Runtime contract summary: platform linux/arm64, endpoints /invocations POST + /ping GET, port 8080, image in ECR, and Strands agents need AWS credentials at runtime.


Gotchas (all verified)

  • Wrong CLI: agentcore configure/launch = legacy pip toolkit; the new npm CLI uses create/deploy. Don't mix their command names.
  • CDK not bootstrapped: Path A agentcore deploy fails until you run cdk bootstrap once per account/region.
  • Model access denied: enable the Claude model in the Bedrock console, in the same region as your deploy.
  • Payload shape mismatch: an SDK/BedrockAgentCoreApp entrypoint reads payload.get("prompt") so you send {"prompt": ...}; the custom FastAPI contract reads request.input.get("prompt") so you send {"input": {"prompt": ...}}. Match them.
  • runtimeSessionId too short: it must be 33+ characters (str(uuid.uuid4()) is 36).
  • Not ARM64: containers must be linux/arm64 or the runtime rejects them.
  • result.message is a dict ({"role": ..., "content": [{"text": ...}]}), not a plain string. Use result.message for JSON responses, or str(result) / result.message["content"][0]["text"] for plain text.
  • Cost: deployed runtimes bill until torn down. Path A: agentcore remove all && agentcore deploy. Path B: stop_runtime_session, then delete the runtime and ECR repo.

Resources

Frequently asked questions

What does the Aws Harness AI skill do?

Build a new AI agent on AWS and deploy it easily, OR wrap and deploy an agent you already have, using the Amazon Bedrock AgentCore harness. Explains what an "agent harness" is (the runtime scaffolding around a model - agent loop, tool execution, memory, identity, observability), then gives two fully-working, verified paths - (A) scaffold + ship a new agent with the AgentCore CLI (create/dev/deploy/invoke), and (B) deploy a prepared agent (Strands, LangGraph, or custom) via the SDK wrapper or a FastAPI + Docker + ECR container. Every import and command is verified against official AWS/Strand...

Why use Aws Harness on TypingMind?

Because you install it once and use it with any model. Aws Harness is plain Markdown rather than provider-specific code, so the same skill runs on GPT-5, Claude, Gemini, Grok, or a local model — and you can switch model mid-chat without it breaking. TypingMind runs on your own API keys, so you pay providers directly instead of a per-seat subscription, and your skills and chats stay in your own storage.

How do I install Aws Harness in TypingMind?

Open Plugins → Skills → Install from GitHub in TypingMind and paste https://github.com/hoodini/ai-agents-skills/tree/master/skills/aws-harness. TypingMind reads its SKILL.md and installs it as a skill you can enable per chat.

Which AI models can use Aws Harness?

Any model you connect in TypingMind. AI skills are plain Markdown instructions rather than provider-specific code, so GPT, Claude, Gemini, Grok, and local models can all load this skill when a request matches it.

How many AI models can I use with Aws Harness?

As many as you like. As long as a model supports skills, you can use Aws Harness with it — GPT, Claude, Gemini, Grok, DeepSeek, Mistral, Llama and more — all on TypingMind with your own API keys.

Is the Aws Harness AI skill free?

It is published on GitHub by hoodini. Check the repository for licensing terms. You only pay your own AI provider for the tokens you use.

What are AI skills?

An AI skill is a reusable instruction bundle that teaches an AI model how to do one specific task. It follows the open Agent Skills format: a SKILL.md file with a name and description, plus any scripts, templates or reference files the model may need. The model reads the instructions only when your request matches the skill, so an installed skill costs nothing until it is used.

How are AI skills different from plugins or MCP servers?

A plugin or MCP server gives a model new tools to call — code that runs somewhere and returns a result. An AI skill gives the model knowledge and process instead: how to approach a task, which steps to follow, what good output looks like. Skills are plain Markdown, so they need no server, no API key and no runtime, and they work with any model.

View all

Set up your own AI workspace now

Get notified about new features and future giveaways by subscribing to our newsletter 👇