HeartPrefs — Specification v0.1 (DRAFT)
An open, portable, signed matching-intent standard for agent-mediated matching. CC-BY-4.0.
Filegokhanturhan.com/heartprefs/spec/05 pages
HeartPrefs · pages
Status: DRAFT / experimental. Field names and bindings may change until v1.0. Every external rail this spec composes onto (x402, AP2, A2A, MCP, ERC-8004, VC cryptosuites) is itself draft or fast-moving — implementers MUST re-verify against first-party sources before depending on a specific field/path/ABI. See §9.
HeartPrefs is an open, portable, signed matching-intent document: a single JSON object that says who someone is, who and what they seek, and on what terms an agent may act for them — readable and actable by any agent at any venue.
The only thing HeartPrefs invents is the matching vocabulary (self / seek / free). Everything that makes a document trustable, portable and payable is delegated to existing standards via four thin binding blocks (identity, attestation, consent, payment). The same canonical bytes are designed to ride an x402 response body, an A2A Agent-Card extension, an MCP resource, and an ERC-8004 service entry without transformation.
1. Document shape
A HeartPrefs document is a JSON object validated by heartprefs.schema.json (JSON Schema draft 2020-12). Required top-level members: version, kind (const "heartprefs"), id, self, seek, free, identity, proof. See ../../examples/minimal.json.
self—gender,age(≥18),ethnicity[],kids,substances{},languages[].additionalProperties: false.seek—genders[],ageRange{min,max},languages[],ethnicities[],dealbreakers[].additionalProperties: false.free—about,seeking,values,interests,logistics,desire,boundaries.desireandboundariesare gated keys (see §5).
2. Identity binding (identity + proof)
The document is bound to a controller key and signed:
identity.subjectis a DID —did:pkh:eip155:<chainId>:<address>for an EVM wallet, ordid:web:<host>for a venue/issuer.proofis a detached signature over the RFC 8785 (JCS) canonicalization of the document withproof.signatureremoved. v0.1 usesproof.type = "EIP191"(personal_sign);proof.verificationMethodMUST equalidentity.subject.- Verification: re-canonicalize the document (JCS,
proof.signatureremoved), recover the signer, and assert it equals the address inidentity.subject. A document whose signature does not recover to its subject is invalid.
Implementation note: JCS number/Unicode handling is the usual signature-mismatch bug. Confirm your serializer is JCS-exact on both ends.
3. Adulthood (attestation)
HeartPrefs carries proof of adulthood by selective disclosure — never a date of birth. attestation.credential is a W3C Verifiable Presentation (VC Data Model 2.0) that discloses only a boolean ageOver18 predicate, issued by a venue/issuer DID (did:web:…) after an out-of-band age check. attestation.ageOver18 is a fast-filter summary; the credential is the source of truth. v0.1 pins the boolean property name ageOver18 (VC 2.0 defines no normative age field).
4. Payment & standing access (payment + consent)
paymentis an x402PaymentRequirementsquote (x402Version,accepts[]) advertising the price to read/submit. Settlement happens out of band over the x402 wire (HTTP402→X-PAYMENT→ facilitator verify/settle); the document only advertises the quote.consentexpresses standing access for an agent acting on the subject's behalf — either an AP2IntentMandate(scheme: "ap2-intent") or a signed metered allowance (scheme: "eip191-allowance"). x402 has no native recurring primitive; a venue picks ONE scheme.
5. Public vs gated
One schema, two projections:
- Public projection — everything except
free.desireandfree.boundaries. Safe to publish on a board, an A2A public Agent Card, or an unpaid MCP read. - Gated projection — adds
free.desire+free.boundaries, served only after identity proof and payment/consent are satisfied.
6. Matching semantics (bilateral)
A match is mutual and constraint-checked, not one-directional:
- For candidates A and B, A's
seekconstraints are checked against B'sself, and B'sseekagainst A'sself. - Dealbreakers are hard and ANDed: if any term in one side's
seek.dealbreakersis present in the other's document, there is no match.seek.ageRange,seek.genders, and non-emptyseek.languages/seek.ethnicitiesare hard filters. - Free-text and soft preferences feed ranking, not eligibility.
A conforming venue MUST enforce dealbreakers as hard predicates before proposing a pairing.
7. Extensions
ext is a permissionless bag for venue- or community-specific keys (suggested form namespace:key). Consumers MUST ignore unknown ext keys and unknown top-level members — never reject. Breaking additions go through the HIP process.
8. Conformance
A conformant document validates against heartprefs.schema.json and carries a proof that recovers to identity.subject. A conformant venue (a) accepts any conformant document, (b) enforces §6 dealbreakers, and (c) honors the public/gated projection in §5. A hosted validator + badge are part of the reference tooling.
9. Versioning & stability
The schema $id is version-pathed (/0.1/) so later versions can change shape without breaking existing holders. v0.1 is draft: treat field names and the binding blocks as unstable until v1.0. Because every composed rail is itself draft/preview, implementers MUST re-verify the exact x402 version, A2A Agent-Card version, MCP protocol/registry schema, ERC-8004 ABIs/addresses, and VC cryptosuite against first-party sources before locking an implementation.
10. Media type & schema URL
- Media type:
application/heartprefs+json(IANA registration pending; use provisionally). - Schema
$id:https://raw.githubusercontent.com/gokhan-vc/heartprefs/main/spec/0.1/heartprefs.schema.json(resolves from this repo). A host-independentw3id.org/heartprefspermalink is prepared understandards/w3id/; once registered, the$idcan switch to it.