Repoint public POST /tokenize at the orchestrator (tokenize -> agent -> restore)
so a single path returns {final, deidentified_prompt, agent_tokenized,
session_id} — matching what Fusion mirrors from the front-end path, and what
openapi.yaml already documents. The granular detector moves to internal
/tokenize-raw (x-api-key protected; the orchestrator calls it). /demo kept as an
alias so the UI keeps working.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
hncb-fusion-deid-demo
Demo of the HNCB use case: a reversible PII de-identification round trip through Axway Amplify AI Gateway (Fusion), with the reasoning done by an Amazon Bedrock AgentCore agent. The advisor types a query containing a real name; the cloud only ever sees a token; the real identity is restored before the answer is shown.
Working with Claude Code? Read
CLAUDE.mdfirst — it has the context, commands, and task backlog.
Status: unrun scaffold. Authored, not executed. Review everything, pin dependency versions, and adjust AgentCore specifics to the current CLI. Demo-grade, not production-grade.
Fusion is shared SaaS
Fusion is not deployed by this repo — it's a shared Amplify AI Gateway SaaS
instance, configured in its console (fusion/POLICY_SETUP.md). Because it's SaaS,
anything it calls must be a public HTTPS endpoint with auth. So the AWS side's
job is to expose two endpoints Fusion calls — /tokenize (ingress) and
/restore (egress) — plus host the detector, vault, RAG tool, and agent.
Those two endpoints are the main remaining build (tasks T1/T2 in CLAUDE.md).
What it demonstrates
Raw PII (a Chinese name + a Taiwan ROC ID) is detected on ingress, replaced with a
random, format-safe token, and only the tokenized prompt goes to the cloud
agent. The agent tool-calls back "on-prem" with the token, gets a de-identified
evidence package, and writes talking points. Fusion restores the identity on the
way out. The money shot: show the Bedrock request / AgentCore trace live — the
cloud only ever saw CUST_000123, never 王小明.
Trust zones are logical
Everything is one AWS account. The "on-prem" zone is tag-labelled resources
(Zone = on-prem-VPC-A) standing in for HNCB's branch data centre. Proves
data-flow behaviour, not physical residency — say so on camera.
Component → service map (their 8 steps)
| Step | Component | Service in this repo |
|---|---|---|
| 1, 8 | Advisor UI | ui/index.html on S3+CloudFront (or local) |
| 2, 3-route, 8 | Fusion AI Gateway (the product) | shared SaaS — configured via fusion/POLICY_SETUP.md (not deployed) |
| 2 (ingress), 8 (egress) | /tokenize + /restore endpoints Fusion calls |
TODO gateway_api/ (tasks T1/T2) |
| 2 | PII detector (typed findings, not redaction) | Presidio on Fargate — presidio/ |
| 2, 4, 8 | Token vault (reversible map) | DynamoDB — terraform/main.tf |
| 3, 7 | Cloud agent + model | AgentCore Runtime + Bedrock — agent/ |
| 4 | Tool bridge (Lambda → MCP tool) | AgentCore Gateway — scripts/agentcore_setup.sh |
| 4-6 | On-prem RAG tool + data | Lambda + DynamoDB — lambda_rag/, seed/ |
| all | Observability | AgentCore Observability + CloudWatch |
Repo layout
CLAUDE.md start here if using Claude Code (context + task backlog)
terraform/ DynamoDB (vault + customers), RAG Lambda, IAM, Presidio hosting
lambda_rag/ RAG tool: token resolve -> de-identified evidence package
gateway_api/ TODO: /tokenize + /restore endpoints Fusion SaaS calls (T1/T2)
agent/ Strands agent for AgentCore Runtime + tool schema
presidio/ PII detector service (typed findings) + Dockerfile
seed/ fake customer (Wang Xiaoming) + seed script
ui/ advisor UI (restored-vs-tokenized split view)
scripts/ deploy.sh, agentcore_setup.sh, teardown.sh
fusion/ POLICY_SETUP.md (SaaS console config — the manual part)
Prerequisites
aws-cli (creds + region — this demo runs in ap-southeast-1), terraform >= 1.5,
podman or docker (Presidio image), python3 + a venv with boto3,
bedrock-agentcore-starter-toolkit (pip install, provides agentcore), Bedrock
access for the apac Claude 3.5 Sonnet v2 inference profile
(apac.anthropic.claude-3-5-sonnet-20241022-v2:0 — the raw id is not on-demand in
this region), and — for the production path — the shared Fusion SaaS instance.
Deploy
The live stack was brought up in this order (authoritative runbook: the task notes
in CLAUDE.md, which record the exact sequencing and gotchas):
terraform -chdir=terraform applycore infra (DynamoDB, RAG + tokenize/restore/ orchestrator Lambdas, API Gateway, Presidio on Fargate, UI on S3+CloudFront). Presidio needs its image in ECR andpresidio_urlset to the task's private IP.- Seed the synthetic customer + the demo vault token (
seed/seed.py). scripts/agentcore_setup.sh→ MCP Gateway + RAG tool target.agentcore configure+agentcore launch→ Runtime ARN; then grant the runtime execution rolebedrock-agentcore:InvokeGateway(command inagentcore_setup.sh).- Put the Runtime ARN in
terraform/local.auto.tfvars(agent_runtime_arn) and re-apply so/democan invoke it.
Demo script (Fusion-less dry run — maps to the 8 steps)
cd terraform && DEMO=$(terraform output -raw demo_url_custom) && UI=$(terraform output -raw ui_url); cd ..
# (demo_url_custom uses the Route53 custom domain Fusion can resolve; demo_url is the raw execute-api one)
# 1-2, 4-8: advisor query -> tokenize -> agent (on tokens) -> restore, in one call:
curl -s -X POST "$DEMO" -H 'content-type: application/json' \
-d '{"query":"請幫我整理王小明最近三個月的理財往來,並給我下次拜訪話術。"}' | python3 -m json.tool
# -> deidentified_prompt: "...CUST_xxxxxx..." (what left for the cloud)
# agent_tokenized: talking points, tokens only
# final: "(客戶:王小明)..." (identity restored on-prem)
# 3. money shot — the cloud runtime trace only ever shows the token:
LG=/aws/bedrock-agentcore/runtimes/<runtime-id>-DEFAULT
aws logs filter-log-events --log-group-name "$LG" --filter-pattern '"王小明"' --query 'length(events)' # 0
aws logs filter-log-events --log-group-name "$LG" --filter-pattern '"CUST_"' --query 'length(events)' # >0
# 8 (visual): open the split-view UI and submit the same query
echo "$UI"
Teardown
bash scripts/teardown.sh # deletes Gateway/Runtime/Memory + `terraform destroy` + ECR repos
Leftover-but-free after teardown: the hand-made default VPC, the
AmazonBedrockAgentCoreSDKRuntime-* role, and a CodeBuild project (delete by hand
if you want it spotless).
Honest caveats
- zh-TW detection is demo-narrow — tuned to the scripted entities, not production recall. That remains the real-engagement risk.
- Per-request randomization lives in the
/tokenizemint step; confirm it satisfies HNCB's "different each time" requirement. - The agentic token-resolution loop (agent tool call → on-prem RAG resolves the token) is custom orchestration by design — where Fusion's depth is the argument.