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>
118 lines
5.7 KiB
Bash
118 lines
5.7 KiB
Bash
#!/usr/bin/env bash
|
|
# AgentCore setup (steps 3-4-7). Terraform's AgentCore coverage lags, so this
|
|
# stage uses the AWS CLI's `bedrock-agentcore-control` API. Verified against the
|
|
# CLI on 2026-07-01; the surface moves fast, so re-check with
|
|
# `aws bedrock-agentcore-control help` if a call rejects.
|
|
#
|
|
# T4 (implemented below): create an MCP Gateway and register the RAG Lambda as a
|
|
# tool. Inbound auth is AWS_IAM (SigV4) -- no Cognito needed. The Gateway assumes
|
|
# the IAM role from Terraform (`terraform output -raw gateway_role_arn`) to invoke
|
|
# the Lambda.
|
|
set -euo pipefail
|
|
cd "$(dirname "$0")"
|
|
|
|
: "${REGION:?set REGION}"
|
|
: "${RAG_LAMBDA_ARN:?set RAG_LAMBDA_ARN (from: terraform -chdir=terraform output -raw rag_lambda_arn)}"
|
|
: "${GATEWAY_ROLE_ARN:?set GATEWAY_ROLE_ARN (from: terraform -chdir=terraform output -raw gateway_role_arn)}"
|
|
: "${BEDROCK_MODEL_ID:=anthropic.claude-3-5-sonnet-20241022-v2:0}"
|
|
GW_NAME="${GW_NAME:-hncb-rag-gateway}"
|
|
TAG='conan hncb demo'
|
|
export AWS_PAGER=""
|
|
|
|
echo "==> 1. Create the MCP Gateway (AWS_IAM inbound auth)"
|
|
GW_JSON="$(aws bedrock-agentcore-control create-gateway \
|
|
--region "$REGION" \
|
|
--name "$GW_NAME" \
|
|
--role-arn "$GATEWAY_ROLE_ARN" \
|
|
--protocol-type MCP \
|
|
--authorizer-type AWS_IAM \
|
|
--tags "Owner=$TAG" 2>/dev/null \
|
|
|| aws bedrock-agentcore-control list-gateways --region "$REGION" \
|
|
--query "items[?name=='$GW_NAME']|[0]" --output json)"
|
|
GW_ID="$(echo "$GW_JSON" | python3 -c 'import sys,json;print(json.load(sys.stdin)["gatewayId"])')"
|
|
echo " gatewayId=$GW_ID"
|
|
|
|
echo "==> 2. Wait for the Gateway to be READY"
|
|
for i in $(seq 1 20); do
|
|
ST="$(aws bedrock-agentcore-control get-gateway --region "$REGION" --gateway-identifier "$GW_ID" --query status --output text)"
|
|
echo " [$i] status=$ST"
|
|
[ "$ST" = "READY" ] && break
|
|
sleep 6
|
|
done
|
|
GW_URL="$(aws bedrock-agentcore-control get-gateway --region "$REGION" --gateway-identifier "$GW_ID" --query gatewayUrl --output text)"
|
|
|
|
echo "==> 3. Register the RAG Lambda as an MCP tool target"
|
|
# Build the target config: mcp.lambda with the tool schema from agent/tool_schema.json
|
|
# (wrapped in the inlinePayload list). The Gateway's inputSchema is a RESTRICTED
|
|
# JSON-Schema subset (only type/properties/required/items/description), so we strip
|
|
# anything else (e.g. the "default" on period_days) recursively.
|
|
python3 - "$RAG_LAMBDA_ARN" > /tmp/hncb_target.json <<'PY'
|
|
import json, sys, os
|
|
ALLOWED = {"type", "properties", "required", "items", "description"}
|
|
def clean(s):
|
|
if not isinstance(s, dict):
|
|
return s
|
|
out = {k: v for k, v in s.items() if k in ALLOWED}
|
|
if "properties" in out:
|
|
out["properties"] = {k: clean(v) for k, v in out["properties"].items()}
|
|
if "items" in out:
|
|
out["items"] = clean(out["items"])
|
|
return out
|
|
lambda_arn = sys.argv[1]
|
|
schema = json.load(open(os.path.join("..", "agent", "tool_schema.json")))
|
|
schema["inputSchema"] = clean(schema["inputSchema"])
|
|
if "outputSchema" in schema:
|
|
schema["outputSchema"] = clean(schema["outputSchema"])
|
|
print(json.dumps({
|
|
"mcp": {"lambda": {"lambdaArn": lambda_arn, "toolSchema": {"inlinePayload": [schema]}}}
|
|
}))
|
|
PY
|
|
if aws bedrock-agentcore-control list-gateway-targets --region "$REGION" \
|
|
--gateway-identifier "$GW_ID" --query 'items[?name==`rag`]' --output text | grep -q rag; then
|
|
echo " target 'rag' already exists -- reusing"
|
|
else
|
|
aws bedrock-agentcore-control create-gateway-target \
|
|
--region "$REGION" \
|
|
--gateway-identifier "$GW_ID" \
|
|
--name "rag" \
|
|
--target-configuration file:///tmp/hncb_target.json \
|
|
--credential-provider-configurations '[{"credentialProviderType":"GATEWAY_IAM_ROLE"}]' \
|
|
--query '{target:targetId,status:status}' --output json
|
|
fi
|
|
|
|
echo ""
|
|
echo "Gateway ready. MCP URL:"
|
|
echo " $GW_URL"
|
|
echo "Export it for the agent + the invoke test:"
|
|
echo " export AGENTCORE_GATEWAY_URL=$GW_URL"
|
|
echo ""
|
|
echo "Verify T4 (manual invoke returns the evidence package):"
|
|
echo " REGION=$REGION AGENTCORE_GATEWAY_URL=$GW_URL python3 scripts/gateway_invoke_test.py CUST_000123"
|
|
|
|
########################################
|
|
# T5: deploy the agent to AgentCore Runtime (uses the starter toolkit CLI).
|
|
# In ap-southeast-1 Claude 3.5 Sonnet v2 is INFERENCE_PROFILE-only -> use the
|
|
# apac.* profile id, not the raw model id.
|
|
########################################
|
|
APAC_MODEL="apac.anthropic.claude-3-5-sonnet-20241022-v2:0"
|
|
echo ""
|
|
echo "==> (T5) Deploy the agent to AgentCore Runtime:"
|
|
cat <<EOF
|
|
cd ../agent # requirements.txt is version-pinned
|
|
pip install bedrock-agentcore-starter-toolkit # provides 'agentcore'
|
|
agentcore configure -e agent.py -n hncb_advisor_agent -r ${REGION} \\
|
|
-rf requirements.txt --non-interactive
|
|
agentcore launch --env AGENTCORE_GATEWAY_URL=${GW_URL} --env BEDROCK_MODEL_ID=${APAC_MODEL}
|
|
# -> note the printed Runtime ARN (Fusion / the UI will invoke this).
|
|
|
|
# REQUIRED post-launch: the auto-created execution role can't call the Gateway
|
|
# yet. Grant it (role name is printed by launch as AmazonBedrockAgentCoreSDKRuntime-*):
|
|
ROLE=\$(aws iam list-roles --query "Roles[?starts_with(RoleName,'AmazonBedrockAgentCoreSDKRuntime-${REGION}')].RoleName | [0]" --output text)
|
|
GW_ARN=\$(aws bedrock-agentcore-control get-gateway --region ${REGION} --gateway-identifier ${GW_ID} --query gatewayArn --output text)
|
|
aws iam put-role-policy --role-name "\$ROLE" --policy-name hncb-gateway-invoke \\
|
|
--policy-document "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Action\":[\"bedrock-agentcore:InvokeGateway\"],\"Resource\":[\"\$GW_ARN\",\"\$GW_ARN/*\"]}]}"
|
|
|
|
# Verify: agentcore invoke '{"prompt":"talking points for CUST_000123"}'
|
|
EOF
|
|
echo "Fill AGENTCORE_GATEWAY_URL + Runtime ARN into fusion/POLICY_SETUP.md."
|