"""InvokeHarness shape from the AgentCore docs. Syntax-checkable. Versions / setup (docs checked 11 October 2026): - Python 3.10+ for boto3 sketches; export-to-code self-host docs say Python 3.12+ - boto3 with bedrock-agentcore and bedrock-agentcore-control - IAM execution role the harness can assume - Node.js 20+ for the CLI: npm install -g @aws/agentcore Does not call AWS unless DRY_RUN=0 and the ARNs are real. Default model when CreateHarness omits one: Anthropic Claude Sonnet 4.6 on Bedrock. runtimeSessionId must be at least 33 characters. This is not a Strands create_harness() call. """ from __future__ import annotations import os import uuid DRY_RUN = os.environ.get("DRY_RUN", "1") == "1" REGION = os.environ.get("AWS_REGION", "us-west-2") EXECUTION_ROLE_ARN = os.environ.get( "HARNESS_EXECUTION_ROLE_ARN", "arn:aws:iam::123456789012:role/HarnessExecutionRole", ) HARNESS_NAME = os.environ.get("HARNESS_NAME", "coding-task-demo") def create_harness() -> str: if DRY_RUN: return f"arn:aws:bedrock-agentcore:{REGION}:123456789012:harness/{HARNESS_NAME}-demo" import boto3 control = boto3.client("bedrock-agentcore-control", region_name=REGION) created = control.create_harness( harnessName=HARNESS_NAME, executionRoleArn=EXECUTION_ROLE_ARN, ) # Poll get_harness until status is READY before invoke. return created.get("arn") or created["harnessArn"] def invoke_harness(harness_arn: str, user_text: str) -> None: session_id = str(uuid.uuid4()) if len(session_id) < 33: raise ValueError("runtimeSessionId must be at least 33 characters") request = { "harnessArn": harness_arn, "runtimeSessionId": session_id, "messages": [{"role": "user", "content": [{"text": user_text}]}], # Documented per-invoke ceilings. Omit to keep service defaults: # maxIterations 75, timeoutSeconds 3600, maxTokens unset. "maxIterations": 8, "timeoutSeconds": 900, } if DRY_RUN: print({"api": "invoke_harness", **request}) return import boto3 client = boto3.client("bedrock-agentcore", region_name=REGION) response = client.invoke_harness(**request) for event in response["stream"]: if "contentBlockDelta" in event: delta = event["contentBlockDelta"].get("delta", {}) if "text" in delta: print(delta["text"], end="", flush=True) elif "runtimeClientError" in event: print(f"\nError: {event['runtimeClientError']['message']}") if __name__ == "__main__": invoke_harness(create_harness(), "Summarize git status. Do not edit files.")