AGX
AGX (NIP-AGX) is an open, MIT-licensed protocol that lets an agent in one organization reach an agent in another. They can send messages or request tasks, and neither side needs a shared server, a shared account or an inbound HTTP endpoint.
AGX runs on Nostr and borrows three ideas from it:
- An identity is a keypair. An agent is its public key (an
npub), not a URL. That means an agent can’t be impersonated by spoofing a hostname. - Everything is signed and encrypted end to end. Relays only store and forward events; they never see who sent a message or what it says.
- The payload is up to you. AGX takes care of identity, integrity, delivery and the task lifecycle. What a task actually does is decided by your runtime.
AGX handles traffic between organizations. Agents inside the same Elacity organization keep using native internal messaging.
The packages
The normative spec is SPEC.md in @nostr-agx/core. The protocol is currently at draft 0.2.0.
Core concepts
How a task travels
Each message and receipt is sealed with the sender’s key and then gift-wrapped (NIP-59) under a fresh one-time key. The only thing a relay learns is who the wrap is for: it can’t see the sender, the real send time, or even that the traffic is AGX.
Quickstart: two agents, no server
You only need two keypairs and a local relay.
agx request waits for the task result. agx send only publishes, so run a one-off serve to collect the reply. Without --handler, agx serve answers invoice.review with a built-in stand-in, so this result is canned; plug in your own runtime for real work.
Try it without the agx identity allow line first. The request gets no reply, and agent A prints the reason. That’s the spec working as intended: a denied request never confirms to an unknown peer that you exist.
Plug in your own runtime
agx serve --handler loads a module that default-exports your capability implementations. That module is the whole integration surface: your code never touches a Nostr event.
The Agent Card advertises the module’s keys as its capabilities. --advertise publishes that card and your relay list.
Or use the library directly
The library and the CLI have opposite defaults here. agx serve publishes a card only with --advertise, but a bare agx.start() publishes one straight away. Cards are public, and retracting one is only best-effort, so decide before you start.
If a handler throws an ordinary error, the peer only sees handler failed; the real message is logged locally. Throw AgxPublicError only for messages that belong to your contract, such as invoice not found, because its text crosses the trust boundary unchanged.
CLI at a glance
--profile <name> is a global option. Four settings can also be read from environment variables:
apiBaseUrlfromAGX_API_URLapiKeyfromAGX_API_KEYorgSlugfromAGX_ORGrelaysfromAGX_RELAY(comma-separated)
org and nip05 have no environment form, so set them with agx config set. AGX_PROFILE selects the profile, and AGX_HOME moves ~/.agx somewhere else.

