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

@synadia-ai/agents

v0.5.2

Published

TypeScript SDK for the Synadia Agent Protocol for NATS — discover, prompt, and stream from AI agents over NATS.

Readme

@synadia-ai/agents

Caller-side TypeScript SDK for the Synadia Agent Protocol for NATS. Discover, prompt, and stream from AI agents over NATS.

  • Catch errors before they hit the wire. Oversized payloads and unsupported attachments are validated locally against the agent's advertised limits — and against the caller's own nc.info.max_payload, so the smaller of the two binds (a caller behind a smaller-cap broker fails fast instead of waiting for MAX_PAYLOAD_VIOLATION).
  • Stream responses with for await. Prompts return typed chunks (response, status, query) you iterate asynchronously.
  • Runs on Node ≥ 20 and Bun ≥ 1.2.

Hosting an agent? Install the sister package @synadia-ai/agent-service for AgentService, ReferenceAgent, and the host-side wire helpers. The two packages release in lockstep.

Install

bun add @synadia-ai/agents
# or: npm install @synadia-ai/agents
# or: pnpm add @synadia-ai/agents

30-second quickstart

You bring a NatsConnection; the SDK uses it. Use @nats-io/transport-node for TCP (nats://, tls://) or wsconnect from @nats-io/nats-core for WebSocket (ws://, wss://) — the same connection can then be shared with JetStream, KV, services, and anything else in the @nats-io/* ecosystem.

import { connect } from "@nats-io/transport-node";
import { Agents } from "@synadia-ai/agents";

const nc = await connect({ servers: "nats://localhost:4222" });
const agents = new Agents({ nc });

const found = await agents.discover(); // stall strategy — returns as soon as replies quiet down

for await (const msg of await found[0]!.prompt("describe this photo", {
  attachments: ["./vacation.jpg"],
})) {
  if (msg.type === "response") process.stdout.write(msg.text);
}

await agents.close();
await nc.close(); // caller owns the NATS connection

Local validation in action

If the target agent doesn't accept attachments, or if the envelope exceeds its max_payload, the SDK fails your call before publishing:

import { AttachmentsNotSupportedError, PayloadTooLargeError } from "@synadia-ai/agents";

try {
  const stream = await remote.prompt("describe this photo", {
    attachments: ["./vacation.jpg"],
  });
  for await (const msg of stream) {
    /* ... */
  }
} catch (e) {
  if (e instanceof AttachmentsNotSupportedError) {
    // agent's attachments_ok === false - no wire traffic.
  } else if (e instanceof PayloadTooLargeError) {
    console.log(`${e.actual} > ${e.limit} bytes`);
    // Again: no wire traffic.
  } else throw e;
}

Both error types extend ValidationErrorNatsAgentError. See Error handling for the full taxonomy.

What's in the box

| API | Purpose | | ---------------------------------------------------------------- | ------------------------------------------------------------------------------------ | | new Agents({ nc, ... }) | Construct from a caller-owned NatsConnection. | | agents.discover({filter?, timeoutMs?}) | Return a live Agent[]; auto subscribe-before-ping (§8.5). | | agent.prompt(text, {attachments, signal, inactivityTimeoutMs}) | Return a PromptStream. | | agents.liveness(id) / onHeartbeat(id, cb) / ping(id) | Heartbeat tracking and on-demand ping. | | agents.close() | Tear down SDK state; aborts all in-flight streams. | | loadContextOptions(name) / parseNatsUrl(url) | Bridge nats CLI context files / URLs into NodeConnectionOptions for connect(). | | withAgentReconnectDefaults(opts?) | Opt-in resilient reconnect defaults for agent runtimes — see below. Pure transform. |

Resilient reconnect defaults

@nats-io/transport-node gives up after ~10 reconnect attempts (~20 seconds) by default, which is too aggressive for an agent process that's supposed to outlive laptop sleeps and intermittent broker reachability. Wrap your options with withAgentReconnectDefaults to keep retrying indefinitely (and to retry from the very first connect attempt, instead of throwing if the broker is down at startup):

import { connect } from "@nats-io/transport-node";
import { withAgentReconnectDefaults } from "@synadia-ai/agents";

const nc = await connect(withAgentReconnectDefaults({ servers: "nats://localhost:4222" }));

The helper merges defaults into caller-provided options, preserving any field the caller explicitly set (including 0 and false). The defaults — maxReconnectAttempts: -1, reconnectTimeWait: 2000, reconnectJitter: 200, waitOnFirstConnect: true — are also exported as AGENT_RECONNECT_DEFAULTS for introspection or selective override.

When you adopt these defaults, also handle the terminal close status event in your for await (const s of nc.status()) loop — it still fires on repeated identical auth errors and on explicit nc.close() / nc.drain(), and a stuck "reconnecting…" UI on a truly dead connection is worse than an honest "disconnected" one.

Subpath exports:

  • @synadia-ai/agents/errors - the error class hierarchy, for targeted instanceof branches.

The host-side ReferenceAgent previously available at @synadia-ai/agents/testing moved to @synadia-ai/agent-service/testing when the SDK split into caller + host packages. Anything you used to import from there is in the new sister package now.

Documentation

  • Getting started - end-to-end walkthrough with error handling, cancellation, and liveness.
  • Protocol mapping - every SDK call cross-referenced to the spec.
  • examples/ - five runnable scripts (discover, prompt-text, prompt-attachment, query-reply, liveness).

Browser support is planned but not shipped yet - the core validation and parsing layers are already runtime-agnostic.

Contributing

bun install          # or: npm install
bun run typecheck
bun run lint
bun run test:unit         # no NATS required
bun run test:integration  # spawns nats-server - install via brew / apt / https://github.com/nats-io/nats-server/releases

Integration tests skip cleanly with a friendly message if nats-server isn't on PATH.

License

Apache-2.0