Build on intents.md
The whole protocol is three steps: write a markdown file, put it at a URL, done. No API, no account, no SDK. Everything below is optional convenience on top of that — publish to a live feed, wear the badge, and hand your AI agent the keys.
1 · Publish an intent
An intent document is plain markdown: a header block of key: value lines, a blank line, then a markdown body. Host it at any URL.
intent: 1
type: offer
title: Vintage synth for sale
ask: 400 USD
contact: mailto:you@example.com
Fully serviced. Local pickup or shipped worldwide.
That is the whole standard — see the spec and examples. An optional signature (Layer 2) binds the document to your domain.
2 · Push it to a live feed
Hosting at a URL is the protocol; pushing to a receiver (a directory that aggregates intents) is how you get discovered. intentsmd.com is the reference receiver, and its publish endpoint is open — any site can POST to it, cross-origin. No account, no key.
POST https://intentsmd.com/api/intents
Content-Type: application/json
| Field | Required | Notes |
|---|---|---|
verb |
yes | want · need · offer · rfp · announce |
title |
yes | 3–200 chars |
contact |
— | mailto:… or https://… only |
category |
— | free text — used to group and filter |
price |
— | free text, e.g. 400 USD, 12.5 ETH |
region |
— | world · apac · europe · americas |
body |
— | markdown body of the intent |
const res = await fetch("https://intentsmd.com/api/intents", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
verb: "offer",
title: "Vintage synth for sale",
category: "gear",
price: "400 USD",
contact: "mailto:you@example.com",
body: "Fully serviced. Local pickup or shipped worldwide.",
}),
});
const { url } = await res.json(); // -> "/i/<id>" on the receiver
Read the feed back the same way: GET /api/intents?sort=latest&limit=20 (add &cat=<category> to filter).
3 · Wear the badge
If your site speaks intents.md, say so — and link home:
<a href="https://intentsmd.org">⛺ built on intents.md</a>
4 · For AI agents
Point your agent at intentsmd.org/llms.txt — a machine-readable summary of the format, the publish endpoint, and the feed. Then just ask it: read intents.md and post my intent.
5 · Sign your intent (get verified)
Unsigned intents (Layer 0) work everywhere but rank lowest. Signing proves an intent came from you — and because the protocol is algorithm-agile (algo is declared, never fixed), there's an easy rung and an advanced one.
Easiest — sign with a crypto wallet → Layer 1. Your wallet already holds a key. A tool (or your agent) computes the document's canonical form, and you sign it with an Ethereum personal_sign (EIP-191):
algo: eip191,keyid:= your0x…address, and the signature block carries thepersonal_signoutput.- Any verifier
ecrecovers your address from the signed canonical form and checks it matcheskeyid. No PGP, no domain.
That's Layer 1 — signed, portable, and your reputation follows the key.
Add the domain badge → Layer 2. Publish that key at https://yourdomain/.well-known/intents-md/key.asc and set issuer-url. Verifiers then show "Signed · yourdomain".
A pages.dev or github.io subdomain is the platform's domain, not yours — the spec caps those at L1, on purpose: the L2 badge exists because a real domain costs money (the sybil defense). The cheapest way to a real one:
- Register a domain you own — Cloudflare Registrar sells at wholesale (~$10/yr for a
.com, no markup), or any registrar works. - Host the key on it for free — a Cloudflare Pages site on your domain, serving your public key at
/.well-known/intents-md/key.asc(a plain static file). - Point to it — set
issuer-urlto your domain. Verifiers fetch the key, match the fingerprint, and grant L2.
No wallet? Ask your agent. Point your AI agent at the spec — github.com/Goldcote/intents.md — and say "help me publish a signed intent." It can generate a key (ed25519 or PGP), compute the canonical form, sign, and set up the well-known path for you.
Key custody. Keep signing keys in a hardware-backed vault — Secure Enclave, HSM, or a hardware wallet — the spec's recommended posture: the vault performs sign(canonical form) and the key never leaves the hardware.
Status — forward-looking. The reference feed doesn't display verified badges yet (it's Tier-0 today), and the exact
eip191binding is being pinned so every verifier agrees. Signing now future-proofs your intent; verification and badges land as the trust layer ships.
Trust & spam — the protocol already answers this
An open write endpoint sounds like a spam magnet. The protocol's answer is trust at the edge, not a gate at the door (03-SERVICES):
- Domain binding (Layer 2) gives every identity a real Sybil cost — domains cost money, and registrars kill abuse cycles.
- Receivers rank L2 > L1 > L0 and default unsigned floods out of the main feed — still reachable by direct URL, because omission is not hiding.
- Admission policy is receiver territory: proof-of-work stamps, payment-gated contacts (x402), bonded reputation. Free for an honest publisher; ruinous at spam scale.
Unsigned (Layer 0) posting stays open; signing is how you earn ranking. That is the design — not a bolt-on captcha.