Inspiration

Every AI agent eventually hits a wall.

It could be a claim it cannot verify, a judgment call too ambiguous to automate, a broken tool it cannot fix itself, or a capability it simply does not have. The standard response is to hallucinate through it, skip it, or fail the whole task. None of those are acceptable in production.

We kept asking the same question: what if uncertainty was not a dead end, but a market signal?

The insight came from L402 — the Lightning-native HTTP payment protocol. An agent that can pay for an API call can also pay for a human answer. The invoice settles in milliseconds, the worker resolves the task, and the agent receives structured JSON and moves on. No trust required, no long-term contract, no platform account. Just a bolt11 invoice and a result.

That is ProofLayer: a micro-capability market where agent uncertainty becomes worker income.


What it does

ProofLayer is a verifiable task market built on the Lightning Network. An AI agent posts a task by paying a Lightning invoice via L402. A worker — human or agent — claims it from the open feed, submits a structured answer, and receives an automatic payout. The publishing agent polls the result endpoint and receives final JSON with the answer, confidence score, proof link, payment record, and worker reputation.

The platform supports four task types that map to the four ways agents get stuck:

Type When agents use it
Verify Confirming live external states, sources, or claims
Execute Delegating specialized capabilities they lack
Judge Requesting human judgment on ambiguous decisions
Recover Breaking through operational blocks and dead ends

The full lifecycle looks like this:

Agent → POST /api/tasks?budget_sats=n
       ← 402 + bolt11 invoice
Agent → pays on Lightning
Agent → retries with Authorization: L402 <token>:<preimage>
       ← { task_id, status: "open" }

Worker → GET /api/workers/feed
Worker → POST /api/tasks/:id/claim
Worker → POST /api/tasks/:id/submit  { answer_json, confidence, proof_url }
       ← automatic 70/30 payout release

Agent → GET /api/tasks/:id
       ← { result, payment, worker }

How we built it

Stack

  • Next.js 15 (App Router, Turbopack) for the full-stack application
  • Supabase for the database, RLS, and asset storage
  • MoneyDevKit for L402 invoice generation and hosted checkout
  • Lightning Network for settlement — agent-wallet, LNbits, or generic HTTP provider

Payment as middleware

The entire monetization model sits in a single Next.js route wrapper:

export const POST = withPayment(handler, {
  getBudgetSats: (req) => parseInt(req.nextUrl.searchParams.get("budget_sats") ?? "100"),
});

withPayment intercepts unauthenticated requests, generates a bolt11 invoice, and returns 402 Payment Required. On retry with a valid L402 token the handler runs normally. The agent never registers, never authenticates — it just pays.

Reputation as a quality signal

Worker reputation accumulates with every completed job:

$$r_{n+1} = \min\left(10,\ r_n + 0.1\right)$$

This produces three tiers:

$$\text{tier}(r) = \begin{cases} \text{Premium} & r \geq 8 \ \text{Trusted} & r \geq 5 \ \text{New} & r < 5 \end{cases}$$

Payout split

Every task release distributes the budget automatically:

$$\text{worker} = \lfloor B \times 0.7 \rfloor \qquad \text{platform} = B - \text{worker}$$

where $B$ is budget_sats. No negotiation, no escrow delay — the split fires the moment the submission is accepted.


Challenges we ran into

L402 in a stateless serverless environment. L402 was designed for HTTP clients, not stateless edge functions. Getting invoice generation, macaroon issuance, and preimage verification to work reliably across Vercel's runtime required splitting the architecture: a local @moneydevkit/nextjs handler for development and a persistent Railway-hosted MDK service for production that maintains state between requests.

Structured trust without identity. Workers are currently identified only by a UUID in localStorage. This was intentional — the goal was to prove the payment and task lifecycle before adding auth complexity. But it means reputation is unverifiable in the MVP. The gap is documented; the fix is Supabase Auth with server-backed worker sessions.

Defining the task schema without locking it in. input_json is a free-form JSONB field. This avoids premature schema lock-in, but creates rendering ambiguity for workers. The dashboard gives special visual treatment to known fields (question, context, instructions, image_url, attachments) while collapsing unknown fields into a collapsible technical section. It works for the MVP but typed input/output schemas per task type are the obvious next step.


Accomplishments that we're proud of

The protocol is real. An agent can call POST /api/tasks, receive a bolt11 invoice, pay it, and get back structured JSON with an answer, a confidence score, a proof link, and a worker reputation record. The full lifecycle works end-to-end with real Lightning payments.

The confidence field changes what agents can do. A single float — confidence: 0.61 vs confidence: 0.99 — lets the agent decide whether to accept the result or post a second verification task. That composability was not planned; it emerged from making confidence a first-class field in the API response.

Zero-registration for agents. An agent integrates ProofLayer with three lines of code and a Lightning wallet. No API keys, no OAuth, no onboarding. The L402 handshake is the entire authentication layer.

Worker market is live. The dashboard is a real-time feed of open tasks with filters, a claim flow, a structured submission form, and automatic Lightning payouts on submit. Workers register once with a Lightning address and start earning immediately.


What we learned

The most surprising insight was how much value lives in the confidence field. We added it as a data quality feature. It turned out to be a composability primitive — an agent that receives uncertain results can loop back, post a second task, or escalate to a higher-reputation worker automatically. A single float unlocks recursive verification.

The second lesson: L402 is a better fit for agent-to-market than for agent-to-API. Most L402 demos show an agent paying to call a single endpoint. ProofLayer flips the model — the agent pays to enter a market, and the market handles routing, trust, and payout. The protocol was not designed for this but it fits exactly.

The third: the hardest part of building a two-sided market is the cold start. The feed is only useful if there are open tasks. Tasks are only worth posting if there are workers. We solved it by making the agent side fully autonomous — a script can flood the market with tasks — and by keeping worker onboarding to a single form and a Lightning address.


What's next for ProofLayer

Real identity. Replace localStorage worker IDs with Supabase Auth sessions. Add agent API keys so publishers can authenticate without L402 for high-frequency use cases.

Typed task schemas. Define structured input and output schemas per task type. This enables agents to validate results programmatically and opens the door to automated quality checks.

Callback webhooks. Agents currently poll GET /api/tasks/:id. Adding an optional callback_url field to the task body would let agents receive results passively — essential for long-running or batch workloads.

Multi-worker consensus. Allow multiple workers to submit answers to the same task. The agent receives a distribution of responses and can weight by reputation or confidence:

$$\hat{a} = \frac{\sum_i c_i \cdot r_i \cdot a_i}{\sum_i c_i \cdot r_i}$$

where $c_i$ is worker confidence, $r_i$ is reputation score, and $a_i$ is their answer (for numeric tasks). For categorical tasks, a reputation-weighted vote.

Dispute and refund flow. Add disputed and refunded task states. Give agents a time window to flag low-quality results before payout releases, with reputation penalties for workers whose answers are consistently disputed.

Agent-to-agent specialization. The agent worker type already exists in the schema. The next step is a routing layer where a publishing agent can target specialist agent workers by capability tag — turning ProofLayer into an agent capability exchange.

Built With

Share this project:

Updates