Implement reversible PII de-identification round trip (T1–T7)

Build the AWS side of the HNCB demo end to end (region ap-southeast-1):

- T1 /tokenize + T2 /restore: Lambdas behind a public API Gateway (shared-secret
  auth), Presidio detection, random per-request tokens, DynamoDB vault; overlap
  resolution so a ROC ID stays TW_ROC_ID.
- T3: Presidio made private (SG-locked to the tokenize Lambda in-VPC; DynamoDB
  gateway endpoint); only /tokenize + /restore are public.
- T4: RAG Lambda registered as an MCP tool on an AgentCore Gateway (AWS_IAM/SigV4);
  agentcore_setup.sh + a SigV4 MCP invoke test.
- T5: Strands agent deployed to AgentCore Runtime; SigV4 gateway auth, apac
  inference profile, pinned deps.
- T6: advisor UI on S3+CloudFront with a Fusion-less demo orchestrator (/demo)
  chaining tokenize -> runtime -> restore.
- T7: README runbook + trace check; teardown deletes gateway/runtime/memory/ECR.

Verified live: the cloud AgentCore/Bedrock trace shows only tokens, never the
real name. Secrets stay in gitignored local.auto.tfvars.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-01 17:10:58 +10:00
parent 6b2a051be3
commit 78d67a2469
21 changed files with 1439 additions and 107 deletions

View File

@@ -6,10 +6,19 @@ CUST_000123, never a name), reasons with a Bedrock model, calls the RAG tool
through AgentCore Gateway (MCP), and returns de-identified talking points.
Fusion restores the real identity on the way back out -- not this agent.
Framework: Strands. Deploy target: AgentCore Runtime (see scripts/agentcore_setup.py).
Framework: Strands. Deploy target: AgentCore Runtime (see scripts/agentcore_setup.sh).
Pin versions in requirements.txt; SDK surfaces move quickly.
Auth to the Gateway: our Gateway uses AWS_IAM, so every MCP request is SigV4-signed
with the Runtime's execution-role credentials (service `bedrock-agentcore`). If a
GATEWAY_TOKEN is provided instead, we fall back to bearer auth (CUSTOM_JWT gateways).
"""
import os
import httpx
from botocore.auth import SigV4Auth
from botocore.awsrequest import AWSRequest
from botocore.session import Session
from bedrock_agentcore.runtime import BedrockAgentCoreApp
from strands import Agent
from strands.models import BedrockModel
@@ -18,9 +27,12 @@ from mcp.client.streamable_http import streamablehttp_client
app = BedrockAgentCoreApp()
GATEWAY_URL = os.environ["AGENTCORE_GATEWAY_URL"] # set by agentcore_setup.py
GATEWAY_URL = os.environ["AGENTCORE_GATEWAY_URL"] # set by agentcore_setup.sh
GATEWAY_TOKEN = os.environ.get("AGENTCORE_GATEWAY_TOKEN", "")
MODEL_ID = os.environ.get("BEDROCK_MODEL_ID", "anthropic.claude-3-5-sonnet-20241022-v2:0")
REGION = os.environ.get("AWS_REGION", "ap-southeast-1")
# In non-US regions Claude 3.5 Sonnet v2 is INFERENCE_PROFILE-only, so default to
# the APAC cross-region profile. Override with BEDROCK_MODEL_ID at launch.
MODEL_ID = os.environ.get("BEDROCK_MODEL_ID", "apac.anthropic.claude-3-5-sonnet-20241022-v2:0")
SYSTEM_PROMPT = (
"You are a financial-advisor assistant. You will be given a customer reference "
@@ -32,9 +44,34 @@ SYSTEM_PROMPT = (
)
class _SigV4Auth(httpx.Auth):
"""SigV4-sign each MCP request with the Runtime's execution-role credentials."""
requires_request_body = True
def __init__(self, service, region):
self._creds = Session().get_credentials()
self._service = service
self._region = region
def auth_flow(self, request):
aws_req = AWSRequest(
method=request.method,
url=str(request.url),
data=request.content,
headers=dict(request.headers),
)
SigV4Auth(self._creds, self._service, self._region).add_auth(aws_req)
request.headers.update(dict(aws_req.headers))
yield request
def _mcp_client():
headers = {"Authorization": f"Bearer {GATEWAY_TOKEN}"} if GATEWAY_TOKEN else {}
return MCPClient(lambda: streamablehttp_client(GATEWAY_URL, headers=headers))
if GATEWAY_TOKEN:
headers = {"Authorization": f"Bearer {GATEWAY_TOKEN}"}
return MCPClient(lambda: streamablehttp_client(GATEWAY_URL, headers=headers))
auth = _SigV4Auth("bedrock-agentcore", REGION)
return MCPClient(lambda: streamablehttp_client(GATEWAY_URL, auth=auth))
@app.entrypoint

View File

@@ -1,4 +1,6 @@
bedrock-agentcore
strands-agents
mcp
boto3
# Pinned before `agentcore launch` (versions resolved 2026-07-01). These SDKs move
# fast; re-resolve and re-pin if you rebuild.
bedrock-agentcore==1.16.0
strands-agents==1.45.0
mcp==1.28.1
boto3==1.43.38