Private Set Intersection Tutorial
Estimated Time to Complete: 20-30 minutes
Expected Outcome
By completing this tutorial, you will:
- Build a complete privacy-preserving private set intersection system with three agents
- Implement AP3 commitments to advertise data structures without revealing values
- Configure agent cards with AP3 extensions for discovery and compatibility checking
- Use Privacy Intent and Result Directives to structure secure computations
Use Case: Quick Commerce Delivery Partner Verification
In the quick commerce industry, companies need to verify if a delivery partner is blacklisted by another company based on their actions before onboarding. However, both parties want to keep their information private:
- Company A (Initiator): Wants to check if a delivery person is blacklisted
- Company B (Receiver): Holds the confidential blacklist
Challenge: Determine if a delivery person appears in the blacklist without revealing the blacklist contents to Company A using Private Set Intersection (PSI) protocol.
System Architecture
The system consists of three agents:
- Company A Agent (
ap3_initiator)- Role: Initiates PSI checks for delivery persons
- Holds: Delivery person queries (name, ID, address)
- Company B Agent (
ap3_receiver)- Role: Processes PSI requests against blacklist
- Holds: Confidential blacklist (never revealed)
- Host Agent (Routing Agent)
- Role: Coordinates agent discovery and protocol initiation
- Provides: AP3 compatibility checking and user interface
Prerequisites
Before starting, ensure you have:
- Python 3.10+ installed
- Google AI Studio API Key - Create one here
- Git installed (to clone the repository)
- Basic terminal/command line knowledge
Tutorial Steps
Step 1: Clone and Set Up the Project
# Clone the repository
git clone https://github.com/silence-laboratories/ap3.git
cd ap3/examples/psi
# Set your Google API key
export GOOGLE_API_KEY=<your-api-key>
# Install dependencies
uv sync && source .venv/bin/activate
Environment Setup
Make sure to activate the virtual environment in each new terminal window when running multiple agents.
Note
In this example, you'll find multiple agents with different roles and commitments. You can explore how we check the compatibility between the agents and how we use the privacy directives to structure the secure computations.
Step 2: Define AP3 Commitments
Both agents need to advertise their data structure using AP3 commitments. Let's implement this:
2.1 Company A Agent Commitment
In company_a_agent/__main__.py, you'll create a commitment like this:
from ap3.types.core import (
CommitmentMetadata,
DataStructure,
DataFormat,
DataFreshness,
Industry,
)
from datetime import datetime
# Company A Initiator Commitment
initiator_commitment = CommitmentMetadata(
commitment_id="psi_initiator_customer_data_v1",
data_structure=DataStructure.CUSTOMER_LIST,
data_format=DataFormat.STRUCTURED,
entry_count=0, # Will vary based on customer data
field_count=3, # name, id, address
estimated_size_mb=0.001,
last_updated=datetime.now().isoformat(),
data_freshness=DataFreshness.REAL_TIME,
industry=Industry.FINANCE,
)
What this does:
- Advertises that Company A has customer data with 3 fields (name, id, address)
- Uses structured data format (can be JSON/CSV)
- Indicates real-time data freshness
- Belongs to the finance industry
- Does NOT reveal the actual customer data or queries
2.2 Company B Agent Commitment
Similarly, in company_b_agent/__main__.py:
# Company B Receiver Commitment
receiver_commitment = CommitmentMetadata(
commitment_id="psi_receiver_sanction_list_v1",
data_structure=DataStructure.BLACKLIST,
data_format=DataFormat.STRUCTURED,
entry_count=16, # Based on default sanction list
field_count=3, # name, id, address
estimated_size_mb=0.001,
last_updated=datetime.now().isoformat(),
data_freshness=DataFreshness.DAILY,
industry=Industry.FINANCE,
)
What this does:
- Advertises that Company B has a blacklist with 16 entries
- Each entry has 3 fields (name, id, address)
- Uses structured data format
- Indicates daily data freshness
- Does NOT reveal the actual blacklist contents
Step 3: Extend Agent Cards with AP3 Parameters
Both agents include AP3 extension parameters in their agent cards:
3.1 Company A Agent Card Extension
# Company A Agent Card Extension
company_a_ap3_extension = {
"uri": "https://github.com/silence-laboratories/ap3/tree/main",
"params": {
"roles": ["ap3_initiator"], # This agent initiates PSI checks
"supported_operations": ["PSI"], # Private Set Intersection
"commitments": [initiator_commitment]
}
}
3.2 Company B Agent Card Extension
# Company B Agent Card Extension
company_b_ap3_extension = {
"uri": "https://github.com/silence-laboratories/ap3/tree/main",
"params": {
"roles": ["ap3_receiver"], # This agent processes PSI requests
"supported_operations": ["PSI"],
"commitments": [receiver_commitment]
}
}
Key Points:
- Roles must be compatible:
ap3_receiver+ap3_initiatorpairs work together - Operations must match: Both must support
PSIfor Private Set Intersection - Commitments enable discovery: They help agents find suitable partners
Step 4: Implement AP3 Discovery
The host agent uses AP3DiscoveryService to:
- Fetch agent cards from both Company A and Company B
- Extract AP3 extension parameters from each card
- Calculate compatibility score based on:
- Role compatibility (receiver + initiator = compatible)
- Common operations (both support PSI)
- Commitment alignment (data structure, format, industry)
4.1 Run the Host Agent
cd host_agent
uv run .
The host agent will start on http://0.0.0.0:8000
4.2 Check Compatibility
The host agent provides an endpoint or interface to check compatibility:
from ap3.discovery import AP3DiscoveryService
ap3_discovery = AP3DiscoveryService()
# Host Agent - Compatibility Check
is_compatible, score, explanation, details = await ap3_discovery.check_compatibility(
company_a_url="http://localhost:10002",
company_b_url="http://localhost:10003"
)
print(f"Compatible: {is_compatible}")
print(f"Score: {score}/100")
print(f"Explanation: {explanation}")
Expected Output:
- is_compatible: True (if roles and operations match)
- score: 100 (if all checks pass)
- Explanation of why they're compatible
Step 5: Use Privacy Directives
5.1 Privacy Intent Directive
When initiating the PSI protocol, Company A creates a PrivacyIntentDirective:
from ap3.types.directive import PrivacyIntentDirective
from datetime import datetime, timedelta
import uuid
session_id = str(uuid.uuid4())
expiry_time = datetime.utcnow() + timedelta(hours=1)
privacy_intent = PrivacyIntentDirective(
ap3_session_id=session_id,
operation_type="PSI",
participants=["http://localhost:10002", "http://localhost:10003"],
expiry=expiry_time.isoformat(),
)
What this does: - Establishes a session for the computation - Declares the operation type (PSI = Private Set Intersection) - Lists all participating agents - Sets an expiry time for security
5.2 Validate Privacy Intent
Company B validates this directive before processing:
from common.ap3_directives import validate_privacy_intent_directive
is_valid, error_msg = validate_privacy_intent_directive(
directive=privacy_intent,
expected_operation_type="PSI"
)
if not is_valid:
raise ValueError(f"Invalid privacy intent: {error_msg}")
5.3 Privacy Result Directive
Upon completion, Company B creates a PrivacyResultDirective with the encrypted result:
from ap3.types.directive import PrivacyResultDirective, ResultData, OperationProofs
privacy_result = PrivacyResultDirective(
ap3_session_id=session_id,
result_data=ResultData(
encrypted_result=encrypted_psi_result,
result_hash=result_hash,
metadata={
"delivery_person_query": delivery_person_query,
"match_found": str(is_match)
}
),
proofs=OperationProofs(
correctness_proof=correctness_proof,
privacy_proof=privacy_proof,
verification_proof=verification_proof
)
)
Step 6: Run the Complete System
6.1 Terminal 1: Start Company A Agent
cd company_a_agent
export GOOGLE_API_KEY=<your-api-key>
uv run .
The Company A agent will start on http://localhost:10002
6.2 Terminal 2: Start Company B Agent
cd company_b_agent
export GOOGLE_API_KEY=<your-api-key>
uv run .
The Company B agent will start on http://localhost:10003
6.3 Terminal 3: Start Host Agent
cd host_agent
export GOOGLE_API_KEY=<your-api-key>
uv run .
The host agent will start on http://0.0.0.0:8000
6.4 Initiate the Computation
Use the host agent's interface to:
- Check compatibility between Company A and Company B agents
- Initiate the PSI computation
- Observe the 2-round protocol execution
- View the final result (MATCH FOUND/NO MATCH) without seeing the blacklist
Expected Flow:
- Host agent checks compatibility
- Company A creates
PrivacyIntentDirective→ Sends to Company B - Company B validates directive
- Both agents execute 2 rounds of secure computation
- Company B creates
PrivacyResultDirectivewith result - Result shows MATCH FOUND or NO MATCH (without revealing blacklist)
Step 7: Understand the Protocol Flow
The PSI protocol consists of 2 rounds of cryptographic computation:
-
Round 1 (msg1):
- Company A initiator hashes the delivery person query:
delivery_person_hash = hash("DeliveryPerson", query) - Creates PSI message 1 with the hash
- Includes
PrivacyIntentDirectivein the message - Sends to Company B receiver
- Company A initiator hashes the delivery person query:
-
Round 2 (msg2):
- Company B receiver validates the
PrivacyIntentDirective - Hashes all blacklist entries:
blacklist_hashes = [hash("Blacklist", entry) for entry in list] - Performs private set intersection computation
- Returns
msg2indicating match/no-match - Creates
PrivacyResultDirectivewith encrypted result - Blacklist never revealed to Company A
- Company B receiver validates the
-
Result:
- Company A initiator processes
PrivacyResultDirectiveto get final boolean result - Returns: "MATCH FOUND" or "NO MATCH"
- Company A initiator processes
Key Insight:
- Company A never sees Company B's blacklist contents
- The computation happens on hashed/encrypted data
- Only the final match/no-match result is revealed
- Company B's blacklist remains completely private
Summary
In this tutorial, you:
- Set up a three-agent system for privacy-preserving private set intersection
- Implemented AP3 commitments to advertise data structures
- Configured agent cards with AP3 extensions
- Used discovery service to check agent compatibility
- Implemented Privacy Intent and Result Directives
- Executed a secure PSI computation over 2 rounds