Inspiration
I have a young child. That fact colors how I read every AI-and-jobs headline these days — not the "AI helps you do more" stories, but the ones asking who's still employable once it doesn't need us the same way. I can probably navigate whatever labor market shows up in the next few decades — but what about him, and the much larger group of people who aren't glued to AI news, aren't early adopters, and won't have a head start? If there's an idea that makes that future a little better, it's worth more shared broadly than kept to myself.
The second thread: most of what I see about AI's impact on work focuses on how power users squeeze more out of it. But the thing that actually feels novel about general-purpose AI isn't that it helps the technically fluent go faster — it's that it can meet people with no technical fluency exactly where they are. That's a strength no prior wave of software had. I wanted a concrete example of that strength doing real work, not just a slide.
I'm sure other people have had a version of this thought before me — I'm not claiming the idea is original. What changed is the timing: WebMCP makes "any web page can be a real market participant" something you can actually build this month, not something that requires a platform to bless it first. So this submission is less "look what I made" and more "here's a working example of what I think this technology is for — someone should be pointing this direction."
What it does
Say to Match (StM) turns any static web page into a
participant in an open task market with one script tag. A page that
needs something declares a Job in plain natural language. A page
that can provide something declares a Skill — whether the provider
behind it is an AI agent or a human professional. Both are exposed as
real document.modelContext WebMCP tools. A Broker, backed by an
LLM, discovers these tools across independent origins, matches Jobs to
Skills, orchestrates the handoff between two pages that have never heard
of each other, verifies the delivered work against the original
requirement, and releases payment from escrow it held in trust. No
platform account, no onboarding, no API key required to participate —
just a script tag and a sentence anyone can write.
Concretely, a Job doesn't have to be a coding task: a small NGO transcribing a budget PDF into a CSV, a gig worker offering to survey Tokyo cafés with just a phone, a small business owner asking a licensed accountant to spot-check AI-transcribed receipts, or a social app team asking an 18–24-year-old for an honest first-time onboarding reaction. None of it requires knowing what WebMCP or JSON Schema even are.
How we built it
- The WebMCP layer is real, not simulated.
document.modelContexttools are actually registered on two genuinely independent origins (Requester and Worker), with a same-surface polyfill so it runs even without the experimental browser flag enabled. - The multi-origin story is real too. The Broker's agent drives an
actual headless Chromium instance via Playwright, opens the Requester
and Worker as separate pages, and calls
document.modelContext. callTool(...)inside each page's own context — proving this isn't one app quietly answering its own API calls. - Verification is tiered and real. Tier 1 runs the submitted work against an actual sandboxed regression test. Tier 2 is an LLM-as-Judge (DeepSeek via OpenRouter) that reviews the deliverable against the original job text — and explicitly screens for prompt-injection attempts from either side, since the requester's job description and the worker's deliverable are both untrusted text from the judge's point of view.
- The trust design is documented, not hand-waved.
docs/PROTOCOL.mdmaps StM's Job/Match/Settlement objects onto Google's AP2 (Agent Payments Protocol) Mandate pattern instead of reinventing signed-authorization primitives, and works through an adversarial catalogue — specific dishonest moves the Requester, the Worker, or the Broker itself could attempt — each one explicitly labeled as already defended in this PoC, designed but not implemented, or an honestly unsolved open problem. - It's actually deployed, not just runnable locally: three genuinely separate origins running on Cloud Run, built from the same container image, with GitHub Actions publishing the image automatically on push.
Worth being upfront about: the code, the deployment, and this write-up were built almost entirely through an AI coding agent (Claude Code), with me providing direction, judgment calls, and the framing — not writing the implementation by hand. That's not incidental to the story. I spent most of my career as a professional programmer before later moving into a different role, so I know firsthand what building something like this used to take. Watching an agent take it from a brainstormed idea to a live, adversarially-tested, multi-service deployment in about two days was a genuinely visceral measure of how far coding agents have come in just the few years since I stopped writing code for a living — and, fittingly, a small live demonstration of this project's own thesis: someone without hands-on technical execution, directing an AI to get something built that they couldn't have built alone in the time available.
Challenges we ran into
- A no-root dev sandbox with nothing pre-installed. Every piece of
infrastructure — Node, Playwright's Chromium system libraries, fonts,
ffmpeg, a TTS engine, even Docker itself (rootless) — had to be
assembled by hand in user space, without interactive
sudoaccess. - Proving cross-origin trust convincingly, not just claiming it. It would have been easy to fake the multi-origin story with one app playing three roles. Getting a real browser agent to navigate real separate origins and call real WebMCP tools took real orchestration work.
- Bidirectional prompt injection. The first pass only screened the worker's submitted deliverable for injection attempts. It took a second look to realize the requester's own job description — text the judge also reads — is just as valid an attack surface, and needed equally explicit defense.
- Verification itself is an attack surface. Once a Broker is willing to run a sandboxed test and an LLM call on request, that's a cost someone could weaponize as a denial-of-service. Working out a fault-based bond mechanism for who pays for verification, and under what conditions, took more thought than the "happy path" demo did.
- Racing a hard deadline without cutting corners on hygiene. Keeping API keys and private planning notes out of a repository that had to go public fast, including rewriting git history safely when something slipped through, ate real time that would rather have gone to features.
- Realizing that verifying non-code deliverables — a professional's
credential-backed judgment call, a claimed identity or demographic, a
piece of physical-world photo evidence — is still an open
trust-protocol problem, not something the current Tier 1 (sandbox) /
Tier 2 (LLM judge) pipeline actually solves. The demo intentionally
runs a code bugfix because it's the one task type that pipeline can
verify end to end today; documented as a real gap in
docs/PROTOCOL.mdrather than glossed over.
Accomplishments that we're proud of
- Genuine multi-origin WebMCP behavior, verified live rather than just
claimed — real cross-origin
document.modelContextcalls driven by a real browser agent, not a single app simulating three roles. - A prompt-injection defense that actually holds up in both directions, checked against real adversarial test cases, not just described.
- A trust-and-escrow design honest enough to explicitly separate what's live, what's designed but unimplemented, and what's an open problem — including an original piece of systems thinking (a fault-based Submission Bond) for a cost-based denial-of-service risk that isn't obvious until you think through who's paying for verification.
- Shipping to a real, live, three-service deployment rather than stopping at "works on my machine."
What we learned
The hard part of an open, permissionless task market was never discovery — it's trust, and specifically, defending the act of verifying trust from being gamed or exploited itself. That problem doesn't go away once you've built a matching engine; it's the actual product.
I also came away more convinced of the personal thesis behind this project than I was going in: a huge amount of what AI-assisted tools like this make possible isn't about making already-capable people faster. It's about letting someone contribute a clear goal and good judgment, and have that be enough — whether that's a non-technical worker declaring a Skill in plain language, or, in this project's own making-of story, an ex-programmer-turned-analyst directing an AI agent to build something in two days that would have taken him weeks by hand three years ago.
What's next for Say to Match
- Replace the simulated escrow ledger with a real settlement rail — the protocol design already maps cleanly onto x402 as the natural next step from the AP2 Mandate pattern it borrows.
- Implement Tier 3 dispute escalation, currently designed in
docs/PROTOCOL.mdbut not yet running in code. - Implement the Submission Bond mechanism described in the protocol design, so verification-cost denial-of-service resistance is actually enforced, not just specified.
- Grow beyond the single hand-verified bug-fix fixture to a broader, real-world catalog of Jobs and Skills, including real human Workers advertising Human-as-a-Service skills, not just an agent fixture.
- Re-evaluate the polyfill layer as native browser support for
document.modelContextactually ships, and make sure the real implementation is what most visitors experience. - Extend the adversarial trust catalogue (
docs/PROTOCOL.md) to cover credential, identity, and physical-evidence verification for non-code Jobs and Skills — the gap the "anyone can participate" pitch exposes once you look past the code-bugfix demo.
Built With
- css3
- docker
- express.js
- github-actions
- google-cloud-run
- html5
- javascript
- node.js
- openrouter
- playwright
- webmcp
Log in or sign up for Devpost to join the conversation.