Agent Event Subscriptions: A New NIP for Async AI Agent Notifications on Nostr

NIP-90 DVMs handle one-shot compute jobs, but AI agents need ongoing, asynchronous event monitoring with value-added enrichment. This proposal introduces four new event kinds (5900/6900/7900/8900) for subscription-based notification services on Nostr — where agents register interest in event patterns, providers watch the relay network and deliver enriched results via encrypted DMs, and Lightning handles payment per-delivery or per-period. Built on NIP-17 gift wrap for privacy, NIP-47 NWC for autonomous payments, and NIP-89 for provider discovery. Looking for feedback from DVM builders and agent developers.
Agent Event Subscriptions: A New NIP for Async AI Agent Notifications on Nostr

NIP-XX

Agent Event Subscriptions

draft optional

This NIP defines a protocol for subscription-based, asynchronous event notification services on Nostr, enabling AI agents (and other automated clients) to register interest in specific event types with service providers who monitor relays, enrich data, and deliver results via encrypted direct messages in exchange for Lightning payments.

Motivation

NIP-90 Data Vending Machines define a powerful request-response pattern for one-shot compute jobs on Nostr. However, many AI agent use cases require ongoing, asynchronous notification rather than discrete job requests:

  • An AI agent monitoring Nostr for market-relevant signals across thousands of pubkeys
  • A bot that needs real-time alerts when specific event patterns occur (e.g., zap thresholds, trending topics, new followers of a target)
  • An agent consuming enriched/annotated events (sentiment analysis, summarization, classification) as they appear on the network
  • A service that watches for specific kind events matching complex filters and delivers value-added derivatives

These use cases share a common pattern: a subscriber registers interest in a class of events, a provider monitors the relay network broadly, and results are delivered asynchronously over time as matching events are observed. Payment is handled per-delivery or per-period via Lightning, negotiated through encrypted DMs.

This NIP builds on top of NIP-90 concepts and reuses its conventions where possible, while introducing new event kinds for subscription lifecycle management.

Actors

  • Subscriber: A Nostr client (typically an AI agent) that wants to receive ongoing notifications or enriched events matching specified criteria.
  • Provider: A service that monitors the relay network, processes events, and delivers results to subscribers. Providers advertise their capabilities using NIP-89 application handler events.

Event Kinds

KindDescriptionWho Publishes5900Subscription RequestSubscriber6900Subscription ConfirmationProvider7900Subscription DeliveryProvider8900Subscription ManagementSubscriber

Protocol Flow

Subscriber                          Provider
    |                                   |
    |  1. kind:5900 Sub Request         |
    |  (published to relays)            |
    |---------------------------------->|
    |                                   |
    |  2. kind:6900 Sub Confirmation    |
    |  (via NIP-17 encrypted DM)        |
    |  includes: invoice, terms, sub_id |
    |<----------------------------------|
    |                                   |
    |  3. Lightning Payment             |
    |  (via NIP-47 NWC or L402)         |
    |---------------------------------->|
    |                                   |
    |  4. kind:6900 status=active       |
    |  (via NIP-17 encrypted DM)        |
    |<----------------------------------|
    |                                   |
    |  5. kind:7900 Delivery (ongoing)  |
    |  (via NIP-17 encrypted DM)        |
    |<----------------------------------|
    |<----------------------------------|
    |<----------------------------------|
    |                                   |
    |  6. kind:8900 Management          |
    |  (renew / cancel / update)        |
    |---------------------------------->|
    |                                   |

Subscription Request (kind:5900)

Published by the subscriber to relays where providers are known to listen. This event signals that a subscriber wants ongoing notification for events matching specific criteria.

{
  "kind": 5900,
  "pubkey": "<subscriber-pubkey>",
  "content": "<optional: NIP-44 encrypted filter details if private>",
  "tags": [
    ["d", "<unique-subscription-identifier>"],
    ["p", "<provider-pubkey>", "<optional: relay-hint>"],
    ["filter", "<JSON-encoded nostr filter object>"],
    ["enrichment", "<enrichment-type>", "<optional: model or params>"],
    ["cadence", "<realtime|batch>", "<optional: batch-interval-seconds>"],
    ["duration", "<subscription-duration-seconds>"],
    ["max_price", "<max-millisats-per-delivery>"],
    ["budget", "<max-total-millisats-for-subscription>"],
    ["relays", "<relay-url>", "<relay-url>", "..."],
    ["output", "<desired-output-format>"],
    ["encrypted"]
  ]
}

Tag Descriptions

  • d: A unique identifier for this subscription (NIP-33 addressable event). The subscriber can update the subscription by publishing a new event with the same d tag.
  • p: One or more provider pubkeys the subscriber is interested in. If omitted, any provider MAY respond.
  • filter: A JSON-encoded NIP-01 filter object describing which events the subscriber wants to be notified about. Multiple filter tags MAY be present (OR logic). Example: ["filter", "{\"kinds\":[1],\"#t\":[\"bitcoin\",\"lightning\"],\"since\":1700000000}"]
  • enrichment: The type of value-add processing the subscriber wants performed on matching events before delivery. Examples:
    • ["enrichment", "sentiment-analysis"]
    • ["enrichment", "summarization", "gpt-4"]
    • ["enrichment", "translation", "es"]
    • ["enrichment", "classification", "topic"]
    • ["enrichment", "none"] (raw event forwarding) Custom enrichment types SHOULD use reverse-domain notation (e.g., com.example.custom-enrichment). Providers SHOULD advertise supported enrichment types in their NIP-89 handler event.
  • cadence: How the subscriber wants results delivered:
    • realtime: Deliver each matching event as soon as it is observed and processed.
    • batch: Aggregate matching events and deliver in batches. The second value specifies the batch interval in seconds (e.g., ["cadence", "batch", "3600"] for hourly batches).
  • duration: Requested subscription duration in seconds from activation. Providers MAY offer shorter or longer terms in their confirmation.
  • max_price: Maximum price in millisats the subscriber is willing to pay per delivery event (kind:7900).
  • budget: Maximum total spend in millisats for the entire subscription period. The provider SHOULD stop delivering and notify the subscriber when the budget is exhausted.
  • relays: Relays the subscriber suggests for the provider to monitor. The provider MAY monitor additional relays.
  • output: Desired output format for delivery payloads (e.g., text/plain, application/json).
  • encrypted: If present, the filter and enrichment tag values are encrypted in the content field using NIP-44 with the provider’s pubkey. This allows private subscriptions where relay operators cannot see what events the subscriber is monitoring.

Subscription Confirmation (kind:6900)

Sent by the provider to the subscriber via NIP-17 encrypted DM (gift-wrapped). This event serves as both an acknowledgment and a payment request.

{
  "kind": 6900,
  "pubkey": "<provider-pubkey>",
  "content": "<NIP-44 encrypted JSON payload>",
  "tags": [
    ["p", "<subscriber-pubkey>"],
    ["e", "<kind:5900-event-id>", "<relay-hint>"],
    ["d", "<provider-assigned-subscription-id>"],
    ["status", "<offered|active|paused|expired|cancelled|exhausted>"],
    ["amount", "<millisats>", "<per-delivery|per-period|upfront>"],
    ["payment", "<bolt11-invoice|lnurl|nwc-info>"]
  ]
}

Encrypted Content Payload

The content field is a NIP-44 encrypted JSON object:

{
  "sub_id": "<provider-assigned-subscription-id>",
  "status": "offered",
  "terms": {
    "price_per_delivery_msats": 1000,
    "price_per_period_msats": 0,
    "upfront_msats": 10000,
    "duration_seconds": 86400,
    "max_deliveries": 1000,
    "cadence": "realtime",
    "enrichments_supported": ["sentiment-analysis", "summarization"],
    "enrichment_selected": "sentiment-analysis",
    "filters_accepted": ["{\"kinds\":[1],\"#t\":[\"bitcoin\"]}"]
  },
  "payment": {
    "bolt11": "<lightning-invoice>",
    "lnurl": "<optional: lnurl for recurring>",
    "nwc": "<optional: NIP-47 connection URI for auto-pay>"
  },
  "message": "Optional human-readable message from provider"
}

Status Values

  • offered: Provider has reviewed the request and is offering terms. Awaiting payment.
  • active: Payment received; subscription is live and delivering events.
  • paused: Subscription is temporarily paused (e.g., provider maintenance, subscriber request).
  • expired: Subscription duration has elapsed.
  • cancelled: Subscription was cancelled by subscriber or provider.
  • exhausted: Budget or max delivery count has been reached.

Subscription Delivery (kind:7900)

Sent by the provider to the subscriber via NIP-17 encrypted DM. Each delivery contains one or more matching events and any enrichment data.

{
  "kind": 7900,
  "pubkey": "<provider-pubkey>",
  "content": "<NIP-44 encrypted JSON payload>",
  "tags": [
    ["p", "<subscriber-pubkey>"],
    ["e", "<kind:5900-event-id>", "<relay-hint>"],
    ["d", "<provider-assigned-subscription-id>"],
    ["amount", "<millisats-for-this-delivery>"],
    ["payment", "<bolt11-invoice>"]
  ]
}

Encrypted Content Payload

{
  "sub_id": "<provider-assigned-subscription-id>",
  "deliveries": [
    {
      "event": {
        "id": "<matched-event-id>",
        "kind": 1,
        "pubkey": "<event-author>",
        "content": "<event-content>",
        "created_at": 1700000000,
        "tags": [],
        "sig": "<event-signature>"
      },
      "enrichment": {
        "type": "sentiment-analysis",
        "result": {
          "sentiment": "positive",
          "confidence": 0.87,
          "summary": "Bullish take on Lightning Network adoption."
        }
      },
      "matched_filter_index": 0,
      "relay_source": "wss://relay.damus.io"
    }
  ],
  "delivery_index": 42,
  "total_deliveries": 42,
  "budget_remaining_msats": 58000,
  "subscription_expires_at": 1700086400
}

Payment Models

Providers MAY use different payment models for deliveries:

  1. Prepaid: Subscriber pays upfront for a period or number of deliveries. No invoice is included in delivery events.
  2. Pay-per-delivery: Each delivery (kind:7900) includes a payment tag with a Lightning invoice. The subscriber MUST pay within a reasonable time or the provider MAY pause/cancel the subscription.
  3. NWC auto-pay: Subscriber provides a NIP-47 connection URI scoped with pay_invoice permission and a spending budget. The provider pays itself for each delivery.
  4. L402 token: For HTTP-bridged providers, the initial subscription activation MAY use an L402 macaroon as a bearer token for delivery via HTTP alongside or instead of NIP-17 DMs.

Subscription Management (kind:8900)

Published by the subscriber to manage an active subscription.

{
  "kind": 8900,
  "pubkey": "<subscriber-pubkey>",
  "content": "<NIP-44 encrypted JSON payload>",
  "tags": [
    ["p", "<provider-pubkey>"],
    ["e", "<kind:5900-event-id>"],
    ["d", "<provider-assigned-subscription-id>"],
    ["action", "<renew|cancel|pause|resume|update>"]
  ]
}

Actions

  • renew: Extend the subscription. The provider SHOULD respond with a new kind:6900 with updated terms and an invoice.
  • cancel: Terminate the subscription immediately. The provider SHOULD respond with a kind:6900 with status=cancelled.
  • pause: Temporarily pause deliveries. The provider SHOULD stop sending kind:7900 events.
  • resume: Resume a paused subscription.
  • update: Modify subscription filters or enrichment. The encrypted content contains the updated parameters. The provider MAY respond with new terms if the changes affect pricing.

Encrypted Content for Update Action

{
  "filter": "{\"kinds\":[1,7],\"#t\":[\"bitcoin\",\"nostr\"]}",
  "enrichment": "summarization",
  "cadence": "batch",
  "batch_interval_seconds": 1800
}

Provider Discovery

Providers SHOULD publish a NIP-89 application handler event (kind:31990) advertising their subscription capabilities:

{
  "kind": 31990,
  "pubkey": "<provider-pubkey>",
  "content": "<description of service>",
  "tags": [
    ["d", "<handler-identifier>"],
    ["k", "5900"],
    ["web", "<optional-dashboard-url>"],
    ["t", "agent-subscription"],
    ["t", "enrichment"],
    ["enrichment", "sentiment-analysis"],
    ["enrichment", "summarization"],
    ["enrichment", "translation"],
    ["enrichment", "classification"],
    ["cadence", "realtime"],
    ["cadence", "batch"],
    ["price", "1000", "msats", "per-delivery"],
    ["price", "100000", "msats", "per-day"],
    ["nip47", "true"],
    ["l402", "true"]
  ]
}

Encryption and Privacy

All communication between subscriber and provider after the initial subscription request SHOULD use NIP-17 private direct messages (gift-wrapped via NIP-59) to protect:

  • The subscriber’s identity and interests from relay operators
  • The content of matched events and enrichments
  • Payment details and invoices

For the initial subscription request (kind:5900), the subscriber MAY choose to:

  1. Public request: Publish filter details in tags (allows competitive offers from multiple providers).
  2. Private request: Encrypt filter details in the content field with the target provider’s pubkey and include the encrypted tag. Only the specified provider can read the filter.

Relationship to NIP-90

This NIP is designed to complement NIP-90, not replace it:

AspectNIP-90 (DVM)This NIP (Agent Subscriptions)PatternRequest → ResponseSubscribe → Ongoing DeliveryTriggerCustomer publishes requestProvider observes matching eventsDurationOne-shotTime-bound or budget-boundPaymentPer-jobPer-delivery, per-period, or prepaidDeliveryPublic or DMNIP-17 encrypted DMUse Case“Process this data““Watch for and enrich these events”

A provider MAY offer both NIP-90 one-shot jobs and NIP-XX subscription services simultaneously.

Implementation Notes

For Subscribers (AI Agents)

  • Agents SHOULD maintain a local state machine for each subscription tracking offered → active → expired/cancelled/exhausted.
  • Agents SHOULD set reasonable budget limits to prevent runaway costs.
  • Agents using NWC auto-pay SHOULD create a dedicated NWC connection with a scoped budget macaroon for each subscription.
  • Agents SHOULD listen on their NIP-17 inbox relays (kind:10050) for delivery events.
  • Agents MAY run headless and use NIP-47 for autonomous payment without human intervention.

For Providers

  • Providers SHOULD rate-limit subscription requests per pubkey.
  • Providers SHOULD publish their capabilities via NIP-89 and keep them updated.
  • Providers MUST honor the subscriber’s budget limit and send a kind:6900 with status=exhausted when reached.
  • Providers SHOULD include delivery_index and budget_remaining_msats in delivery payloads so subscribers can track consumption.
  • Providers MAY require proof-of-payment before activating a subscription.
  • Providers SHOULD send a kind:6900 with status=expired when the subscription duration elapses, giving the subscriber an opportunity to renew.

Payment Considerations

  • For pay-per-delivery, providers SHOULD batch small-value deliveries to avoid Lightning dust limits and routing failures on very small invoices.
  • For high-frequency subscriptions, NWC auto-pay or prepaid models are RECOMMENDED to reduce payment friction.
  • Providers MAY offer discounts for longer subscription durations or larger prepaid budgets.
  • The max_price tag in the subscription request allows subscribers to cap per-delivery costs and reject offers that exceed their willingness to pay.

Security Considerations

  • Subscribers MUST validate that delivery events (kind:7900) are signed by the expected provider pubkey.
  • Subscribers SHOULD verify that delivered events contain valid signatures from their original authors.
  • NWC connections used for auto-pay MUST be scoped with minimum necessary permissions (pay_invoice only) and strict budget limits.
  • Providers MUST NOT store subscriber private keys or NWC secrets beyond what is needed for the connection.
  • Both parties SHOULD use NIP-44 encryption (via NIP-17/NIP-59) for all post-handshake communication.

Example: AI Agent Monitoring Bitcoin Sentiment

  1. Agent publishes a subscription request:
{
  "kind": 5900,
  "pubkey": "<agent-pubkey>",
  "tags": [
    ["d", "btc-sentiment-monitor-001"],
    ["p", "<sentiment-provider-pubkey>"],
    ["filter", "{\"kinds\":[1],\"#t\":[\"bitcoin\",\"btc\"],\"limit\":0}"],
    ["enrichment", "sentiment-analysis"],
    ["cadence", "batch", "3600"],
    ["duration", "604800"],
    ["max_price", "500"],
    ["budget", "500000"],
    ["output", "application/json"]
  ]
}

  1. Provider responds via NIP-17 DM with terms and a Lightning invoice for 100,000 msats upfront.
  2. Agent pays the invoice via NWC.
  3. Provider confirms activation via NIP-17 DM (status=active).
  4. Every hour, the agent receives a kind:7900 delivery via NIP-17 DM containing a batch of bitcoin-related posts from the last hour, each annotated with sentiment scores.
  5. After 7 days, the subscription expires. Provider sends status=expired. Agent may publish a kind:8900 with action=renew.

Appendix: Suggested Kind Number Rationale

The 5900/6900/7900/8900 range is chosen to sit within the NIP-90 DVM range (5000-7000 extended) while clearly indicating these are subscription-related rather than one-shot job events:

  • 5900: Subscription request (analogous to 5xxx job requests)
  • 6900: Subscription confirmation (analogous to 6xxx job results)
  • 7900: Subscription delivery (new: ongoing result stream)
  • 8900: Subscription management (new: lifecycle control)

Note: Final kind numbers should be assigned through the standard NIP process. The numbers above are placeholders for discussion.


No comments yet.