|
| 1 | +# Secure Passport Python Sample |
| 2 | + |
| 3 | +This sample provides the runnable code for the **Secure Passport Extension v1** for the Agent2Agent (A2A) protocol, demonstrating its implementation and usage in a Python environment. |
| 4 | + |
| 5 | +## 1. Extension Overview |
| 6 | + |
| 7 | +The core of this extension is the **`CallerContext`** data model, which is attached to the A2A message metadata under the extension's unique URI. This enables the secure transfer of trusted contextual state between collaborating agents. |
| 8 | + |
| 9 | +### Extension URI |
| 10 | + |
| 11 | +The unique identifier for this extension is: |
| 12 | +`https://github.com/a2aproject/a2a-samples/tree/main/samples/python/extensions/secure-passport` |
| 13 | + |
| 14 | +--- |
| 15 | + |
| 16 | +## 2. Comprehensive Usage and Middleware Demonstration |
| 17 | + |
| 18 | +The `run.py` script demonstrates the full client-server pipeline using the conceptual **middleware layers** for seamless integration. |
| 19 | + |
| 20 | +### A. Use Case Code Demonstration |
| 21 | + |
| 22 | +The following code demonstrates how to create the specific `CallerContext` payloads for the four core use cases, verifying that the structure and integrity checks work as intended. |
| 23 | + |
| 24 | +```python |
| 25 | +from secure_passport_ext import ( |
| 26 | + CallerContext, |
| 27 | + A2AMessage, |
| 28 | + add_secure_passport, |
| 29 | + get_secure_passport |
| 30 | +) |
| 31 | + |
| 32 | +def demonstrate_use_case(title: str, client_id: str, state: dict, signature: str | None = None, session_id: str | None = None): |
| 33 | + print(f"\n--- Demonstrating: {title} ---") |
| 34 | + |
| 35 | + passport = CallerContext( |
| 36 | + client_id=client_id, |
| 37 | + session_id=session_id, |
| 38 | + signature=signature, |
| 39 | + state=state |
| 40 | + ) |
| 41 | + |
| 42 | + message = A2AMessage() |
| 43 | + add_secure_passport(message, passport) |
| 44 | + retrieved = get_secure_passport(message) |
| 45 | + |
| 46 | + if retrieved: |
| 47 | + print(f" Source: {retrieved.client_id}") |
| 48 | + print(f" Verified: {retrieved.is_verified}") |
| 49 | + print(f" Context: {retrieved.state}") |
| 50 | + else: |
| 51 | + print(" [ERROR] Passport retrieval failed.") |
| 52 | + |
| 53 | +# 1. Efficient Currency Conversion (Low Context, High Trust) |
| 54 | + |
| 55 | +demonstrate_use_case( |
| 56 | + title="1. Currency Conversion (GBP)", |
| 57 | + client_id="a2a://travel-orchestrator.com", |
| 58 | + state={"user_preferred_currency": "GBP", "user_id": "U001"}, |
| 59 | + signature="sig-currency-1" |
| 60 | +) |
| 61 | + |
| 62 | +# 2. Personalized Travel Booking (High Context, Session Data) |
| 63 | + |
| 64 | +demonstrate_use_case( |
| 65 | + title="2. Personalized Travel (Platinum Tier)", |
| 66 | + client_id="a2a://travel-portal.com", |
| 67 | + session_id="travel-session-999", |
| 68 | + state={ |
| 69 | + "destination": "Bali, Indonesia", |
| 70 | + "loyalty_tier": "Platinum" |
| 71 | + }, |
| 72 | + signature="sig-travel-2" |
| 73 | +) |
| 74 | + |
| 75 | +# 3. Proactive Retail Assistance (Unsigned, Quick Context) |
| 76 | + |
| 77 | +demonstrate_use_case( |
| 78 | + title="3. Retail Assistance (Unverified)", |
| 79 | + client_id="a2a://ecommerce-front.com", |
| 80 | + state={"product_sku": "Nikon-Z-50mm-f1.8", "user_intent": "seeking_reviews"}, |
| 81 | + signature=None |
| 82 | +) |
| 83 | + |
| 84 | +# 4. Marketing Agent seek insights (High Trust, Secured Scope) |
| 85 | + |
| 86 | +demonstrate_use_case( |
| 87 | + title="4. Secured DB Access (Finance)", |
| 88 | + client_id="a2a://marketing-agent.com", |
| 89 | + state={ |
| 90 | + "query_type": "quarterly_revenue", |
| 91 | + "access_scope": ["read:finance_db", "user:Gulli"] |
| 92 | + }, |
| 93 | + signature="sig-finance-4" |
| 94 | +) |
| 95 | +``` |
| 96 | + |
| 97 | +### B. Convenience Method: AgentCard Declaration |
| 98 | + |
| 99 | +The `SecurePassportExtension` class provides a static method to easily generate the necessary JSON structure for including this extension in an agent's `AgentCard`. This ensures the structure is always compliant. |
| 100 | + |
| 101 | +```python |
| 102 | +from secure_passport_ext import SecurePassportExtension |
| 103 | + |
| 104 | +# Scenario 1: Agent supports basic Secure Passport |
| 105 | +simple_declaration = SecurePassportExtension.get_agent_card_declaration() |
| 106 | +# Output will be: {'uri': '...', 'params': {'receivesCallerContext': True}} |
| 107 | + |
| 108 | +# Scenario 2: Agent supports specific keys (e.g., the Travel Agent) |
| 109 | +travel_keys = ["destination", "loyalty_tier", "dates"] |
| 110 | +complex_declaration = SecurePassportExtension.get_agent_card_declaration(travel_keys) |
| 111 | +# Output will include: 'supportedStateKeys': ['destination', 'loyalty_tier', 'dates'] |
| 112 | +``` |
| 113 | + |
| 114 | +## 3. How to Run the Sample 🚀 |
| 115 | + |
| 116 | +To run the sample and execute the comprehensive unit tests, follow these steps. |
| 117 | + |
| 118 | +### A. Setup and Installation |
| 119 | + |
| 120 | +1. **Navigate** to the Python sample directory: |
| 121 | + ```bash |
| 122 | + cd extensions/secure-passport/v1/samples/python |
| 123 | + ``` |
| 124 | +2. **Install Dependencies** (using Poetry): |
| 125 | + ```bash |
| 126 | + poetry install |
| 127 | + |
| 128 | + # Activate the virtual environment |
| 129 | + poetry shell |
| 130 | + ``` |
| 131 | + |
| 132 | +### B. Verification and Execution |
| 133 | + |
| 134 | +#### 1. Run Unit Tests (Recommended) |
| 135 | + |
| 136 | +Confirm all 11 core logic and validation tests pass: |
| 137 | + |
| 138 | +```bash |
| 139 | +pytest tests/ |
| 140 | +``` |
| 141 | + |
| 142 | +#### 2. Run Middleware Demo Script |
| 143 | + |
| 144 | +Execute `run.py` to see the full client/server middleware pipeline in action for all four use cases: |
| 145 | + |
| 146 | +```bash |
| 147 | +python run.py |
| 148 | +``` |
0 commit comments