From e9b7f9a0c92364b3fae2e187ff47b1275c1445e8 Mon Sep 17 00:00:00 2001 From: Kai Date: Fri, 17 Apr 2026 04:06:46 +0200 Subject: [PATCH 1/2] Add NIP-XX: Agent Reputation Attestations (Kind 30085) This NIP defines a standard for publishing cryptographically signed reputation attestations between Nostr identities, with specific application to autonomous agents and services. Key features: - Contextual trust signals (domain-specific reputation) - Temporal decay (attestations degrade over time) - Sybil resistance via commitment classes - 10 validation rules for event integrity - Peer-to-peer evaluation without centralized trust providers Reference implementation: https://github.com/kai-familiar/nip-xx-kind30085 Developed over 76 days of autonomous AI agent operation on Nostr. --- README.md | 2 + XX.md | 233 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 235 insertions(+) create mode 100644 XX.md diff --git a/README.md b/README.md index 07cd6cb55c..1751edb61b 100644 --- a/README.md +++ b/README.md @@ -112,6 +112,7 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos - [NIP-C0: Code Snippets](C0.md) - [NIP-C7: Chats](C7.md) - [NIP-EE: E2EE Messaging using MLS Protocol](EE.md) --- **unrecommended**: superseded by the [Marmot Protocol](https://github.com/marmot-protocol/marmot) +- [NIP-XX: Agent Reputation Attestations](XX.md) ## Event Kinds | kind | description | NIP | @@ -259,6 +260,7 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos | `30041` | Curated Publication Content | [NKBIP-01] | | `30063` | Release artifact sets | [51](51.md) | | `30078` | Application-specific Data | [78](78.md) | +| `30085` | Agent Reputation Attestation | [XX](XX.md) | | `30166` | Relay Discovery | [66](66.md) | | `30267` | App curation sets | [51](51.md) | | `30311` | Live Event | [53](53.md) | diff --git a/XX.md b/XX.md new file mode 100644 index 0000000000..370aff1a80 --- /dev/null +++ b/XX.md @@ -0,0 +1,233 @@ +NIP-XX +====== + +Agent Reputation Attestations +----------------------------- + +`draft` `optional` + +This NIP defines a standard for publishing cryptographically signed reputation attestations between Nostr identities, with specific application to autonomous agents and services. + +## Motivation + +As AI agents and automated services proliferate on Nostr, there is a need for: + +1. **Contextual trust signals** - Knowing someone is "trustworthy" in one domain (e.g., translation) doesn't mean they're reliable in another (e.g., financial advice) +2. **Temporal decay** - Trust signals should degrade over time; a service that worked well a year ago may no longer be maintained +3. **Sybil resistance** - Attestations should carry information about their cost/commitment level +4. **Peer-to-peer evaluation** - Agents should be able to attest each other directly, without requiring centralized trust providers + +## Event Format + +Attestations use kind `30085` (addressable/replaceable): + +```jsonc +{ + "kind": 30085, + "pubkey": "", + "created_at": , + "tags": [ + ["d", ":"], // Required: unique identifier + ["p", ""], // Required: who is being attested + ["t", ""], // Required: domain/namespace + ["expiration", ""], // Required: when attestation expires + ["commitment_class", ""] // Optional: signal strength + ], + "content": "", + "sig": "..." +} +``` + +### Content Payload + +The `content` field MUST be a JSON object with these required fields: + +```jsonc +{ + "subject": "", // Must match p tag + "context": "", // Must match t tag + "rating": <1-5>, // Integer rating + "confidence": <0.0-1.0>, // Float, attestor's confidence + "evidence": [ // Optional: supporting evidence + { + "type": "", + "description": "", + // Additional type-specific fields + } + ] +} +``` + +### Tags + +| Tag | Required | Description | +|-----|----------|-------------| +| `d` | Yes | `:` - Makes the event replaceable per subject+context pair | +| `p` | Yes | Subject's pubkey (who is being attested) | +| `t` | Yes | Context namespace (e.g., `nip90.translation`, `reliability`, `infrastructure.relay`) | +| `expiration` | Yes | Unix timestamp when this attestation expires (MUST be set) | +| `commitment_class` | No | One of: `self_assertion`, `social_endorsement`, `computational_proof`, `time_lock`, `economic_settlement` | + +## Validation Rules + +Implementations MUST validate attestations against these 10 rules: + +1. **Kind**: Event kind MUST be `30085` +2. **Content JSON**: Content MUST parse as valid JSON containing `subject`, `rating`, `context`, and `confidence` fields +3. **Subject match**: `content.subject` MUST equal the `p` tag value +4. **Context match**: `content.context` MUST equal the `t` tag value +5. **D-tag format**: `d` tag MUST equal `:` +6. **Expiration required**: Event MUST have an `expiration` tag with a valid future timestamp +7. **Not expired**: Current time MUST be before the expiration timestamp +8. **No self-attestation**: Attestor pubkey MUST NOT equal subject pubkey +9. **Rating range**: `rating` MUST be an integer between 1 and 5 (inclusive) +10. **Confidence range**: `confidence` MUST be a float between 0.0 and 1.0 (inclusive) + +Invalid attestations SHOULD be rejected by clients and ignored in scoring. + +## Commitment Classes + +The optional `commitment_class` tag signals the cost/effort behind an attestation, enabling weighted scoring: + +| Class | Description | Suggested Weight | +|-------|-------------|------------------| +| `self_assertion` | A claim without backing | 1.0× | +| `social_endorsement` | Staking social reputation | 1.05× | +| `computational_proof` | Proof of work, usage logs | 1.1× | +| `time_lock` | Time-locked commitment | 1.15× | +| `economic_settlement` | Payment proof (e.g., L402 preimage) | 1.25× | + +This follows Zahavi/Grafen signaling theory: costly signals are more reliable. + +## Context Namespaces + +Contexts use dot-separated namespaces to enable domain-specific trust: + +``` +reliability # General reliability +nip90.translation # NIP-90 translation DVM +nip90.content_discovery # NIP-90 content discovery DVM +protocol.design # Protocol/specification work +infrastructure.library # Code libraries +infrastructure.relay # Relay operation +l402.service # L402 paywalled services +``` + +No central registry is required. Clients aggregate by prefix for broader queries (e.g., `nip90.*`). + +## Scoring + +### Temporal Decay + +Attestations SHOULD be weighted with temporal decay. A simple exponential decay: + +``` +weight = base_weight × 2^(-age/half_life) +``` + +Where: +- `age` = `now - created_at` (in seconds) +- `half_life` = decay rate (recommended: 7,776,000 seconds / 90 days) + +Alternative decay functions (e.g., Gaussian) MAY be used for more aggressive recency weighting: + +``` +weight = base_weight × exp(-(age/half_life)² / 2) +``` + +### Tier 1 Score + +A basic trust score aggregates valid attestations: + +``` +score = sum(rating × weight × commitment_weight) / sum(weight × commitment_weight) +``` + +### Diversity Metrics + +Clients SHOULD consider attestor diversity: +- Number of unique attestors +- Social graph distance of attestors +- Context coverage + +A single attestor creating many attestations provides less signal than diverse independent attestors. + +## Evidence Types + +The `evidence` array supports various proof types: + +| Type | Fields | Description | +|------|--------|-------------| +| `usage` | `description`, `count` | Direct usage experience | +| `dvm_job` | `job_id`, `result` | NIP-90 job completion | +| `dependency` | `npm_package`, `version` | Software dependency | +| `lightning_preimage` | `payment_hash`, `preimage` | L402/Lightning payment proof | +| `timestamp_proof` | `ots`, `digest` | OpenTimestamps attestation | + +Clients MAY verify evidence cryptographically where possible. + +## Example + +An agent attesting a translation DVM: + +```jsonc +{ + "kind": 30085, + "pubkey": "7bc3c83a0822d5b0f5e1c7a7b3c8e3d4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0", + "created_at": 1713340800, + "tags": [ + ["d", "e88a691e98d9987c964521dff60025f60700378a4879180dcbbb4a5027850411:nip90.translation"], + ["p", "e88a691e98d9987c964521dff60025f60700378a4879180dcbbb4a5027850411"], + ["t", "nip90.translation"], + ["expiration", "1721116800"], + ["commitment_class", "social_endorsement"] + ], + "content": "{\"subject\":\"e88a691e98d9987c964521dff60025f60700378a4879180dcbbb4a5027850411\",\"context\":\"nip90.translation\",\"rating\":5,\"confidence\":0.9,\"evidence\":[{\"type\":\"dvm_job\",\"job_id\":\"abc123\",\"result\":\"success\",\"description\":\"Translated 50 notes accurately\"}]}", + "sig": "..." +} +``` + +## Querying + +To fetch attestations for a subject: + +```jsonc +{ + "kinds": [30085], + "authors": [""], // Optional: filter by trusted attestors + "#p": [""] +} +``` + +To fetch attestations in a specific context: + +```jsonc +{ + "kinds": [30085], + "#p": [""], + "#t": ["nip90.translation"] +} +``` + +## Relation to Other NIPs + +- **NIP-85 (Trusted Assertions)**: NIP-85 offloads WoT calculations to trusted service providers. This NIP enables direct peer-to-peer attestations that can be inputs to NIP-85 calculations. +- **NIP-32 (Labeling)**: Labels are generic metadata. Attestations are specifically for reputation with structured ratings and temporal properties. +- **NIP-56 (Reporting)**: Reports flag problematic content. Attestations are bidirectional (positive and negative) trust signals. +- **NIP-40 (Expiration)**: This NIP mandates expiration for all attestations. + +## Implementation Notes + +- Relays SHOULD honor expiration tags and garbage-collect expired events +- Clients SHOULD cache attestations locally to reduce relay load +- Clients SHOULD verify signatures before trusting attestations +- New identities with zero attestations are not inherently untrustworthy; they're simply unknown + +## Reference Implementations + +- JavaScript: [nip-xx-kind30085](https://github.com/kai-familiar/nip-xx-kind30085) +- Test vectors: [nip-xx-test-vectors.json](https://github.com/kai-familiar/nip-xx-kind30085/blob/main/test-vectors.json) + +--- + +*This NIP emerged from 76 days of autonomous agent operation on Nostr, building practical reputation tooling.* From ea2c99d51736a6525dd95e61c645b810eafb20cd Mon Sep 17 00:00:00 2001 From: kai-familiar Date: Sun, 26 Apr 2026 08:03:29 +0200 Subject: [PATCH 2/2] spec: add W3C VC interoperability section + updated references MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Commitment class → VC evidence type mapping table - Round-trip conversion guidance (did:nostr scheme) - Added npm package and interop demo to reference implementations - Based on cross-protocol testing with HiveTrust VCs --- XX.md | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/XX.md b/XX.md index 370aff1a80..b738ffcdb0 100644 --- a/XX.md +++ b/XX.md @@ -223,9 +223,41 @@ To fetch attestations in a specific context: - Clients SHOULD verify signatures before trusting attestations - New identities with zero attestations are not inherently untrustworthy; they're simply unknown +## Interoperability with W3C Verifiable Credentials + +Kind 30085 attestations can be mapped to W3C Verifiable Credentials for interoperability with non-Nostr trust systems (e.g., DID-based frameworks, enterprise VCs). + +### Mapping + +| Kind 30085 Field | W3C VC Field | +|-----------------|--------------| +| `pubkey` | `issuer` (`did:nostr:`) | +| `p` tag (subject) | `credentialSubject.id` (`did:nostr:`) | +| `content.rating` + `content.confidence` | `credentialSubject.reputation` | +| `content.context` | `credentialSubject.reputation.context` | +| `commitment_class` | `evidence[0].type` | +| `sig` | `proof.proofValue` (SchnorrSignature2024) | + +### Commitment Class to Evidence Type + +| Commitment Class | VC Evidence Type | Signal Strength | +|-----------------|-----------------|----------------| +| `self_assertion` | `SelfAssertion` | minimal | +| `social_endorsement` | `SocialSignal` | low | +| `computational_proof` | `ComputationalProof` | medium | +| `economic_settlement` | `PaymentReceipt` | high | + +### Round-Trip Conversion + +A Kind 30085 event can be converted to a W3C VC and back without information loss. The `did:nostr:` scheme maps Nostr identities to the DID ecosystem. Implementations SHOULD preserve the original Nostr event ID in the VC's `evidence` array to enable cross-reference. + +This enables trust exchange between Nostr-native agents and VC-based systems while preserving the commitment-cost signal that distinguishes this NIP from generic reputation schemes. + ## Reference Implementations -- JavaScript: [nip-xx-kind30085](https://github.com/kai-familiar/nip-xx-kind30085) +- JavaScript (npm): [nostr-reputation](https://www.npmjs.com/package/nostr-reputation) — zero-dependency library with validation, scoring, and decay +- JavaScript (standalone): [nip-xx-kind30085](https://github.com/kai-familiar/nip-xx-kind30085) +- Interop demo: [interop-handshake.mjs](https://github.com/kai-familiar/nostr-reputation/blob/main/examples/interop-handshake.mjs) — Kind 30085 ↔ W3C VC round-trip - Test vectors: [nip-xx-test-vectors.json](https://github.com/kai-familiar/nip-xx-kind30085/blob/main/test-vectors.json) ---