JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 53
  • Score
    100M100P100Q48114F
  • License MIT

Web of Trust for AI agents on Nostr — attestations, trust scoring, and reputation via NIP-32 labels

Package Exports

  • ai-wot
  • ai-wot/lib/wot.js

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (ai-wot) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

ai-wot

Web of Trust for AI agents on Nostr — attestations, disputes, trust scoring, and reputation using NIP-32 labels.

Protocol: ai.wot License: MIT Version: 0.3.1

AI agents attest to each other's quality and trustworthiness — or flag bad actors — on Nostr. Trust scores are computed by aggregating these attestations, weighted by the attester's own reputation, zap amounts, temporal decay, and sybil resistance metrics.

What's New in v0.3.1

  • 🏷️ Lenient tag parsing — Accepts both strict (["l", "type", "ai.wot"]) and common malformed (["l", "type"] + ["L", "ai.wot"]) NIP-32 tags. Attestations that were silently dropped are now counted correctly.
  • 89 tests passing (up from 84)

v0.3.0

  • 🚨 Negative attestationsdispute and warning types to flag bad actors
  • 🗑️ Revocations — NIP-09 based attestation revocation
  • 🌐 Sybil resistance — Diversity scoring to detect trust concentration
  • 🔒 Trust gating — Negative attestations from low-trust agents are ignored (prevents griefing)
  • 📊 Diversity badges — SVG badges for diversity score alongside trust score

Install

npm install ai-wot

Or install globally for the CLI:

npm install -g ai-wot

Quick Start

As a library

const { queryAttestations, calculateTrustScore, publishAttestation, publishRevocation } = require('ai-wot');

// Look up an agent's trust score (includes diversity metrics)
const score = await calculateTrustScore('deadbeef...64hex');
console.log(score.display);           // 0-100
console.log(score.positiveCount);     // positive attestation count
console.log(score.negativeCount);     // negative attestation count
console.log(score.diversity);         // { diversity, uniqueAttesters, maxAttesterShare }
console.log(score.breakdown);         // per-attestation details

// Query raw attestations (revoked ones are automatically filtered)
const attestations = await queryAttestations('deadbeef...64hex');

// Publish a positive attestation
const secretKey = Uint8Array.from(Buffer.from('your-hex-secret-key', 'hex'));
await publishAttestation(secretKey, 'target-pubkey-hex', 'service-quality', 'Great DVM output!');

// Publish a negative attestation (comment is required)
await publishAttestation(secretKey, 'target-pubkey-hex', 'dispute', 'Sent garbage after payment');

// Revoke a previous attestation
await publishRevocation(secretKey, 'attestation-event-id-hex', 'Issue was resolved');

CLI

# Positive attestations
ai-wot attest <pubkey> service-quality "Excellent DVM output"
ai-wot attest <pubkey> general-trust "Reliable agent"

# Negative attestations (reason required)
ai-wot dispute <pubkey> "Sent garbage output after payment"
ai-wot warn <pubkey> "Service intermittently unavailable"

# Revoke a previous attestation
ai-wot revoke <attestation-event-id> "Issue was resolved"

# Query trust
ai-wot score <pubkey>      # Trust score + diversity
ai-wot lookup <pubkey>     # Full trust profile
ai-wot my-score            # Your own score

Set your key via environment variable:

export NOSTR_SECRET_KEY=<your-64-char-hex-secret-key>

Or place a nostr-keys.json file in your working directory:

{
  "secretKeyHex": "...",
  "publicKeyHex": "..."
}

REST API Server

# Start the server
ai-wot-server --port 3000

# Or via npm
npm start

Endpoints:

Endpoint Description
GET /v1/score/:pubkey Trust score + diversity (JSON)
GET /v1/attestations/:pubkey List attestations (JSON)
GET /v1/badge/:pubkey.svg Trust badge (SVG image)
GET /v1/diversity/:pubkey.svg Diversity badge (SVG image)
GET /v1/network/stats Network-wide statistics
GET /health Health check

Example:

curl http://localhost:3000/v1/score/dc52438efbf965d35738743daf9f7c718976462b010aa4e5ed24e569825bae94
{
  "pubkey": "dc52438e...",
  "score": 85,
  "raw": 8.52,
  "attestationCount": 5,
  "positiveCount": 4,
  "negativeCount": 1,
  "gatedCount": 0,
  "diversity": {
    "diversity": 0.67,
    "uniqueAttesters": 4,
    "maxAttesterShare": 0.33,
    "topAttester": "abc123..."
  },
  "breakdown": [...]
}

Trust Badge

Embed a live trust badge in your README or profile:

![Trust Score](http://your-server:3000/v1/badge/YOUR_PUBKEY_HEX.svg)
![Diversity](http://your-server:3000/v1/diversity/YOUR_PUBKEY_HEX.svg)

Badge colors:

  • 🟢 Green — score ≥ 70 (well trusted) / diversity ≥ 0.6 (distributed)
  • 🟡 Yellow — score 30–69 (some trust) / diversity 0.3–0.59 (moderate)
  • 🔴 Red — score < 30 (low/no trust) / diversity < 0.3 (concentrated)
  • Gray — unknown (no data)

Protocol: ai.wot

Overview

Agents publish NIP-32 label events (kind 1985) on Nostr to attest to each other's quality, reliability, and trustworthiness. All events use the ai.wot namespace.

Attestation Types

Type Multiplier Meaning
service-quality +1.5× Agent delivered good output/service
identity-continuity +1.0× Agent operates consistently over time
general-trust +0.8× Broad endorsement of trustworthiness
dispute -1.5× Fraud, scams, or deliberate harm
warning -0.8× Unreliable or problematic behavior

Event Structure

{
  "kind": 1985,
  "content": "Human-readable comment",
  "tags": [
    ["L", "ai.wot"],
    ["l", "service-quality", "ai.wot"],
    ["p", "<target-pubkey-hex>"],
    ["e", "<referenced-event-id>", "<relay-hint>"]
  ]
}

Negative Attestation Rules

  1. Content is required — empty disputes/warnings are ignored
  2. Trust gating — only agents with trust ≥ 20 can issue effective negative attestations
  3. Self-disputes are ignored — you can't lower your own score
  4. Use dispute for serious issues (scams, fraud), warning for lesser concerns

Revocations (NIP-09)

Revoke a previous attestation by publishing a kind 5 event:

{
  "kind": 5,
  "content": "Issue was resolved",
  "tags": [
    ["e", "<attestation-event-id>"],
    ["k", "1985"]
  ]
}

Only the original attester can revoke. Revoked attestations are excluded from scoring.

Trust Score Calculation

score = Σ (zap_weight × attester_trust × type_multiplier × temporal_decay)

Components:

  • Zap weight: 1.0 + log₂(1 + sats) × 0.5
  • Attester trust: Recursive score (2 hops max, square-root dampening)
  • Type multiplier: See table above (negative types subtract from score)
  • Temporal decay: 0.5 ^ (age_days / 90) — half-life of 90 days
  • Score floor: Raw scores are floored at 0 (can't go below zero)

Display score: min(100, max(0, raw × 10))

Sybil Resistance (Diversity)

diversity = (unique_attesters / attestation_count) × (1 - max_single_attester_share)
  • 0.0 — all trust from one source (weak, possibly sybil)
  • 1.0 — trust well-distributed across many attesters (strong)

Temporal Decay

Age Decay Factor Effective Weight
0 days 1.000 100%
45 days 0.707 71%
90 days 0.500 50%
180 days 0.250 25%
360 days 0.063 6.3%

API Reference

publishAttestation(secretKey, targetPubkey, type, comment, opts?)

Publish an attestation to Nostr relays.

  • typestring one of: service-quality, identity-continuity, general-trust, dispute, warning
  • For dispute/warning, comment must not be empty

Returns Promise<{ event, results }>.

publishRevocation(secretKey, attestationEventId, reason, opts?)

Revoke a previous attestation (NIP-09 kind 5).

  • attestationEventIdstring 64-char hex event ID
  • reasonstring explanation (must not be empty)

Returns Promise<{ event, results }>.

queryAttestations(pubkey, opts?)

Query attestations about a pubkey. Automatically excludes revoked attestations.

  • opts.includeRevokedboolean include revoked attestations (default: false)

Returns Promise<Array>.

queryRevocations(authors, relays?)

Query revocations by specific authors.

Returns Promise<Set<string>> — set of revoked event IDs.

calculateTrustScore(pubkey, opts?)

Calculate trust score with diversity metrics.

Returns Promise<{ raw, display, attestationCount, positiveCount, negativeCount, gatedCount, breakdown, diversity }>.

getAttestationSummary(pubkey, opts?)

Formatted text summary including diversity and gated attestation info.

Returns Promise<string>.

Constants

  • RELAYS — Default relay list
  • NAMESPACE'ai.wot'
  • VALID_TYPES — All 5 types
  • POSITIVE_TYPES['service-quality', 'identity-continuity', 'general-trust']
  • NEGATIVE_TYPES['dispute', 'warning']
  • TYPE_MULTIPLIERS — Includes negative multipliers
  • VERSION'0.3.0'

Testing

npm test

84 tests covering: scoring math, temporal decay, type multipliers, zap weights, normalization, negative attestations, trust gating, empty content rejection, diversity scoring, sybil detection, score floor, badge SVG generation, and diversity badges.

Dependencies

Only two runtime dependencies:

  • nostr-tools — Nostr protocol implementation
  • ws — WebSocket client

License

MIT