Brand vocabulary scrub: settlement framing, UI strings, retire M1-era design docs

- docs/ARCHITECTURE.md: settlement-asset framing (AP3X bonded in escrow,
  settles on accepted work); remove references to external network
  adapters that are not part of the project
- docs/buyer + docs/supplier READMEs: commission/bond/settle vocabulary
- Buyer web UI: "Accept & Settle", escrow-framed labels, gateway-managed
  wallet wording; gateway landing title punctuation
- Delete EXECUTIVE_SUMMARY and local-llm-marketplace docs + exports:
  M1-era internal design snapshots superseded by ARCHITECTURE.md and the
  public docs site

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
FilipBl4gojevic
2026-07-30 13:23:35 +02:00
parent 2aa1688a17
commit 73700f983a
16 changed files with 21 additions and 848 deletions

View File

@@ -94,7 +94,7 @@ export default function JobEstimate({
<dd className="text-right">{est.mapCalls}</dd>
<dt>Reduce calls</dt>
<dd className="text-right">{est.reduceCalls}</dd>
<dt className="font-medium">Total paid calls</dt>
<dt className="font-medium">Total escrowed calls</dt>
<dd className="text-right font-medium">{est.totalCalls}</dd>
<dt className="font-medium">Est. max cost</dt>
<dd className="text-right font-medium">{est.totalAp3x} AP3X</dd>
@@ -126,7 +126,7 @@ export default function JobEstimate({
disabled={blocked || starting}
className="rounded bg-indigo-600 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700 disabled:bg-gray-400"
>
{starting ? "Starting…" : `Proceed & pay (~${est.totalAp3x} AP3X)`}
{starting ? "Starting…" : `Proceed (locks ~${est.totalAp3x} AP3X in escrow)`}
</button>
</div>
);

View File

@@ -50,7 +50,7 @@ export default function PdfUploadForm({ onUploaded }: { onUploaded: (info: Uploa
return (
<form onSubmit={handleSubmit} className="space-y-4">
<p className="text-sm text-gray-600">
Upload a text-based PDF book. The buyer will chunk it and pay marketplace
Upload a text-based PDF book. The buyer will chunk it and commission marketplace
suppliers to summarize each chunk, then synthesize a full-book summary.
</p>
<input

View File

@@ -114,7 +114,7 @@ export default function ApiKeys() {
<h1 className="text-2xl font-semibold">API Keys</h1>
<p className="text-sm text-gray-600">
Generate an OpenAI-compatible API key for the marketplace gateway. Each key has its own
custodial wallet — fund its deposit address with AP3X, then point any OpenAI SDK at{" "}
gateway-managed wallet (the gateway holds this wallet's key) - fund its deposit address with AP3X, then point any OpenAI SDK at{" "}
<code className="font-mono text-xs">{baseUrl}</code>.
</p>
</div>

View File

@@ -152,7 +152,7 @@ export default function BookSummarizer() {
<div>
<h1 className="text-2xl font-semibold">Book Summarizer</h1>
<p className="mt-1 text-sm text-gray-500">
Upload a PDF → pay suppliers to summarize each chunk → get a full-book summary.
Upload a PDF → commission suppliers to summarize each chunk → get a full-book summary.
Jobs keep running if you navigate away; reopen them below.
</p>
</div>

View File

@@ -1,6 +1,6 @@
/**
* buyer/src/ui/pages/PendingReceipts.tsx — list of currently-Submitted escrows
* for this buyer, with an "Accept & Pay" action per row.
* for this buyer, with an "Accept & Settle" action per row.
*
* Data flow:
* GET /v1/pending-receipts → buyer-app server proxies indexer /escrows?buyer=<pkh>
@@ -190,7 +190,7 @@ export default function PendingReceipts() {
<th className="px-2 py-2">Submitted</th>
<th className="px-2 py-2">Supplier</th>
<th className="px-2 py-2">Capability</th>
<th className="px-2 py-2">Payment</th>
<th className="px-2 py-2">Escrowed</th>
<th className="px-2 py-2">Window left</th>
<th className="px-2 py-2">Action</th>
</tr>
@@ -254,7 +254,7 @@ export default function PendingReceipts() {
: "bg-indigo-600 text-white hover:bg-indigo-700")
}
>
{isAccepting ? "accepting…" : expired ? "expired" : "Accept & Pay"}
{isAccepting ? "accepting…" : expired ? "expired" : "Accept & Settle"}
</button>
)}
</td>

View File

@@ -304,7 +304,7 @@ function LifecycleCard({ lc }: { lc: Lifecycle }): JSX.Element {
</>
)}
<span className="text-gray-500">·</span>
<span>{fmtAda(lc.payment_lovelace)} payment</span>
<span>{fmtAda(lc.payment_lovelace)} escrowed</span>
<span className="text-gray-500">·</span>
<span>{fmtAda(lc.buyer_bond_lovelace)} bond</span>
<span className="text-gray-500">·</span>

View File

@@ -8,13 +8,13 @@
## 1. Goal and scope
**What this is.** A two-sided marketplace where buyers (agents or humans) submit prompts to suppliers running inference on their own hardware, pay with AP3X via on-chain bonded escrow on Vector L2, and receive signed-receipt responses. The primary validation goal is **technical feasibility + lifecycle** ("can it be done end-to-end"), not demand modelling or economic stress testing.
**What this is.** A two-sided marketplace where buyers (agents or humans) submit prompts to suppliers running inference on their own hardware, with each job settled in AP3X through on-chain bonded escrow on Vector L2, and receive signed-receipt responses. The primary validation goal is **technical feasibility + lifecycle** ("can it be done end-to-end"), not demand modelling or economic stress testing.
**What v1 is NOT.**
- Not agentic on the supplier side. Suppliers answer single prompts. Buyer agents drive multiple prompts.
- Not LLM-only in design. Capability model is open from day 1 (whisper / kokoro / image generation are planned siblings), but the first supplier is an LLM.
- Not multi-slot. Single-slot per supplier process. Multi-capability operators run multiple processes.
- Not multi-chain. Vector testnet first, mainnet later. Masumi / Sokosumi / USDM is target #2 (adapter, not fork).
- Not multi-chain. Vector only (testnet and mainnet).
- Not disputed. M1 ships happy-path escrow only. Module-1 disputes wire in M2.
- Not streaming. `stream: true` is rejected by suppliers.
- Not tool-calling. `tools` / `tool_choice` / `functions` are rejected by suppliers.
@@ -24,7 +24,7 @@
| # | Decision |
|---|---|
| 1 | Payment token: **AP3X** (Vector testnet, later mainnet). Masumi = USDM, target #2. |
| 1 | Settlement asset: **AP3X**, bonded in escrow; jobs settle in AP3X on accepted work. |
| 2 | v1 scope: **Option C** — happy-path escrow only, no disputes. Module-1 wiring is milestone 2. |
| 3 | Module-1 contract source: TBD — to be located or restored before M2. Not blocking M0–M1. |
| 4 | Evidence: **signed receipt** `{prompt_hash, response_hash, model, tokens, wallclock}` + Ed25519 supplier signature. Hash on-chain, plaintext off-chain. |
@@ -283,7 +283,6 @@ Malformed datum · escrow to wrong script · supplier claims escrow addressed to
| **M1** | Happy-path end-to-end, Hetzner CPU supplier | 2–3 wks | `qwen2.5:0.5b` on Hetzner, buyer posts → supplier claims → submits → buyer accepts; full Vector testnet lifecycle; indexer serves discovery |
| **M2** | Module-1 dispute wiring | 2–3 wks post-M1 | Contract source located; supplier=claimer / buyer=auditor mapping; Dispute state; evidence URI; mainnet-dry-run lifecycle |
| **M3** | Capability expansion + local lab | 2–4 wks (may overlap M2) | `speech.transcribe.v1` via Whisper live; local-lab GPU supplier with larger model; heterogeneous discovery validated |
| **M4** | Masumi / Sokosumi adapter | later | MIP-003 HTTP shim; MIP-002 NFT registration; USDM payment path; Sokosumi listing |
## 9. Open follow-ups (not blocking M0 / M1)
@@ -310,5 +309,3 @@ Malformed datum · escrow to wrong script · supplier claims escrow addressed to
- Apex-dashboard CBOR decoders: `apex-dashboard/server/cbor-decoder.ts`
- Apex-dashboard test discipline: `apex-dashboard/tests/`
- Prior Python reference (AP3X buyer/supplier): `./docs/buyer/`, `./docs/supplier/`
- Masumi docs: https://docs.masumi.network/
- MIP-003 spec: https://docs.masumi.network/mips/_mip-003

View File

@@ -1,412 +0,0 @@
---
marp: true
paginate: true
size: 16:9
---
<!--
EXECUTIVE_SUMMARY.md — slide-style overview of the Local Agents Marketplace.
Build PDF + PPTX with: bash docs/build-deck.sh
Edit this file; mermaid blocks are pre-rendered to docs/img/diagram-*.png.
-->
<style>
/* ── Local Agents Marketplace — unified dark theme ────────────────────
* Every slide uses the same navy→indigo gradient as the title slide so
* the deck reads as one continuous document. Title and closing slides
* keep the centered hero treatment; content slides stay top-aligned but
* share the same palette and accent rules. */
:root {
--ink: #f1f5f9; /* primary text on dark gradient */
--muted: #94a3b8;
--accent: #818cf8; /* indigo-400, readable on the dark gradient */
--accent-deep: #4f46e5; /* used for solid accents (h2 bar, table head) */
--accent-soft: rgba(129,140,248,0.12);
--gradient: linear-gradient(135deg, #0f172a 0%, #1e293b 50%, #312e81 100%);
--row-even: rgba(255,255,255,0.04);
--row-odd: rgba(255,255,255,0.02);
--border: rgba(255,255,255,0.10);
}
section {
background: var(--gradient);
color: var(--ink);
font-family: 'Inter', 'Segoe UI', system-ui, -apple-system, sans-serif;
font-size: 22px;
padding: 40px 60px;
display: flex;
flex-direction: column;
justify-content: flex-start;
}
section::after {
content: attr(data-marpit-pagination) ' / ' attr(data-marpit-pagination-total);
color: var(--muted);
font-size: 13px;
}
h1 {
font-size: 48px;
font-weight: 700;
color: #ffffff;
border-bottom: 4px solid var(--accent);
padding-bottom: 10px;
margin: 0 0 18px 0;
}
h2 {
font-size: 34px;
font-weight: 700;
color: #ffffff;
margin: 0 0 14px 0;
}
h2::before {
content: '';
display: inline-block;
width: 6px;
height: 28px;
background: var(--accent);
margin-right: 14px;
vertical-align: middle;
border-radius: 2px;
}
h3 { color: #c7d2fe; font-weight: 600; font-size: 24px; margin: 8px 0; }
p, li { margin: 6px 0; line-height: 1.45; }
ul, ol { margin: 8px 0 12px 0; padding-left: 28px; }
strong { color: #ffffff; }
a { color: #a5b4fc; }
blockquote {
border-left: 4px solid var(--accent);
background: rgba(255,255,255,0.06);
padding: 10px 18px;
color: #e0e7ff;
border-radius: 0 8px 8px 0;
margin: 10px 0;
}
code {
background: rgba(255,255,255,0.10);
color: #e0e7ff;
padding: 2px 6px;
border-radius: 4px;
font-size: 0.9em;
}
/* Constrain mermaid images so they always fit on a 720px-tall slide
* (16:9 @ 1280×720 default). Soft white card behind the diagram so the
* mermaid SVG (which renders on a transparent canvas with dark ink)
* stays readable on the navy gradient. */
img {
display: block;
margin: 8px auto;
max-width: 92%;
max-height: 420px;
object-fit: contain;
background: #ffffff;
border-radius: 10px;
padding: 10px;
box-shadow: 0 4px 16px rgba(0,0,0,0.25);
}
/* Tile grid for the local-agent versatility slide. */
.backends {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 14px;
margin: 14px 0 12px 0;
}
.tile {
background: var(--accent-soft);
border: 2px solid var(--accent);
border-radius: 10px;
padding: 14px 16px;
text-align: center;
font-weight: 600;
color: #ffffff;
}
.tile small {
display: block;
margin-top: 4px;
font-weight: 400;
color: var(--muted);
font-size: 0.8em;
}
.tile.dots {
background: rgba(255,255,255,0.04);
border-style: dashed;
color: var(--muted);
font-size: 28px;
}
.pipeline {
text-align: center;
background: rgba(255,255,255,0.08);
border: 1px solid var(--border);
color: #f8fafc;
padding: 12px 18px;
border-radius: 10px;
margin: 6px auto 14px auto;
max-width: 760px;
font-weight: 600;
}
.pipeline span {
display: inline-block;
margin: 0 10px;
}
/* Tables sit on a solid white card so cell text reads cleanly against
* the dark gradient backdrop. Rounded outer corners + shadow match the
* mermaid card styling. `display:table` + `table-layout:fixed` are
* needed so the table actually consumes the full slide width — Marp's
* default theme leaves tables at content-natural width, which left
* blank gutters on either side. */
table {
display: table !important;
width: 100% !important;
table-layout: fixed;
border-collapse: collapse;
margin: 12px 0;
font-size: 0.82em;
color: #0f172a;
background: #ffffff;
border-radius: 10px;
overflow: hidden;
box-shadow: 0 4px 16px rgba(0,0,0,0.25);
}
td, th { word-wrap: break-word; overflow-wrap: anywhere; }
th {
background: var(--accent-deep);
color: #ffffff;
text-align: left;
padding: 9px 12px;
font-weight: 700;
}
td {
padding: 7px 12px;
border-bottom: 1px solid #e2e8f0;
color: #0f172a;
}
tr:nth-child(even) td { background: #ffffff; }
tr:nth-child(odd) td { background: #f8fafc; }
/* code spans inside table cells need a light pill, not the dark one
* defined globally — otherwise they'd disappear into the white row. */
td code {
background: #eef2ff;
color: #1e293b;
}
/* Bold/strong inside cells must stay dark — the global rule paints
* <strong> white for the dark-gradient body text, which would render
* invisible against the white table card. */
td strong, th strong {
color: #0f172a;
}
th strong {
color: #ffffff;
}
/* Title slide — centered hero treatment on the same gradient. */
section.title {
text-align: center;
padding: 100px 80px;
justify-content: center;
}
section.title h1 {
display: inline-block;
font-size: 64px;
margin: 0 auto 20px auto;
}
section.title blockquote {
margin: 28px auto;
max-width: 900px;
}
/* Closing slide — same centered treatment. */
section.closing {
text-align: center;
padding: 100px 80px;
justify-content: center;
}
section.closing h2::before { display: none; }
section.closing blockquote { font-size: 26px; max-width: 900px; }
</style>
<!-- _class: title -->
# Local Agents Marketplace
### A trust-minimised, on-chain marketplace for LLM inference
Buy and sell prompt → response with **bonded escrow** on **Vector** (UTxO).
No platform fee. No central rate-limiter. Verifiable receipts on chain.
> *Status: M1 lifecycle proven end-to-end on Vector testnet — 2026-05-05.*
---
## The problem
* AI inference is **centralised** — a handful of providers, opaque pricing, account-level rate limits.
* Local-AI hardware is **idle most of the time** — GPUs and CPUs sit unused between user prompts.
* Buyers and sellers can't transact directly without a **trusted intermediary** taking a cut.
* "Verifiable" claims about which model ran are usually nothing more than the provider's word.
We need a **two-sided marketplace** where:
1. Sellers monetise spare compute,
2. Buyers get a **cryptographic receipt** of what was actually computed,
3. **Neither side has to trust the other** — bonds + on-chain settlement enforce honesty.
---
## How it works — three actors, one chain
```mermaid
flowchart LR
subgraph CHAIN[Vector — UTxO]
ADV[Advert UTxO<br/>capability, price, bonds]
ESC[Escrow UTxO<br/>locked funds + state]
end
SUP[🧠 Supplier<br/>local LLM node]
BUY[💼 Buyer<br/>app or agent]
IDX[🔭 Indexer<br/>read-only bulletin board]
SUP -->|publish advert| ADV
BUY -->|discover| IDX
IDX -.->|index events| CHAIN
BUY -->|post escrow| ESC
BUY -->|prompt + escrow_ref| SUP
SUP -->|signed receipt| BUY
SUP -->|claim & submit| ESC
BUY -->|accept & pay| ESC
```
* **Supplier** runs the inference and publishes a price.
* **Buyer** posts the work as a bonded escrow, sends the prompt, accepts the receipt.
* **Indexer** is a public mirror of chain state — anyone can run one. No platform middleman.
---
## The bonded-escrow lifecycle
```mermaid
sequenceDiagram
autonumber
participant B as Buyer
participant Chain as Vector
participant S as Supplier
participant LLM as Local LLM<br/>(OpenAI-compatible)
S->>Chain: PostAdvert (locks supplier_bond)
B->>Chain: PostEscrow → Open<br/>(locks payment + bonds)
B->>S: POST /v1/chat/completions
S->>Chain: ClaimEscrow → Claimed
S->>LLM: run inference
LLM-->>S: assistant message
S->>Chain: SubmitEscrow → Submitted
S-->>B: 200 OK + signed receipt
B->>Chain: AcceptEscrow — supplier paid
```
Every transition is on-chain, validated by an Aiken Plutus V3 script. The receipt is signed by the supplier's advert key; prompt and response hashes are bound on chain.
---
## What if someone misbehaves?
```mermaid
flowchart LR
OPEN[Open]:::norm --> CLAIMED[Claimed]:::norm --> SUBMITTED[Submitted]:::norm --> ACCEPTED[Accepted ✓]:::good
OPEN -->|deliver_by passed| RECLAIM[Reclaimed<br/>buyer recovers funds]:::warn
CLAIMED -->|deliver_by passed| RECLAIM
SUBMITTED -->|accept_window passed| RELEASE[Released<br/>supplier collects]:::warn
classDef norm fill:#e0e7ff,stroke:#4f46e5
classDef good fill:#dcfce7,stroke:#16a34a
classDef warn fill:#fef3c7,stroke:#d97706
```
| Failure mode | Recovery | Loss bearer |
|---|---|---|
| Supplier never claims/submits | Buyer **Reclaim** after `deliver_by` | Supplier — forfeits supplier_bond |
| Buyer disappears after Submit | Supplier **Release** after `submitted_at + 10 min` | Buyer — forfeits buyer_bond |
Bonds make honesty cheaper than running away. Both sides have skin in the game; no third-party arbiter is needed for the M1 happy/timeout paths.
---
## Local-agent versatility — any OpenAI-compatible engine
<div class="pipeline">
<span>💼 Buyer</span> →
<span>🧠 Supplier (OpenAI-compatible HTTP wrapper)</span> →
<span>backend ↓</span>
</div>
<div class="backends">
<div class="tile">Ollama<br/><small>local model runner</small></div>
<div class="tile">vLLM<br/><small>high-throughput GPU</small></div>
<div class="tile">llama.cpp<br/><small>CPU · Metal · ROCm</small></div>
<div class="tile">OpenRouter<br/><small>cloud API mux</small></div>
<div class="tile">openclaw / custom<br/><small>arbitrary stack</small></div>
<div class="tile dots">…<br/><small>any OpenAI-shaped API</small></div>
</div>
The supplier service is a thin HTTP wrapper — it forwards `/v1/chat/completions` to whatever backend is configured. Each supplier picks its own model, hardware, and engine, then advertises a `capability_id`. Buyers shop on capability + model + price.
---
## Capability + model = task selection
| Capability ID | Example models | Use case |
|---|---|---|
| `llm.text.generate.v1` | Llama 3 · Qwen 2.5 · Mistral · GPT-4 | Q&A, drafts, summarisation |
| `code.completion.v1` | Codestral · DeepSeek-Coder · StarCoder | IDE tab-complete, refactor |
| `vision.describe.v1` | LLaVA · Qwen-VL · Pixtral | Image captioning, OCR |
| `embedding.text.v1` | nomic-embed · BGE · ada-002 | RAG indexing |
| `audio.transcribe.v1` | whisper-large-v3 · distil-whisper | Voice-to-text |
| `…` | … | … |
* New capabilities = **just publish a new advert**. No marketplace governance gate.
* Today's deploy uses Ollama + Qwen 2.5; switching to vLLM with Llama 3 70B is a config change, not a code change.
---
## OpenClaw — agentic teams on your existing OpenAI seat
<div class="pipeline">
<span>🧠 Supplier wrapper</span> →
<span>🦾 OpenClaw</span> →
<span>🪪 OpenAI ChatGPT seat (flat-rate)</span>
</div>
* **Cost-efficient by default.** OpenClaw exposes your existing **OpenAI ChatGPT subscription** as an OpenAI-compatible API. The marketplace supplier dispatches its inference against it, so an entire **agentic team** (coders, QA automation testers, release curators…) draws from the **flat-rate seat you already pay for** — no per-token metering, no surprise invoices.
* **Reliability layer (optional, marginal cost).** OpenClaw can fall back to the **Anthropic API** or **OpenRouter** model pool when the primary seat is rate-limited, the prompt requires a different model, or you want a **second-layer hardening** of responses (e.g. cross-provider consensus on critical outputs). You only pay metered tokens for the requests that actually fall through.
---
## Proven on Vector testnet — 2026-05-05
| Step | Tx hash |
|---|---|
| Buyer posts escrow | `af762561…c2f7bc5` |
| Supplier claims | (lifecycle tx) |
| Supplier submits receipt | (lifecycle tx) |
| Buyer accepts | `125e3cfe…7dc100d` |
Funds flowed correctly: supplier received `payment + supplier_bond` (3 ADA); buyer got `buyer_bond` back.
* **Browser demo:** https://mp-buyers.vector.testnet.apexfusion.org
* **Live event stream:** https://mp-indexer.vector.testnet.apexfusion.org
* **Test suite:** 1098 unit tests passing, full lifecycle exercised in CI.
---
## Why UTxO + Vector
* **Bonded escrow is native** — Plutus validators enforce the state machine without a custom token or oracle.
* **Vector settles in seconds** — the buyer→claim→submit→accept loop fits inside a single chat-completion's wall clock.
* **AP3X token** for fees and bonds — fungible, transparent, on-chain.
* **No custom rollup, no bridge** — runs on a production chain today.
---
<!-- _class: closing -->
## The pitch in one sentence
> Local Agents Marketplace turns any OpenAI-compatible inference endpoint into a **trustlessly billable service** — buyer and supplier exchange prompt, response, and payment with on-chain proof that what was paid for is what was delivered.
### Try it
* **Indexer (live event stream):** https://mp-indexer.vector.testnet.apexfusion.org
* **Buyer:** https://mp-buyers.vector.testnet.apexfusion.org
* **Supplier:** https://mp-suppliers.vector.testnet.apexfusion.org/capability

Binary file not shown.

Binary file not shown.

View File

@@ -1,11 +1,11 @@
# Vector Buyer App
A self-contained app for purchasing AI compute on the Vector L2 testnet (Cardano). You submit prompts, pay with AP3X tokens via on-chain escrow, and receive LLM responses from supplier nodes.
A self-contained app for commissioning AI compute on the Vector L2 testnet. You submit prompts, bond AP3X in on-chain escrow, and receive LLM responses from supplier nodes; the escrow settles in AP3X on accepted work.
## How It Works
1. You type a **prompt** and set a **payment** amount in the web UI
2. The app posts an **escrow transaction** on-chain, locking your payment + bond
1. You type a **prompt** and set a **price** in the web UI
2. The app posts an **escrow transaction** on-chain, locking price + bond
3. The app sends the task to a **supplier node** via HTTP
4. The supplier calls an LLM, **claims** the escrow, and **submits** the result hash on-chain
5. You see the response in the UI and can **accept** to release payment, or **dispute**
@@ -193,8 +193,8 @@ If you accept the result, you get your 1 AP3X bond back. Total cost = payment +
- **Never share your .env file** - it contains your wallet seed phrase
- **Never share your data/ folder** - it contains task history
- The seed phrase controls your wallet funds. Back it up securely.
- Escrow protects you: the supplier cannot take your funds without delivering a result
- The seed phrase controls your wallet. Back it up securely.
- Escrow protects you: the supplier cannot take your escrowed value without delivering a result
- You have a 10-minute dispute window after receiving a result
## Troubleshooting

View File

@@ -1,412 +0,0 @@
---
marp: true
paginate: true
size: 16:9
---
<!--
EXECUTIVE_SUMMARY.md — slide-style overview of the Local Agents Marketplace.
Build PDF + PPTX with: bash docs/build-deck.sh
Edit this file; mermaid blocks are pre-rendered to docs/img/diagram-*.png.
-->
<style>
/* ── Local Agents Marketplace — unified dark theme ────────────────────
* Every slide uses the same navy→indigo gradient as the title slide so
* the deck reads as one continuous document. Title and closing slides
* keep the centered hero treatment; content slides stay top-aligned but
* share the same palette and accent rules. */
:root {
--ink: #f1f5f9; /* primary text on dark gradient */
--muted: #94a3b8;
--accent: #818cf8; /* indigo-400, readable on the dark gradient */
--accent-deep: #4f46e5; /* used for solid accents (h2 bar, table head) */
--accent-soft: rgba(129,140,248,0.12);
--gradient: linear-gradient(135deg, #0f172a 0%, #1e293b 50%, #312e81 100%);
--row-even: rgba(255,255,255,0.04);
--row-odd: rgba(255,255,255,0.02);
--border: rgba(255,255,255,0.10);
}
section {
background: var(--gradient);
color: var(--ink);
font-family: 'Inter', 'Segoe UI', system-ui, -apple-system, sans-serif;
font-size: 22px;
padding: 40px 60px;
display: flex;
flex-direction: column;
justify-content: flex-start;
}
section::after {
content: attr(data-marpit-pagination) ' / ' attr(data-marpit-pagination-total);
color: var(--muted);
font-size: 13px;
}
h1 {
font-size: 48px;
font-weight: 700;
color: #ffffff;
border-bottom: 4px solid var(--accent);
padding-bottom: 10px;
margin: 0 0 18px 0;
}
h2 {
font-size: 34px;
font-weight: 700;
color: #ffffff;
margin: 0 0 14px 0;
}
h2::before {
content: '';
display: inline-block;
width: 6px;
height: 28px;
background: var(--accent);
margin-right: 14px;
vertical-align: middle;
border-radius: 2px;
}
h3 { color: #c7d2fe; font-weight: 600; font-size: 24px; margin: 8px 0; }
p, li { margin: 6px 0; line-height: 1.45; }
ul, ol { margin: 8px 0 12px 0; padding-left: 28px; }
strong { color: #ffffff; }
a { color: #a5b4fc; }
blockquote {
border-left: 4px solid var(--accent);
background: rgba(255,255,255,0.06);
padding: 10px 18px;
color: #e0e7ff;
border-radius: 0 8px 8px 0;
margin: 10px 0;
}
code {
background: rgba(255,255,255,0.10);
color: #e0e7ff;
padding: 2px 6px;
border-radius: 4px;
font-size: 0.9em;
}
/* Constrain mermaid images so they always fit on a 720px-tall slide
* (16:9 @ 1280×720 default). Soft white card behind the diagram so the
* mermaid SVG (which renders on a transparent canvas with dark ink)
* stays readable on the navy gradient. */
img {
display: block;
margin: 8px auto;
max-width: 92%;
max-height: 420px;
object-fit: contain;
background: #ffffff;
border-radius: 10px;
padding: 10px;
box-shadow: 0 4px 16px rgba(0,0,0,0.25);
}
/* Tile grid for the local-agent versatility slide. */
.backends {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 14px;
margin: 14px 0 12px 0;
}
.tile {
background: var(--accent-soft);
border: 2px solid var(--accent);
border-radius: 10px;
padding: 14px 16px;
text-align: center;
font-weight: 600;
color: #ffffff;
}
.tile small {
display: block;
margin-top: 4px;
font-weight: 400;
color: var(--muted);
font-size: 0.8em;
}
.tile.dots {
background: rgba(255,255,255,0.04);
border-style: dashed;
color: var(--muted);
font-size: 28px;
}
.pipeline {
text-align: center;
background: rgba(255,255,255,0.08);
border: 1px solid var(--border);
color: #f8fafc;
padding: 12px 18px;
border-radius: 10px;
margin: 6px auto 14px auto;
max-width: 760px;
font-weight: 600;
}
.pipeline span {
display: inline-block;
margin: 0 10px;
}
/* Tables sit on a solid white card so cell text reads cleanly against
* the dark gradient backdrop. Rounded outer corners + shadow match the
* mermaid card styling. `display:table` + `table-layout:fixed` are
* needed so the table actually consumes the full slide width — Marp's
* default theme leaves tables at content-natural width, which left
* blank gutters on either side. */
table {
display: table !important;
width: 100% !important;
table-layout: fixed;
border-collapse: collapse;
margin: 12px 0;
font-size: 0.82em;
color: #0f172a;
background: #ffffff;
border-radius: 10px;
overflow: hidden;
box-shadow: 0 4px 16px rgba(0,0,0,0.25);
}
td, th { word-wrap: break-word; overflow-wrap: anywhere; }
th {
background: var(--accent-deep);
color: #ffffff;
text-align: left;
padding: 9px 12px;
font-weight: 700;
}
td {
padding: 7px 12px;
border-bottom: 1px solid #e2e8f0;
color: #0f172a;
}
tr:nth-child(even) td { background: #ffffff; }
tr:nth-child(odd) td { background: #f8fafc; }
/* code spans inside table cells need a light pill, not the dark one
* defined globally — otherwise they'd disappear into the white row. */
td code {
background: #eef2ff;
color: #1e293b;
}
/* Bold/strong inside cells must stay dark — the global rule paints
* <strong> white for the dark-gradient body text, which would render
* invisible against the white table card. */
td strong, th strong {
color: #0f172a;
}
th strong {
color: #ffffff;
}
/* Title slide — centered hero treatment on the same gradient. */
section.title {
text-align: center;
padding: 100px 80px;
justify-content: center;
}
section.title h1 {
display: inline-block;
font-size: 64px;
margin: 0 auto 20px auto;
}
section.title blockquote {
margin: 28px auto;
max-width: 900px;
}
/* Closing slide — same centered treatment. */
section.closing {
text-align: center;
padding: 100px 80px;
justify-content: center;
}
section.closing h2::before { display: none; }
section.closing blockquote { font-size: 26px; max-width: 900px; }
</style>
<!-- _class: title -->
# Local Agents Marketplace
### A trust-minimised, on-chain marketplace for LLM inference
Buy and sell prompt → response with **bonded escrow** on **Vector** (UTxO).
No platform fee. No central rate-limiter. Verifiable receipts on chain.
> *Status: M1 lifecycle proven end-to-end on Vector testnet — 2026-05-05.*
---
## The problem
* AI inference is **centralised** — a handful of providers, opaque pricing, account-level rate limits.
* Local-AI hardware is **idle most of the time** — GPUs and CPUs sit unused between user prompts.
* Buyers and sellers can't transact directly without a **trusted intermediary** taking a cut.
* "Verifiable" claims about which model ran are usually nothing more than the provider's word.
We need a **two-sided marketplace** where:
1. Sellers monetise spare compute,
2. Buyers get a **cryptographic receipt** of what was actually computed,
3. **Neither side has to trust the other** — bonds + on-chain settlement enforce honesty.
---
## How it works — three actors, one chain
```mermaid
flowchart LR
subgraph CHAIN[Vector — UTxO]
ADV[Advert UTxO<br/>capability, price, bonds]
ESC[Escrow UTxO<br/>locked funds + state]
end
SUP[🧠 Supplier<br/>local LLM node]
BUY[💼 Buyer<br/>app or agent]
IDX[🔭 Indexer<br/>read-only bulletin board]
SUP -->|publish advert| ADV
BUY -->|discover| IDX
IDX -.->|index events| CHAIN
BUY -->|post escrow| ESC
BUY -->|prompt + escrow_ref| SUP
SUP -->|signed receipt| BUY
SUP -->|claim & submit| ESC
BUY -->|accept & pay| ESC
```
* **Supplier** runs the inference and publishes a price.
* **Buyer** posts the work as a bonded escrow, sends the prompt, accepts the receipt.
* **Indexer** is a public mirror of chain state — anyone can run one. No platform middleman.
---
## The bonded-escrow lifecycle
```mermaid
sequenceDiagram
autonumber
participant B as Buyer
participant Chain as Vector
participant S as Supplier
participant LLM as Local LLM<br/>(OpenAI-compatible)
S->>Chain: PostAdvert (locks supplier_bond)
B->>Chain: PostEscrow → Open<br/>(locks payment + bonds)
B->>S: POST /v1/chat/completions
S->>Chain: ClaimEscrow → Claimed
S->>LLM: run inference
LLM-->>S: assistant message
S->>Chain: SubmitEscrow → Submitted
S-->>B: 200 OK + signed receipt
B->>Chain: AcceptEscrow — supplier paid
```
Every transition is on-chain, validated by an Aiken Plutus V3 script. The receipt is signed by the supplier's advert key; prompt and response hashes are bound on chain.
---
## What if someone misbehaves?
```mermaid
flowchart LR
OPEN[Open]:::norm --> CLAIMED[Claimed]:::norm --> SUBMITTED[Submitted]:::norm --> ACCEPTED[Accepted ✓]:::good
OPEN -->|deliver_by passed| RECLAIM[Reclaimed<br/>buyer recovers funds]:::warn
CLAIMED -->|deliver_by passed| RECLAIM
SUBMITTED -->|accept_window passed| RELEASE[Released<br/>supplier collects]:::warn
classDef norm fill:#e0e7ff,stroke:#4f46e5
classDef good fill:#dcfce7,stroke:#16a34a
classDef warn fill:#fef3c7,stroke:#d97706
```
| Failure mode | Recovery | Loss bearer |
|---|---|---|
| Supplier never claims/submits | Buyer **Reclaim** after `deliver_by` | Supplier — forfeits supplier_bond |
| Buyer disappears after Submit | Supplier **Release** after `submitted_at + 10 min` | Buyer — forfeits buyer_bond |
Bonds make honesty cheaper than running away. Both sides have skin in the game; no third-party arbiter is needed for the M1 happy/timeout paths.
---
## Local-agent versatility — any OpenAI-compatible engine
<div class="pipeline">
<span>💼 Buyer</span> →
<span>🧠 Supplier (OpenAI-compatible HTTP wrapper)</span> →
<span>backend ↓</span>
</div>
<div class="backends">
<div class="tile">Ollama<br/><small>local model runner</small></div>
<div class="tile">vLLM<br/><small>high-throughput GPU</small></div>
<div class="tile">llama.cpp<br/><small>CPU · Metal · ROCm</small></div>
<div class="tile">OpenRouter<br/><small>cloud API mux</small></div>
<div class="tile">openclaw / custom<br/><small>arbitrary stack</small></div>
<div class="tile dots">…<br/><small>any OpenAI-shaped API</small></div>
</div>
The supplier service is a thin HTTP wrapper — it forwards `/v1/chat/completions` to whatever backend is configured. Each supplier picks its own model, hardware, and engine, then advertises a `capability_id`. Buyers shop on capability + model + price.
---
## Capability + model = task selection
| Capability ID | Example models | Use case |
|---|---|---|
| `llm.text.generate.v1` | Llama 3 · Qwen 2.5 · Mistral · GPT-4 | Q&A, drafts, summarisation |
| `code.completion.v1` | Codestral · DeepSeek-Coder · StarCoder | IDE tab-complete, refactor |
| `vision.describe.v1` | LLaVA · Qwen-VL · Pixtral | Image captioning, OCR |
| `embedding.text.v1` | nomic-embed · BGE · ada-002 | RAG indexing |
| `audio.transcribe.v1` | whisper-large-v3 · distil-whisper | Voice-to-text |
| `…` | … | … |
* New capabilities = **just publish a new advert**. No marketplace governance gate.
* Today's deploy uses Ollama + Qwen 2.5; switching to vLLM with Llama 3 70B is a config change, not a code change.
---
## OpenClaw — agentic teams on your existing OpenAI seat
<div class="pipeline">
<span>🧠 Supplier wrapper</span> →
<span>🦾 OpenClaw</span> →
<span>🪪 OpenAI ChatGPT seat (flat-rate)</span>
</div>
* **Cost-efficient by default.** OpenClaw exposes your existing **OpenAI ChatGPT subscription** as an OpenAI-compatible API. The marketplace supplier dispatches its inference against it, so an entire **agentic team** (coders, QA automation testers, release curators…) draws from the **flat-rate seat you already pay for** — no per-token metering, no surprise invoices.
* **Reliability layer (optional, marginal cost).** OpenClaw can fall back to the **Anthropic API** or **OpenRouter** model pool when the primary seat is rate-limited, the prompt requires a different model, or you want a **second-layer hardening** of responses (e.g. cross-provider consensus on critical outputs). You only pay metered tokens for the requests that actually fall through.
---
## Proven on Vector testnet — 2026-05-05
| Step | Tx hash |
|---|---|
| Buyer posts escrow | `af762561…c2f7bc5` |
| Supplier claims | (lifecycle tx) |
| Supplier submits receipt | (lifecycle tx) |
| Buyer accepts | `125e3cfe…7dc100d` |
Funds flowed correctly: supplier received `payment + supplier_bond` (3 ADA); buyer got `buyer_bond` back.
* **Browser demo:** https://mp-buyers.vector.testnet.apexfusion.org
* **Live event stream:** https://mp-indexer.vector.testnet.apexfusion.org
* **Test suite:** 1098 unit tests passing, full lifecycle exercised in CI.
---
## Why UTxO + Vector
* **Bonded escrow is native** — Plutus validators enforce the state machine without a custom token or oracle.
* **Vector settles in seconds** — the buyer→claim→submit→accept loop fits inside a single chat-completion's wall clock.
* **AP3X token** for fees and bonds — fungible, transparent, on-chain.
* **No custom rollup, no bridge** — runs on a production chain today.
---
<!-- _class: closing -->
## The pitch in one sentence
> Local Agents Marketplace turns any OpenAI-compatible inference endpoint into a **trustlessly billable service** — buyer and supplier exchange prompt, response, and payment with on-chain proof that what was paid for is what was delivered.
### Try it
* **Indexer (live event stream):** https://mp-indexer.vector.testnet.apexfusion.org
* **Buyer:** https://mp-buyers.vector.testnet.apexfusion.org
* **Supplier:** https://mp-suppliers.vector.testnet.apexfusion.org/capability

Binary file not shown.

Binary file not shown.

View File

@@ -164,8 +164,8 @@ If the buyer does NOT accept within the dispute window (10 minutes), you can col
- **Never share your .env file** - it contains your wallet seed phrase
- **Never share your data/ folder** - it contains task history
- The seed phrase controls your wallet funds. Back it up securely.
- The node only responds to buyers who have already locked funds on-chain, so you cannot be scammed out of compute.
- The seed phrase controls your wallet. Back it up securely.
- The node only responds to buyers who have already locked value on-chain, so you cannot be scammed out of compute.
## Troubleshooting

View File

@@ -8,7 +8,7 @@ export const INDEX_HTML = `<!doctype html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Vector Marketplace — OpenAI Gateway</title>
<title>Vector Marketplace - OpenAI Gateway</title>
<style>
body { font-family: system-ui, sans-serif; max-width: 760px; margin: 2rem auto; padding: 0 1rem; line-height: 1.5; }
h1 { font-size: 1.5rem; } h2 { font-size: 1.1rem; margin-top: 2rem; }
@@ -22,7 +22,7 @@ export const INDEX_HTML = `<!doctype html>
</style>
</head>
<body>
<h1>Vector Marketplace — OpenAI-compatible Gateway</h1>
<h1>Vector Marketplace - OpenAI-compatible Gateway</h1>
<p class="muted">Point any OpenAI SDK at <code id="base"></code> using your API key as the bearer token.</p>
<h2>1. Create an API key</h2>