diff --git a/.cspell/custom-words.txt b/.cspell/custom-words.txt index ce73c361..9c14d554 100644 --- a/.cspell/custom-words.txt +++ b/.cspell/custom-words.txt @@ -185,3 +185,21 @@ XVCJ Yapily Zalopay Zalora + +CNPJ +CURP +LOPJ +NIR +Personalausweis +RRN +SIRET +Sanitizer +TRUSTBOOST +TrustBoost +sanitization +sanitize +sanitized +sanitizer +trustboost +HDFRZN +mainnet \ No newline at end of file diff --git a/code/samples/python/scenarios/a2a/human-not-present/pii-sanitization/README.md b/code/samples/python/scenarios/a2a/human-not-present/pii-sanitization/README.md new file mode 100644 index 00000000..913842e7 --- /dev/null +++ b/code/samples/python/scenarios/a2a/human-not-present/pii-sanitization/README.md @@ -0,0 +1,31 @@ +# AP2 Sample: PII Sanitization Before Autonomous Payment + +This sample demonstrates how an autonomous AI agent sanitizes PII from +text using **TrustBoost** before completing an **AP2 + x402** payment. + +## Scenario + +A shopping agent receives user-generated text containing PII. Before +sending to an LLM or completing an x402 payment, the agent calls +TrustBoost to redact PII and receive immutable proof on Solana. + +## Key Features + +- Autonomous PII sanitization via TrustBoost x402 protocol +- Proof of Sanitization anchored on Solana mainnet +- 8 languages: EN, ES-LATAM, PT-BR, DE, JA, FR, IT, KO +- EU AI Act compliant (Articles 12, 13, 26) + +## Quick Start + +```bash +pip install -r requirements.txt +python agent.py +``` + +## Resources + +- [TrustBoost](https://github.com/teodorofodocrispin-cmyk/TrustBoost-PII-Sanitizer) +- [Agent Card](https://api.trustboost.dev/.well-known/agent-card.json) +- [Health](https://api.trustboost.dev/health) +- [AP2 docs](https://ap2-protocol.org) diff --git a/code/samples/python/scenarios/a2a/human-not-present/pii-sanitization/agent.py b/code/samples/python/scenarios/a2a/human-not-present/pii-sanitization/agent.py new file mode 100644 index 00000000..f92eb312 --- /dev/null +++ b/code/samples/python/scenarios/a2a/human-not-present/pii-sanitization/agent.py @@ -0,0 +1,79 @@ +import os +import requests +from dotenv import load_dotenv + +load_dotenv() + +TRUSTBOOST_URL = "https://api.trustboost.dev" +TX_HASH = os.getenv("TRUSTBOOST_TX_HASH", "TRIAL") +WALLET = os.getenv("TRUSTBOOST_WALLET", "ap2-sample-agent") + + +def discover_trustboost(): + r = requests.get(f"{TRUSTBOOST_URL}/.well-known/agent-card.json", timeout=10) + r.raise_for_status() + card = r.json() + print(f"[TrustBoost] {card.get('name', 'Unknown')} v{card.get('version', '?')}") + print(f"[TrustBoost] Languages: {card.get('languages', [])}") + print(f"[TrustBoost] Compliance: {card.get('compliance', [])}") + return card + + +def sanitize_pii(text, context="general"): + print(f"\n[Sanitizing] {len(text)} chars, context={context}") + + # x402 flow: call without payment -> HTTP 402 -> pay -> retry + payload = {"text": text, "context": context} + r = requests.post(f"{TRUSTBOOST_URL}/sanitize", json=payload, timeout=10) + if r.status_code == 402: + x402 = r.json().get("x402", {}) + accepts_list = x402.get("accepts", []) + if accepts_list: + acc = accepts_list[0] + print(f"[x402] HTTP 402 - {acc.get('amount')} {acc.get('currency')} on {acc.get('network')}") + print(f"[x402] Paying autonomously with tx_hash={TX_HASH}") + payload.update({"tx_hash": TX_HASH, "wallet_address": WALLET}) + r = requests.post(f"{TRUSTBOOST_URL}/sanitize", json=payload, timeout=30) + r.raise_for_status() + data = r.json().get("data", {}) + + print(f"[Result] {data.get('sanitized_content', '')[:80]}...") + print(f"[Score] {data.get('safety_score')} | Risk: {data.get('risk_category')}") + + proof = data.get("proof_of_sanitization") + if proof: + print(f"[Proof] {proof.get('verify_url')}") + + return data + + +def main(): + print("=" * 60) + print("AP2 Sample: PII Sanitization Before Autonomous Payment") + print("=" * 60) + + discover_trustboost() + + tests = [ + {"lang": "English (Financial)", "text": "Wire to john@acme.com, SSN 123-45-6789", "ctx": "financial"}, + {"lang": "Spanish LATAM (Legal)", "text": "RFC: LOPJ850101ABC, CURP: LOPJ850101HDFRZN09", "ctx": "legal"}, + {"lang": "Portuguese BR", "text": "CPF: 123.456.789-09, email: paciente@hospital.com.br", "ctx": "medical"}, + {"lang": "Japanese", "text": "田中太郎、マイナンバー:123456789012", "ctx": "general"}, + ] + + mode = "TRIAL (50 free)" if TX_HASH == "TRIAL" else "PAID (x402 Solana)" + print(f"\n[Mode] {mode}\n" + "=" * 60) + + for t in tests: + print(f"\n[{t['lang']}] {t['text']}") + try: + sanitize_pii(t["text"], t["ctx"]) + except requests.exceptions.RequestException as e: + print(f"[Error] {e}") + + print("\nPII sanitized. Safe to proceed with AP2 payment.") + print(f"Verify: GET {TRUSTBOOST_URL}/verify/{{anchor_tx}}") + + +if __name__ == "__main__": + main() diff --git a/code/samples/python/scenarios/a2a/human-not-present/pii-sanitization/requirements.txt b/code/samples/python/scenarios/a2a/human-not-present/pii-sanitization/requirements.txt new file mode 100644 index 00000000..2b1be2aa --- /dev/null +++ b/code/samples/python/scenarios/a2a/human-not-present/pii-sanitization/requirements.txt @@ -0,0 +1,2 @@ +requests>=2.31.0 +python-dotenv>=1.0.0