> **Nostr Agent Onboarding** · [start here](https://npub1d70emggs6jzun5lhvqnfqsd9reqmaarn2qjf6q3r02gryyl4v8sqjn44xe.nsite.lol/start.md) · [index](https://npub1d70emggs6jzun5lhvqnfqsd9reqmaarn2qjf6q3r02gryyl4v8sqjn44xe.nsite.lol/llms.txt) · source: `nostr-dev/docs/sources/outbox-model.md` · snapshot 2026-10-10

# Outbox model — references and condensed rules

> Vendored summary + canonical links. The mechanics are simple enough to
> codify here directly.

## Canonical sources

- **NIP-65** — Relay List Metadata (kind 10002):
  <https://github.com/nostr-protocol/nips/blob/master/65.md>
- **Nostrify** — "The Outbox Model": <https://nostrify.dev/relay/outbox>
- **whynostr.org** — "What is the Outbox Model?":
  <https://www.whynostr.org/post/8yjqxm4sky-tauwjoflxs/>
- **Mike Dilger's gossip client** — original implementation:
  <https://github.com/mikedilger/gossip>
- **NDK outbox docs** — <https://github.com/nostr-dev-kit/ndk> (the JS library
  in this workspace's `sdk/` already implements outbox under the hood)

## The mechanics — condensed

A **kind 10002** event from a user contains `r` tags. Each `r` tag has either
no second value (relay used for both reading and writing), or one of `read` /
`write`:

```json
{
  "kind": 10002,
  "tags": [
    ["r", "wss://relay.damus.io"],
    ["r", "wss://nos.lol", "write"],
    ["r", "wss://relay.nostr.band", "read"]
  ],
  "content": ""
}
```

Terminology, post NIP-65 finalization:

| Tag flag | Modern name | Use |
|---|---|---|
| `write` (or unflagged) | **OUTBOX** | where this user *publishes* their events |
| `read` (or unflagged) | **INBOX** | where this user *expects to receive* DMs and mentions |

## Routing rules that fall out

- **Reading someone's posts** → query their **OUTBOX** relays (typically pick
  2–3 of them, not all).
- **Sending a DM (NIP-17 / NIP-44 / NIP-59)** → publish to the recipient's
  **INBOX** only. Also publish to your own INBOX so you have a record.
- **Posting your own content publicly** → publish to **all** of your OUTBOX
  relays + the INBOX relays of every user you `p`-tagged or mentioned.
- **Querying a user's profile / follow list / relay list** → their OUTBOX.
- **Anonymous browsing / cold start** → general-purpose relays
  (`wss://relay.damus.io`, `wss://nos.lol`) + index relays
  (`wss://purplepag.es`, `wss://user.kindpag.es`; `relay.nostr.band` was
  unreachable as of 2026-09).

## Why outbox > fixed-list (for general social)

A fixed-list client publishes to N popular relays and reads from the same N.
Result: those N relays become de facto centralization points; if they drop
you, your followers can't see you. With outbox, *each user is sovereign over
their own distribution*. Censorship-resistance comes from the routing being
declared by the author, not the platform.

## What outbox does NOT solve (be explicit in your design)

- **Communities, group chats, topical feeds** — those want a community/topic
  relay, not the user's outbox. NIP-29, NIP-72.
- **DMs** — go to inbox, not outbox.
- **Search / full-text indexing** — needs a search relay
  (`search.nos.today`; NIP-50. `relay.nostr.band` was unreachable as of 2026-09).
- **Discovery of users you don't follow yet** — outbox is read-side only.
  You need gossip-flavored hints (relay hints in `e`/`p`/`a` tags, NIP-05,
  `nprofile`).
- **Per-event routing for non-broadcast kinds** — anything that is not a
  general-purpose social broadcast probably wants a deliberate routing choice.

## Practical implementation hints

- Maintain a routing table: `pubkey → [outbox relays]`. NDK calls this an
  "outbox database." Update lazily as you encounter new authors.
- Cap outbox per author at 2–4 relays per query. More is wasteful; fewer is
  fragile.
- Treat kind 10002 as **replaceable** — only the latest matters.
- A user with no kind 10002 → fall back to general-purpose relays + any relay
  hints you have for them.

## Gossip — the superset

Gossip = outbox + every other discoverable hint:

- relay hints in `e` tags (`["e", "<id>", "<relay-url>"]`),
- relay hints in `p` tags (`["p", "<pubkey>", "<relay-url>"]`),
- relay hints in `a` tags for addressable references,
- `nprofile` / `nevent` URIs that bake in relays,
- NIP-05 metadata that names relays,
- observed presence of the author in replies on relays you already speak to.

The Gossip client is the canonical reference; NDK and Coracle implement
gossip-flavored outbox by default.
