尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證Private fraud check for agent payments: AP3 PSI + PayPal Orders v2 (PayPal AI Hackathon)
翻譯準備中
取自儲存庫 README
正在載入完整 README。
檢視完整 README ↗When an AI agent buys on someone's behalf, the merchant's own agent privately checks the buyer against other merchants' fraud lists, then uses PayPal to capture, hold or decline the payment. No merchant ever shares its list.
Built for the PayPal AI Hackathon 2026 (solo entry by Vic Kaul). PayPal sandbox only; all data is synthetic.
Live demo · Judges' summary ·
merchant console at /console (password in the Devpost testing
instructions) · Video (2:51)
| 9 | 14-18 s | 0 | 134 |
|---|---|---|---|
| private checks per order (3 identifiers x 3 merchants) | buyer approval to final decision, hosted (measured) | list entries that ever leave their owner | automated tests, plus live sandbox runs |
The problem · What it does · Who saw what · Architecture · AI tools used · Try it hosted · Run it locally · Tests · Limits · Licence and credits
A purchase made by an AI agent arrives without most of what fraud tools read: no mouse movement, no typing rhythm, no browsing path. Industry reporting from MPE 2026 says agentic transactions strip away the behavioural markers current tools rely on [1], and fraud liability for agent pilots is still unclear [2].
What still identifies a repeat abuser is the plain stuff: email, shipping address, device. Another merchant may already have this buyer on its chargeback list. But merchants can't hand customer lists to competitors: privacy law limits sharing personal data to what is necessary and proportionate [3], and a list is a commercial asset. Shared fraud intelligence today runs through a vendor that receives every member's data, and hashing the lists doesn't help, because emails and addresses are guessable (our assessment).
AP3, an open protocol that lets agents from different companies compute on private data without revealing it, makes a different design possible. Silence Laboratories contributed it to LF Decentralized Trust; it is in research preview [4] [5].
What it's worth (industry figures; how far Quiet Check moves them in production is not yet measured):
Shop. The buyer tells the shopping agent "buy the blue backpack in medium". It finds the item, builds the cart
and creates a PayPal order with intent AUTHORIZE, priced by the backend, never the agent. The buyer approves in the
PayPal pop-up.
Check. The merchant's risk agent asks three consortium merchants (Members A, B, C) whether they hold the buyer's email, shipping address or device ID: 3 x 3 = 9 AP3 private set intersection (PSI) sessions, run at once. Each answer is a yes or no; no list leaves its owner, and every session is stored as a signed, verified receipt.
Decide. A fixed rule decides, and Claude explains the decision in 2-3 sentences. It can explain the decision but never change it.
| Hits | Decision | PayPal action |
|---|---|---|
| 0 | clean | Authorise, then capture |
| 1 | hold | Authorise only (funds held); queue for human review |
| 2 or more, or email and device both hit | block | Don't authorise; the order expires |
Review. In the merchant console a reviewer sees the receipts, a 3x3 hit grid and a "who saw what" panel, asks the review copilot about the hold, and on their instruction plus one Approve click the copilot captures or voids the payment in PayPal. The console counts down PayPal's 3-day honour period for capturing a hold.
Dispute. If a buyer later disputes a captured payment, the verified webhook brings the dispute into the console, Claude drafts the merchant's evidence from the receipts and decision log, and a reviewer edits and submits it to PayPal.
Three demo buyers, same shop, same item, three outcomes:
| Persona | Seeded on | Hits | Outcome | Buyer sees |
|---|---|---|---|---|
| Ana | Nothing | 0 | Authorised and captured | "Paid" |
| Ben | Member B (email) | 1 | Authorised only, held for review | "Payment on hold for review" |
| Cy | Members A and C (email and device) | 4 | Never authorised, no money moves | "We couldn't complete this order" |
Each member holds about 300 synthetic entries with the personas seeded on purpose. In three back-to-back hosted runs on 2026-10-14 and three more on 2026-10-16, all 18 orders came out right, each with 9 of 9 receipts verified (measured).
Every PayPal call in the demo hits the live sandbox. Nothing on screen is mocked.
| PayPal piece | What we use it for |
|---|---|
| JS SDK v6 | Buyer approval in the PayPal pop-up, started from the agent's order |
| Orders v2 | Create with intent AUTHORIZE; read payer email and shipping after approval; authorise |
| Payments v2 | Capture a clean order; capture or void a held one on the reviewer's instruction |
| Webhooks | CHECKOUT.ORDER.APPROVED starts the risk agent; capture, void and dispute events confirm state. Signatures verified, events deduped |
| Idempotency | PayPal-Request-Id on every money-moving call, so retries can't double-charge |
| Disputes v1 | Read the dispute; submit the reviewer's evidence with provide-evidence |
The consortium runs on the open-source AP3 SDK (ap3[a2a], ap3-functions 1.2.2) [4].
| AP3 piece | What we use it for |
|---|---|
| A2A agents | Members A, B and C are separate A2A servers, each holding only its own list |
| AgentCards | Roles (initiator, receiver) and each member's signed commitment to its list (size, format, digest) |
| PSI | 9 sessions per order: "is this value in your set?", answered yes or no [5] |
| Directives | Each session's signed intents are captured; receipts are verified before they are stored |
The console shows this panel on every order, because privacy claims should be specific:
| Party | Sent | Learned | Never saw |
|---|---|---|---|
| Merchant (us) | Blinded hashes of email, address, device | Match yes/no per member per field | Any member's list |
| Member A, B or C | Its PSI responses (unsigned) and its signed commitment | Nothing about the query or result | The buyer's identifiers; other members' lists |
| PayPal | Payer details; payment status | Order, authorisation, capture or void | Any fraud list or check result |
| The AI model | - | The hit summary only (which member matched which field) | Raw lists, other buyers' data; for dispute drafts, also the payer's email, address and device |
Note the first row: PSI tells the checking merchant which member matched which field. "Count only" is future work (see Limits).
Seven pieces on Render, one private network. Only the shop and the backend are public. The backend accepts unauthenticated calls only for health, PayPal's signed webhooks and the order status; everything else needs a token. Members are private services that answer only the backend's AP3 initiator.
flowchart LR
buyer([Buyer]) --> web
reviewer([Fraud reviewer]) --> web
subgraph render [Render · private network · oregon]
web["Web · Next.js<br/>shop + shopping agent<br/>console + review copilot"]
backend["Backend · FastAPI<br/>risk agent · policy · payments<br/>AP3 initiator :8100"]
wf["Render Workflow<br/>process_order task<br/>retries, durable runs"]
db[("Postgres<br/>orders · checks · receipts<br/>decisions · events")]
a["Member A<br/>own list"]
b["Member B<br/>own list"]
c["Member C<br/>own list"]
web -->|token| backend
backend -->|start run| wf
wf -->|/merchant/process| backend
backend --- db
backend <-->|AP3 PSI| a
backend <-->|AP3 PSI| b
backend <-->|AP3 PSI| c
end
web -.->|JS SDK v6 pop-up| paypal
backend <-->|Orders v2 · Payments v2| paypal[(PayPal sandbox)]
paypal -->|signed webhooks| backend
web -->|AI SDK| claude[(Claude API)]
backend -->|LangChain| claude
| Layer | Choice |
|---|---|
| Backend | Python 3.12, FastAPI, SQLAlchemy Core; SQLite locally, Postgres on Render |
| Consortium | AP3 SDK 1.2.2; three member agents (local processes, or Render private services) |
| Web | Next.js 16, React 19, Tailwind 4, Vercel AI SDK v7 |
| Orchestration | Render Workflows runs each order's check -> decide -> PayPal action with retries; an in-process fallback takes over within 45 s if a run stalls. Locally the risk agent runs in-process |
| Operations | Deep health check (database, each member's list digest, workflow); a sweep reruns orders stuck mid-check; a scheduled synthetic check emails on failure |
Locally the same pieces run as processes: backend on :8000 (AP3 initiator on :8100), Members A-C on :8101-8103,
web on :3000, SQLite instead of Postgres, no token or console password.
Inside the product. All models are Anthropic's Claude, behind a swap layer (LLM_PROVIDER, LLM_MODEL_FAST,
LLM_MODEL_SMART), with prompts in prompts/. The AI explains and assists; it never makes the decision
and can't move money on its own.
| Where | Model | Library | What it does |
|---|---|---|---|
Shopping agent (web/app/api/chat/route.ts) | Claude Haiku 5.5 (LLM_MODEL_FAST) | Vercel AI SDK v7, @ai-sdk/anthropic | Turns a sentence into a product search, a cart and a PayPal order, with three tools |
Risk rationale (backend/app/rationale.py) | Claude Haiku 5.5 (LLM_MODEL_FAST) | LangChain init_chat_model | Explains each decision in 2-3 sentences from the hit summary only. After any error or 10 s, a template stands in |
Review copilot (web/app/api/console/chat/route.ts) | Claude Haiku 5.5 (LLM_MODEL_FAST) | Vercel AI SDK v7 tool approval | Answers "why is this on hold?"; captures or voids only after the reviewer clicks Approve on a signed card showing the order, amount and action |
Dispute evidence (backend/app/disputes.py) | Claude Sonnet 5.5 (LLM_MODEL_SMART) | LangChain init_chat_model | Drafts the merchant's evidence from the receipts, decision and PayPal timeline, without the buyer's identifiers. A person edits and submits it. A template stands in on failure |
Guardrail: the backend recomputes the policy from the stored receipts and rejects any decision the policy didn't make
(409 policy_mismatch). A swap to Sonnet for the fast tasks was tested live (measured).
Used to build it. The code, tests and docs were written with Claude Code (Claude Opus 5.5) under Vic's direction;
commits it co-authored carry a Co-Authored-By trailer. The demo video's narration is ElevenLabs text-to-speech
(voice: elevenlabs.io).
/console (any username; the password is in the testing instructions), click the order and ask the copilot
about a held order.Log out at https://www.sandbox.paypal.com before switching buyers: the PayPal pop-up reuses the last login, even across incognito windows. The first order after a quiet spell can take up to about 30 s (measured).
About 15 minutes, most of it the PayPal sandbox setup. You need macOS or Linux, uv (it fetches Python 3.12), Node 22, pnpm 10, a free PayPal developer account and an Anthropic API key.
In the PayPal Developer Dashboard, with Sandbox selected:
ngrok http 8000, add a webhook on the app at
https://<ngrok-host>/webhooks/paypal with the events CHECKOUT.ORDER.APPROVED, PAYMENT.AUTHORIZATION.CREATED,
PAYMENT.AUTHORIZATION.VOIDED, PAYMENT.CAPTURE.COMPLETED and CUSTOMER.DISPUTE.CREATED / UPDATED / RESOLVED,
and copy its webhook ID.git clone https://github.com/vickaul-ai/quiet-check.git && cd quiet-check
cp .env.example .env # fill in the variables below
make install # uv sync (backend) + pnpm install (web)
make sandbox # checks the PayPal credentials can fetch an OAuth token
make seed # writes the three members' synthetic lists, seeded with Ben's and Cy's emails
make dev # backend :8000, Members A-C :8101-8103, web :3000
Variable in .env | Value |
|---|---|
PAYPAL_CLIENT_ID, PAYPAL_CLIENT_SECRET | The sandbox app's credentials |
ANTHROPIC_API_KEY | Your Anthropic key |
PERSONA_ANA_EMAIL, PERSONA_BEN_EMAIL, PERSONA_CY_EMAIL | The three sandbox buyer emails |
PAYPAL_WEBHOOK_ID | Optional: the webhook's ID, if you set one up |
Leave the rest at their defaults. The member keys are generated on first run. Every variable, including the hosted-only
ones, is described in docs/contracts.md. If you change a persona email,
rerun make seed and restart make dev.
Open http://localhost:3000, pick Ana, ask "buy the blue backpack in medium" and approve in the pop-up as Ana's sandbox buyer. Then log out at https://www.sandbox.paypal.com and repeat as Ben and Cy. The console is at http://localhost:3000/console (open locally, no password).
Approve as the buyer that matches the persona: the persona sets the device ID, the PayPal login sets the email, and the check uses both.
render.yaml is a Render Blueprint for the whole stack (backend, web, Members A-C, Postgres, the risk workflow).
bash scripts/render_setup.sh walks through the first deploy; docs/deploy-render.md has the
details and the cost (about $41/month on Render's paid plans).
make check # what CI runs: ruff, 134 pytest tests, the log privacy scan, eslint, type-check
cd backend && uv run pytest -m slow -s # times a demo-size check (~300 entries per member; about 3 s)
The unit and integration tests start real member processes and use a stateful fake PayPal. CI runs the backend suite on SQLite and Postgres. Every test run's logs are scanned, and the build fails if any list entry or test identifier appears.
Live sandbox runs need a human to approve orders in the pop-up:
| Command | Does |
|---|---|
make live-personas | One order per persona through the sandbox; the webhook alone must give captured, held and blocked (needs ngrok http 8000 and make dev-backend stopped) |
make approve-orders, then make test-live or make gate-a END=capture | Saved sandbox orders through the risk agent: capture, or hold then reviewer void |
make e2e-hosted | Ana, Ben and Cy through the hosted shop and PayPal pop-up, driven by Playwright (needs PERSONA_*_PASSWORD and the hosted console password in .env) |
scripts/check_hosted.sh <backend URL> <web URL> | Smoke-checks the hosted demo: public routes answer, private ones refuse |
make dispute-sandbox ARGS="--list" | Lists the app's sandbox disputes; --escalate and --require-evidence move one along so the console can submit |
Evidence it works (all measured on the hosted build, 2026-10-14 to 2026-10-16):
What this demo doesn't claim:
| Path | Holds |
|---|---|
backend/ | FastAPI app: risk check, policy, risk agent, payments, webhooks, disputes, AP3 initiator and members (uv) |
web/ | Next.js storefront, shopping agent, merchant console and review copilot (pnpm) |
workflow/ | The Render Workflows task that runs the risk agent when hosted |
prompts/ | One Markdown prompt per AI task |
scripts/ | Sandbox check, hosted smoke check, hosted persona run, Render setup |
site/ | The judges' summary (static HTML) |
docs/ | brief.md (story, policy, scope), contracts.md (endpoints, webhooks, tables, errors), ENGINEERING.md, PRODUCT.md, deploy-render.md, decisions/ (ADRs) |
PayPal authorisation rules (29-day hold, 3-day honour period): https://developer.paypal.com/docs/checkout/standard/customize/authorization/. Measurements come from the project's test log, 2026-10-13 to 2026-10-16.
Apache-2.0. See LICENSE.
ap3 and
ap3-functions packages.Quiet Check is not affiliated with or endorsed by PayPal, Silence Laboratories or LF Decentralized Trust.