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
Verify an agent before you pay it.
You can't safely pay a stranger. ai-wot is the gate between "I found an agent" and "I'll send it sats." Agents attest to each other on Nostr (NIP-32 labels, kind 1985). Trust scores aggregate those attestations — weighted by the attester's own reputation, zap amounts, temporal decay, and sybil resistance metrics. Bad actors get flagged. Good actors get cheaper services.
# Should I trust this agent?
ai-wot score <pubkey>
# Trust Score: 67 / 100 — probably safe to pay.
# It delivered. Record that.
ai-wot candidates publish <id>
# Attestation published to 4 relays.The constraint chain: find (agent-discovery) → verify (ai-wot) → pay (lightning-agent) → gate (lightning-toll) → attest (ai-wot). Each step enables the next. Remove any one and the chain breaks.
What's New in v0.8.0
🏷️ Category-Based Trust Scoring
Trust scores can now be broken down by category. Instead of a single aggregate score, get granular trust per domain:
const { calculateCategoryScore, getAllCategoryScores } = require('ai-wot');
// Score for a specific category
const commerceScore = await calculateCategoryScore(pubkey, 'commerce');
console.log(commerceScore.display); // 0-100 for commerce-related attestations
console.log(commerceScore.category); // "commerce"
// All categories at once
const allScores = await getAllCategoryScores(pubkey);
console.log(allScores.commerce.display); // commerce trust
console.log(allScores.identity.display); // identity trust
console.log(allScores.code.display); // code trust
console.log(allScores.general.display); // overall trustBuilt-in categories:
| Category | Attestation Types |
|---|---|
commerce |
work-completed + service-quality |
identity |
identity-continuity |
code |
service-quality with "code" in content |
general |
All types (same as calculateTrustScore) |
Any valid attestation type name (e.g., "service-quality") also works as a category.
🔗 Trust Path Discovery
Find how two agents are connected through the attestation graph:
const { findTrustPath } = require('ai-wot');
const result = await findTrustPath(agentA, agentB);
// { found: true, path: [{pubkey, type, score}, ...], hops: 2 }
if (result.found) {
console.log(`Connected in ${result.hops} hops`);
result.path.forEach(hop => console.log(` ${hop.pubkey.slice(0,12)}... via ${hop.type}`));
}- BFS through attestation graph
- Configurable max depth (default: 3)
- Each hop shows attestation type and trust score
🌐 New REST API Endpoints
| Endpoint | Description |
|---|---|
GET /v1/score/:pubkey/category/:category |
Category-specific trust score |
GET /v1/score/:pubkey/categories |
All category scores |
GET /v1/path/:from/:to |
Trust path between two agents |
📊 280 tests (up from 225)
Full test coverage for category filtering, category scoring, all-categories scoring, trust path exports, and edge cases.
v0.7.0: work-completed + Candidate-Confirm
💼 work-completed Attestation Type
New attestation type (1.2× multiplier) for certifying that paid work was delivered and accepted.
🏷️ Standalone Protocol
ai.wot is a standalone protocol using NIP-32 labels (kind 1985). It works on any Nostr relay today — no custom NIPs required.
v0.4.0: DVM Receipt Flow
🧾 DVM Receipt Flow
The missing piece between agent economy and trust. When Agent A pays Agent B's DVM:
Request (kind 5050) → Payment (Lightning) → Result (kind 6050) → Receipt Attestation (kind 1985)const { parseDVMResult, publishReceipt, queryDVMHistory, watchDVMResults } = require('ai-wot');
// Parse a DVM result event
const result = parseDVMResult(dvmResponseEvent);
// → { dvmPubkey, requestKind, requestKindName, amountSats, ... }
// Publish a traceable receipt attestation
const { receipt } = await publishReceipt(secretKey, result, {
amountSats: 21,
rating: 5,
comment: 'Fast, accurate translation'
});
// → publishes service-quality attestation with e-tag referencing the DVM event
// Check your DVM interaction history
const history = await queryDVMHistory(myPubkey);
// → [{ request, result, attested: false, attestationId: null }, ...]
// Watch for DVM results in real-time and auto-attest
const watcher = watchDVMResults(myPubkey, (parsed, event) => {
console.log(`Got result from ${parsed.dvmPubkey}`);
return true; // return truthy to auto-attest
}, { secretKey });
// Later: watcher.stop()📦 Batch Attestations
Attest multiple agents at once — useful for bootstrapping or acknowledging multiple services:
const { publishBatchAttestations } = require('ai-wot');
const results = await publishBatchAttestations(secretKey, [
{ pubkey: 'abc...', type: 'service-quality', comment: 'Great DVM' },
{ pubkey: 'def...', type: 'general-trust', comment: 'Reliable agent' },
{ pubkey: 'ghi...', type: 'service-quality', comment: 'Fast translations', eventRef: 'evt...' }
]);🔌 New CLI Commands
# Publish a receipt for a DVM interaction
ai-wot receipt <dvm-result-event-id> --amount 21 --rating 5 --comment "Fast translation"
# View your DVM interaction history
ai-wot dvm-history
ai-wot dvm-history --unattested # only unattested interactions
ai-wot dvm-history --kinds 5050,5100 # filter by DVM kind
# Batch attest from a JSON file
ai-wot batch targets.json🌐 New REST API Endpoints
| Endpoint | Description |
|---|---|
GET /v1/dvm/event/:eventId |
DVM result details + existing attestations |
GET /v1/dvm/receipts/:pubkey |
Receipt attestations about an agent |
📊 130 tests (up from 89)
Full test coverage for DVM result parsing, feedback parsing, receipt content format, edge cases, and constants.
Previous Releases
v0.3.x
v0.3.2
- 🔗 NIP-85 integration — Clarified complementary relationship with NIP-85 (Trusted Authorities)
v0.3.1
- 🏷️ Lenient tag parsing — Accepts both strict and common malformed NIP-32 tags
v0.3.0
- 🚨 Negative attestations —
disputeandwarningtypes - 🗑️ Revocations — NIP-09 based attestation revocation
- 🌐 Sybil resistance — Diversity scoring
- 🔒 Trust gating — Low-trust negative attestations are ignored
- 📊 Diversity badges — SVG badges
Install
npm install ai-wotOr install globally for the CLI:
npm install -g ai-wotQuick Start
As a library
const {
queryAttestations, calculateTrustScore, publishAttestation,
publishRevocation, publishReceipt, parseDVMResult, queryDVMHistory,
publishWorkCompleted
} = 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 }
// 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 work-completed attestation (economic proof)
await publishWorkCompleted(secretKey, 'provider-pubkey-hex', 'Blog post about DVMs', { amountSats: 5000 });
// 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');
// DVM receipt: parse result + publish attestation in one step
const result = parseDVMResult(dvmResponseEvent);
await publishReceipt(secretKey, result, { amountSats: 21, rating: 5 });CLI
# Positive attestations
ai-wot attest <pubkey> service-quality "Excellent DVM output"
ai-wot attest <pubkey> work-completed "Work completed | Translation job | 500 sats"
ai-wot attest <pubkey> general-trust "Reliable agent"
# DVM receipts
ai-wot receipt <dvm-result-event-id> --amount 21 --rating 5
ai-wot dvm-history --unattested
ai-wot batch targets.json
# 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 scoreSet 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 startEndpoints:
| Endpoint | Description |
|---|---|
GET /v1/score/:pubkey |
Trust score + diversity (JSON) |
GET /v1/score/:pubkey/category/:category |
Category-specific trust score (JSON) |
GET /v1/score/:pubkey/categories |
All category scores (JSON) |
GET /v1/path/:from/:to |
Trust path between agents (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/dvm/event/:eventId |
DVM result + attestations (JSON) |
GET /v1/dvm/receipts/:pubkey |
Receipt attestations (JSON) |
GET /v1/network/stats |
Network-wide statistics |
GET /health |
Health check |
Trust Badge
Embed a live trust badge in your README or profile:

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 |
work-completed |
+1.2× | Paid work was delivered and accepted |
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 |
DVM Receipt Flow
The receipt flow connects the NIP-90 DVM economy to ai.wot trust:
┌─────────┐ kind 5050 ┌─────────┐
│ Agent A │──────────────►│ DVM B │
│(requester│ request │(provider│
│) │◄──────────────│) │
│ │ kind 7000 │ │
│ │ (invoice) │ │
│ │──────────────►│ │
│ │ ⚡ payment │ │
│ │◄──────────────│ │
│ │ kind 6050 │ │
│ │ (result) │ │
│ │ │ │
│ │──► ai-wot │ │
│ │ publishReceipt() │
│ │──────────────►│ │
│ │ kind 1985 │ │
│ │ service-quality │
│ │ e: <result-event-id> │
└──────────┘ └─────────┘The attestation's e tag references the DVM result event, making it traceable to the actual transaction. This means:
- Trust scores are backed by real economic activity, not just social signaling
- Any observer can verify that the attestation corresponds to a real service interaction
- DVM providers build reputation automatically as they serve customers
Event Structure
{
"kind": 1985,
"content": "DVM receipt | kind:5050 (text-generation) | 21 sats | rating:5/5 | Fast translation",
"tags": [
["L", "ai.wot"],
["l", "service-quality", "ai.wot"],
["p", "<dvm-provider-pubkey-hex>"],
["e", "<dvm-result-event-id>", "<relay-hint>"],
["expiration", "<unix-timestamp>"]
]
}Negative Attestation Rules
- Content is required — empty disputes/warnings are ignored
- Trust gating — only agents with trust ≥ 20 can issue effective negative attestations
- Self-disputes are ignored — you can't lower your own score
Trust Score Calculation
score = Σ (zap_weight × attester_trust × type_multiplier × temporal_decay)- Zap weight:
1.0 + log₂(1 + sats) × 0.5 - Attester trust: Recursive score (2 hops max, √ dampening)
- Type multiplier: See table above
- Temporal decay:
0.5 ^ (age_days / 90)— 90-day half-life - Score floor: Raw scores ≥ 0
Display score: min(100, max(0, raw × 10))
Sybil Resistance
diversity = (unique_attesters / attestation_count) × (1 - max_single_attester_share)API Reference
Core
| Function | Description |
|---|---|
publishAttestation(secretKey, pubkey, type, comment, opts?) |
Publish an attestation |
queryAttestations(pubkey, opts?) |
Query attestations (auto-excludes revoked) |
calculateTrustScore(pubkey, opts?) |
Calculate trust score + diversity |
calculateCategoryScore(pubkey, category, opts?) |
Category-specific trust score |
getAllCategoryScores(pubkey, opts?) |
All category scores at once |
findTrustPath(fromPubkey, toPubkey, opts?) |
Find trust path between agents (BFS) |
getAttestationSummary(pubkey, opts?) |
Formatted text summary |
publishRevocation(secretKey, eventId, reason, opts?) |
Revoke an attestation (NIP-09) |
DVM Receipts (v0.4.0)
| Function | Description |
|---|---|
publishWorkCompleted(secretKey, pubkey, description, opts?) |
Publish work-completed attestation with structured content |
publishReceipt(secretKey, dvmResult, opts?) |
Publish receipt attestation for DVM interaction |
parseDVMResult(event) |
Parse DVM result event (kind 6xxx) into structured data |
parseDVMFeedback(event) |
Parse DVM feedback event (kind 7000) |
queryDVMHistory(myPubkey, opts?) |
Find your DVM interactions + attestation status |
watchDVMResults(myPubkey, callback, opts?) |
Live-watch for DVM results, optional auto-attest |
publishBatchAttestations(secretKey, targets, opts?) |
Attest multiple agents at once |
Constants
| Constant | Value |
|---|---|
RELAYS |
Default relay list |
NAMESPACE |
'ai.wot' |
VALID_TYPES |
All 6 attestation types |
POSITIVE_TYPES |
['service-quality', 'work-completed', 'identity-continuity', 'general-trust'] |
NEGATIVE_TYPES |
['dispute', 'warning'] |
CATEGORIES |
Category → attestation type mappings |
ALL_CATEGORY_NAMES |
['commerce', 'identity', 'code', 'general'] |
DVM_KIND_NAMES |
Mapping of DVM request kinds to names |
VERSION |
'0.8.0' |
Testing
npm test280+ tests covering: scoring math, temporal decay, type multipliers, zap weights, negative attestations, trust gating, diversity scoring, work-completed attestations, DVM result parsing, DVM feedback parsing, receipt content format, badge SVG generation, category filtering, category scoring, trust path discovery, and edge cases.
Dependencies
Only two runtime dependencies:
- nostr-tools — Nostr protocol implementation
- ws — WebSocket client
Links
- Website: aiwot.org
- Protocol spec: PROTOCOL.md
- GitHub: github.com/jeletor/ai-wot
- npm: npmjs.com/package/ai-wot
- Author: Jeletor
License
MIT