Gökhan Turhan

Full-stack builder · generalist solopreneur · conceptual artist

MX-000 · REV 2026-07-17

Products Numetal

HeartPrefs

An open, portable, signed matching-intent standard for agent-mediated matching. CC-BY-4.0.

Filegokhanturhan.com/heartprefs/05 pages
HeartPrefsgokhanturhan.com/heartprefs/

An open, portable, signed matching-intent document that agents exchange to negotiate matches.

License Last commit Stars

Spec status TypeScript JSON Schema EIP-191 x402 A2A MCP

A HeartPrefs document says who someone is, who and what they seek, and on what terms an agent may act for them — in one signed JSON object that any agent, at any venue, can read, verify, and act on. You write it once; your agent can court anywhere that speaks HeartPrefs.

Status: v0.1 — DRAFT / experimental. Field names and bindings may change until v1.0.

What it is

HeartPrefs invents only the matching vocabulary (self / seek / free). Everything that makes a document trustable, portable, and payable is delegated to existing rails through four thin binding blocks:

Block Delegates to
identity W3C DID (did:pkh / did:web) + a detached EIP-191 signature
attestation a W3C Verifiable Credential (VC 2.0) proving ageOver18 by selective disclosure — no date of birth
consent an AP2 Intent Mandate, or a signed allowance, for standing / delegated access
payment an x402 quote (HTTP 402 + USDC) to read / submit / subscribe

The same canonical bytes are designed to ride an x402 body, an A2A Agent-Card extension, an MCP resource, and an ERC-8004 service entry — with no transformation.

Read the full spec: spec/0.1/SPEC.md · Schema: spec/0.1/heartprefs.schema.json · Example: examples/minimal.json.

Why

Agent-to-agent payment (x402 / AP2), discovery (A2A), tool/context (MCP), and identity (ERC-8004 + DID/VC) are all being standardized — but none defines a bilateral, mutual-consent matching intent. HeartPrefs fills exactly that gap, and only that gap, by composing the rest.

Quick look

{
  "kind": "heartprefs", "version": "0.1.0", "id": "urn:heartprefs:…",
  "self": { "gender": "woman", "age": 31, "languages": ["tr","en"] },
  "seek": { "genders": ["man"], "ageRange": {"min":30,"max":45},
            "dealbreakers": ["smoking","wants-no-kids"] },        // hard, ANDed
  "free": { "about": "…", "desire": "", "boundaries": "" },        // desire/boundaries are gated
  "identity": { "subject": "did:pkh:eip155:8453:0x…" },
  "attestation": { "ageOver18": true },
  "proof": { "type": "EIP191", "signature": "0x…" }                // over RFC-8785 JCS of the doc
}

The flow: sign → validate → verify → match

  • Sign — EIP-191 personal_sign over the RFC-8785 (JCS) canonicalization of the document with proof.signature removed. That single rule makes any document self-authenticating.
  • Validate — check the document against the frozen JSON Schema (draft 2020-12).
  • Verify — re-canonicalize, recover the signer, and assert it equals the DID in identity.subject. A document whose signature does not recover to its subject is invalid.
  • Match — matching is bilateral (SPEC §6): a.seek is checked against b.self and b.seek against a.self. Dealbreakers are hard and ANDed; free text feeds ranking, not eligibility.

SDK quickstart

The reference implementation is @heartprefs/sdk — a TypeScript library to author, sign, verify, validate, and match v0.1 documents.

npm install @heartprefs/sdk viem
import { buildDoc, signDoc, verifyDoc, validate, matches, didPkhFromAddress } from "@heartprefs/sdk";
import { privateKeyToAccount } from "viem/accounts";
const account = privateKeyToAccount(process.env.AGENT_PRIVATE_KEY as `0x${string}`);
const subject = didPkhFromAddress(account.address, 8453); // Base
const doc = buildDoc({
  id: `urn:heartprefs:${crypto.randomUUID()}`,
  self: { gender: "woman", age: 31, languages: ["tr", "en"] },
  seek: { genders: ["man"], ageRange: { min: 30, max: 45 }, dealbreakers: ["smoking"] },
  identity: { subject },
  attestation: { ageOver18: true },
});
const signed = await signDoc(doc, account);   // fills proof.signature
const { valid } = validate(signed);           // ajv, JSON Schema draft 2020-12
const v = await verifyDoc(signed);            // v.recovered === account.address

Build and test the SDK from source:

cd sdk
npm install
npm run typecheck   # tsc --noEmit
npm test            # vitest
npm run build       # tsup -> dist (ESM + CJS + .d.ts)

A full copy-paste agent walkthrough is in sdk/SKILL.md, and the SDK API surface is documented in sdk/README.md.

Validate without the SDK

Any JSON-Schema 2020-12 validator works — the document format is not tied to any one implementation:

npx ajv-cli validate -s spec/0.1/heartprefs.schema.json -d examples/minimal.json --spec=draft2020

Interop

HeartPrefs is a document format, not a transport. It is designed so the same canonical bytes move across the agent stack unchanged:

  • x402 — a payment block carries an x402 PaymentRequirements quote; the document advertises the price to read/submit while settlement happens out of band over the x402 wire (HTTP 402 → X-PAYMENT → facilitator verify/settle).
  • A2A — the public projection of a document fits an A2A Agent-Card extension, so an agent can publish who it seeks alongside its capabilities.
  • MCP — a document can be served as an MCP resource for context/tool exchange between agents.
  • ERC-8004 / DID / VC — identity binds to a W3C DID (did:pkh:eip155 or did:web); adulthood is a W3C Verifiable Credential (VC 2.0) disclosing only an ageOver18 predicate; a document can be referenced from an ERC-8004 service entry.

Each of these rails is itself draft or fast-moving — implementers MUST re-verify against first-party sources before depending on a specific field, path, or ABI. See SPEC §9.

Governance

HeartPrefs is stewarded as an open, neutral-by-design standard. A numbered HIP (HeartPrefs Improvement Proposal) process governs changes, and the standard is intended to move to a neutral home (W3C Community Group → Linux Foundation) once there are independent implementations. See GOVERNANCE.md.

Proposals, questions, and discussion go through the repository's issue tracker (open an issue or a PR). For contact by email, use [email protected].

Credits & third-party

The SDK builds on the following open-source projects:

Project Used for License
viem EIP-191 signing and signer recovery MIT
ajv + ajv-formats JSON Schema (draft 2020-12) validation MIT
canonicalize RFC-8785 (JCS) canonicalization Apache-2.0
tsup ESM/CJS/.d.ts bundling MIT
vitest testing MIT
TypeScript language / typecheck Apache-2.0

The standard composes onto the x402, AP2, A2A, MCP, and ERC-8004 specifications, plus the W3C DID and Verifiable Credentials data models.

License

Copyright (c) 2026 Atelier Gökhan / Numetal.

  • Vocabulary, JSON Schema, and spec text (spec/): CC-BY-4.0 — you may share, adapt, and build on HeartPrefs, including commercially, provided you give appropriate credit to "HeartPrefs (Atelier Gökhan / Numetal)" and link to the license.
  • Code (sdk/): Apache-2.0 (see sdk/LICENSE).
  • The name "HeartPrefs" and the conformance mark are protected — attribution lets you build on the standard; it does not grant the right to imply endorsement. See GOVERNANCE.md.

Reference implementation

Ishtar is the reference implementation and the first venue to consume HeartPrefs.