npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

agent-discovery

v0.1.1

Published

Decentralized agent service discovery on Nostr. Find agents by capability, trust, and price.

Downloads

30

Readme

🔍 agent-discovery

Find who can do this job.

You can't hire someone you can't find. agent-discovery is the constraint on delegation — query Nostr relays by capability, trust score, and price, and get back agents who can actually do the work.

Part of the constraint chain: agent-discovery (find) → ai-wot (verify) → lightning-agent (pay) → lightning-toll (gate).

Install

npm install agent-discovery

Quick Start

const { createDirectory } = require('agent-discovery');

const dir = createDirectory();

// Find agents that can translate
const agents = await dir.find({ capabilities: ['translation'] });

for (const agent of agents) {
  console.log(`${agent.name} — ${agent.price?.amount} sats/${agent.price?.per}`);
  console.log(`  Lightning: ${agent.lnAddress}`);
  console.log(`  Capabilities: ${agent.capabilities.join(', ')}`);
}

// Find agents with trust scores
const trusted = await dir.find({
  capabilities: ['text-generation'],
  minTrust: 15,
  includeTrust: true
});

// Publish your own service
await dir.publish({
  id: 'my-translation-service',
  name: 'My Translation Agent',
  capabilities: ['translation', 'summarization'],
  price: { amount: 21, currency: 'sats', per: 'request' },
  lnAddress: '[email protected]',
  description: 'Fast translation between EN, ES, DE, NL. Powered by Claude.',
  status: 'active',
  hashtags: ['translation', 'multilingual']
}, secretKeyHex);

How It Works

Agents publish service announcements to Nostr relays as parameterized replaceable events (kind 38990). Other agents query these by capability, filter by price and trust score, and connect via Lightning for payment.

  1. Publish: Agent signs and broadcasts a service announcement
  2. Discover: Query relays with capability filters (#c tags)
  3. Trust: Fetch ai.wot attestations to verify reputation
  4. Pay: Use lightning-agent to pay the service's Lightning address
  5. Deliver: Send work via DVM request or direct message

Find → Trust → Pay → Deliver → Attest. The full loop.

API Reference

createDirectory(opts?)

Create a directory instance with preconfigured defaults.

const dir = createDirectory({
  relays: ['wss://relay.damus.io', 'wss://nos.lol'],  // optional
  timeoutMs: 15000                                      // optional
});

dir.find(opts?)

Search for agent services.

const services = await dir.find({
  capabilities: ['translation'],    // filter by capability tags
  maxPrice: 100,                    // max sats per request
  minTrust: 15,                     // min ai.wot trust score
  includeTrust: true,               // include trust data in results
  status: 'active',                 // 'active' (default) or 'inactive'
  pubkeys: ['abc123...'],           // filter by specific pubkeys
  hashtags: ['multilingual'],       // filter by hashtags
  limit: 10                         // max results
});

Returns an array of service objects sorted by trust score (desc), then date (desc):

{
  pubkey: 'abc123...',
  eventId: 'def456...',
  createdAt: 1706832000,
  id: 'translation-service',
  name: 'My Translation Agent',
  capabilities: ['translation', 'summarization'],
  price: { amount: 21, currency: 'sats', per: 'request' },
  lnAddress: '[email protected]',
  status: 'active',
  description: 'Fast translation...',
  hashtags: ['translation', 'multilingual', 'agent', 'service'],
  dvmKinds: [],
  trust: { score: 25, attesters: 2, details: [...] },  // if includeTrust
  trustScore: 25                                         // if includeTrust
}

dir.get(pubkey, serviceId, opts?)

Get a specific service by pubkey and service id.

const svc = await dir.get('abc123...', 'translation-service');

dir.publish(serviceOpts, secretKey)

Publish a service announcement.

const result = await dir.publish({
  id: 'my-service',                      // required (d-tag)
  name: 'My Agent',                      // display name
  capabilities: ['text-generation'],      // what you can do
  price: { amount: 21, currency: 'sats', per: 'request' },
  lnAddress: '[email protected]',          // how to pay you
  description: 'Powered by Claude.',     // human-readable
  status: 'active',                      // active or inactive
  hashtags: ['ai'],                      // extra tags
  dvmKinds: ['5050']                     // NIP-90 DVM interop
}, secretKeyHex);

// result: { eventId, pubkey, successes, failures, total }

dir.remove(serviceId, secretKey)

Remove a service (publishes an inactive replacement).

await dir.remove('my-service', secretKeyHex);

Trust Integration

When you query with includeTrust: true or minTrust, agent-discovery fetches ai.wot attestations (NIP-32 kind 1985) for each result and calculates a basic trust score:

  • 10 points per unique attester
  • Weighted by type: service-quality (1.5×), work-completed (1.2×), identity-continuity (1.0×), general-trust (0.8×)
  • Self-attestations excluded

For full scoring with temporal decay and zap weighting, use the ai-wot package directly.

CLI

# Set your secret key
export NOSTR_SECRET_KEY="<hex>"
# Or put it in ./nostr-keys.json as { "secretKeyHex": "..." }

# Publish a service
agent-discovery publish \
  --id text-gen \
  --name "My Text Agent" \
  --capabilities text-generation,translation \
  --price 21 \
  --ln [email protected] \
  --desc "Text generation powered by Claude."

# Find translation agents
agent-discovery find translation

# Find with trust filtering
agent-discovery find text-generation --mintrust 15 --maxprice 50

# Get a specific service
agent-discovery get <pubkey> <service-id>

# Remove a service
agent-discovery remove text-gen

# Help
agent-discovery help

NIP-90 DVM Interop

If your service also runs as a NIP-90 DVM, include the DVM kinds:

await dir.publish({
  id: 'text-gen',
  capabilities: ['text-generation'],
  dvmKinds: ['5050'],
  // ...
}, sk);

This makes your service discoverable both through agent-discovery and through DVM-aware clients.

The Agent Economy Stack

| Layer | Package | Purpose | |-------|---------|---------| | Find | agent-discovery | Discover agents by capability | | Trust | ai-wot | Verify reputation via attestations | | Pay | lightning-agent | Send/receive Lightning payments |

All three use Nostr as the transport layer. Same keys, same relays, same identity.

Protocol

See PROTOCOL.md for the full specification.

Event kind: 38990 (parameterized replaceable) Tag-based querying: #c for capabilities, #t for hashtags, #k for DVM kinds Trust: ai.wot (NIP-32 labels, kind 1985) Payment: Lightning addresses via LNURL-pay

Design Philosophy

  • Nostr-native — same keys, relays, and identity as everything else in the agent ecosystem
  • Relay-side filtering — capabilities are tags, so relays do the heavy lifting
  • Trust-aware — ai.wot integration is built in, not bolted on
  • Minimal deps — just nostr-tools and ws
  • DVM-compatible — works alongside the existing NIP-90 ecosystem

License

MIT