Programmable Promises
Pay when the work is real. A payer describes what “done” means; PayPal holds funds; a worker submits photo proof; AI checks it against a machine-readable checklist; pass triggers capture and payout, fail explains why with human review when the outcome is unclear.
Demo application using PayPal authorize → capture → Payouts. Not escrow or legal advice.
Inspiration
Freelance and gig work often breaks down at the same moment: “Did they actually do what I paid for?” Escrow products exist, but they rarely encode your definition of done in a way software can enforce. Vision models can read photos well enough to check simple, explicit criteria and PayPal already knows how to authorize, capture, and pay out.
We wanted a story you could feel in three minutes: write a promise, fund it with PayPal Buttons, watch a worker upload proof, and see money move only when the rules say so not when the model “feels” confident. Programmable Promises treats payment logic as data (checklist + thresholds + state machine), not as ad-hoc chat.
We extended that with AG Studio for operational visibility and MCP so agents can create and track promises while funding still goes through PayPal’s UI so a person approves the hold.
What we built
| Actor | Experience |
|---|---|
| Payer | Create promise → AI drafts checklist → edit & confirm → authorize hold via PayPal → monitor status, review edge cases, AG Studio dashboard |
| Worker | One-time link → challenge code → upload JPG/PNG → live verification progress |
| Agent (optional) | Cursor + custom pp_* MCP tools + PayPal MCP; human completes PayPal Buttons for funding |
End-to-end flow
- Create promise (amount, deadline, natural-language condition).
- Confirm checklist (required items, weights, pass threshold).
- Fund → Money held (PayPal authorization).
- Worker submits proof with challenge code visible in the image.
- Pass → capture + payout to worker email. Clear fail → hold kept, reasons shown. Third fail / low confidence / verifier error → Review (approve pays, deny releases hold).
- Past deadline → authorization voided.
Also in the repo: paginated promise list, SSE + polling on worker/payer views, optional Kafka workers for async verify and webhooks, LLM proxy for AG Studio’s agent panel, Docker Compose for local full stack.
How we built it
Architecture
TypeScript monorepo:
packages/sharedstate machine, shared decision rules, unit tests.apps/apiExpress, PostgreSQL, Redis, PayPal client, verifier abstraction, analytics for AG Studio, studio LLM proxy.apps/webAngular: create, fund, worker upload, detail/review, lazy-loaded AG Studio dashboard.apps/mcpstdio MCP server over the REST API (pp_login,pp_create_promise,pp_submit_proof, …).workerKafka consumers for verification, webhooks, and payment commands (optional; sync path for simpler deploys).
Hosted demo: Angular on Vercel, API on Render, managed Postgres + Redis. The production UI calls the API directly (CORS); worker links use the live site origin.
Browser (Vercel) ──► Express API (Render) ──► Postgres / Redis
├──► PayPal (authorize, capture, payouts)
├──► OpenAI / Gemini (vision + checklist)
└──► Kafka + worker (optional)
Agents ──► MCP ──► API
PayPal
OAuth token caching, Orders with authorize intent, capture after proof, Payouts to worker email. PayPal Buttons in the UI with server-side confirm on approve. Idempotent writes, payout batch reuse on retry, background polling so long-running payout status does not depend on a single HTTP request (important on serverless/time-limited hosts).
AI + rules (the model never touches money)
- Checklist generation from the payer’s description (editable before confirm).
- Proof verification multimodal model returns per-item scores; a deterministic rules engine decides pass / fail / review.
Logged model output is for debugging; it is not the payment decision.
- Every required item must pass with confidence (\geq \tau_{\mathrm{item}}) (default (0.7)).
- Weighted score (\displaystyle\frac{\sum_i w_i \cdot s_i}{\sum_i w_i} \geq \tau_{\mathrm{global}}) (default (0.8)).
- Challenge code in the image must match.
Ambiguous results → human review, not auto-pay.
AG Studio & MCP
/dashboard KPIs, status charts, promise pipeline and verification evidence from GET /api/analytics/studio-data; Studio agent via POST /api/studio/llm-turn (keys on server). PayPal MCP plus our @pp/mcp server for agent-driven create/track/submit.
What we learned
- Separate AI opinion from payment action a thin rules layer on vision output made behavior trustworthy and debuggable.
- PayPal is asynchronous payouts can stay pending; UX, retries, and background reconciliation matter as much as the happy path.
- Split hosting is normal static UI + long-lived API; explicit API base URL and CORS beat fragile reverse-proxy-only setups on preview URLs.
- Agents need guardrails MCP accelerates workflows; PayPal checkout stays human-in-the-loop for authorization.
- Partner SDKs are real work AG Studio + Angular versioning, lazy routes, and LLM proxy shapes were a major slice of the build.
- Live feedback sells the demo SSE and polling on the worker page made verification feel real, not batch-only.
Challenges we faced
| Challenge | What happened | What we did |
|---|---|---|
| Duplicate proof / double pay | Retries and races | Idempotent payout batches, proof dedup, clear states |
| Payout stuck “in progress” | Long PayPal processing; HTTP timeouts on PaaS | Shorter in-request polls + 30s background job; Retry payment; treat unclaimed payouts appropriately in demo |
| Deploy: UI vs API | Vercel rewrites flaky on previews | Production apiBaseUrl to Render; CORS on API |
| Worker links showed localhost | APP_BASE_URL vs browser origin |
Build worker URLs from window.location when payer creates from UI |
| AG Studio LLM 502 | Request shape / model mismatch for Gemini | Proxy parsing, provider-aware models, clearer errors |
| Angular × AG Studio | Peer dependency conflicts | Pin Angular 19, lazy dashboard, bundle budgets |
| Grid layout UX | Action buttons stretched into circles | align-self, flex rows, split-column alignment |
| Scope | Time and complexity | Images-only MVP, 48h deadline cap, one crisp video narrative |
Tech stack
Angular 19 · Node.js / Express · TypeScript · PostgreSQL · Redis · PayPal REST · OpenAI / Gemini · AG Studio · MCP · Docker · Vercel · Render · optional Kafka (Redpanda)
Try it
- Live app: (https://programmable-promises.vercel.app/)
- Repo: github.com/deveshparmar/programmable-promises
- Sign in with any email → create → confirm checklist → PayPal fund → worker link → upload proof → Dashboard for AG Studio.
Closing
Can PayPal hold the money while AI checks the proof and only then pay? Programmable Promises implements that loop: programmable checklists, rules-based verification, PayPal capture and payout, human review when automation is not enough, AG Studio for visibility, and MCP for agents without letting the model sign the check.
Built With
- ai
- angular.js
- docker
- express.js
- gemini
- jwt
- kafka
- mcp
- monorepo
- node.js
- npm
- openai
- postgresql
- redis
- redpanda
- sse
- typescript
Log in or sign up for Devpost to join the conversation.