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

@agentskit/net

v0.2.3

Published

Resilient, bounded and SSRF-safe HTTP for the AgentsKit ecosystem: retry with Retry-After, timeouts, size-limited bodies, SSE parsing and private-address checks. Runs in Node, Bun, Deno, browsers and edge.

Readme

@agentskit/net

Profile: concise-package

HTTP plumbing for agents, in one small package: retries with backoff and Retry-After, per-attempt timeouts, bounded body reads, server-sent events, and SSRF address checks. Web APIs only, so it runs on Node, Bun, Deno, browsers and edge runtimes.

npm version npm downloads bundle size license stability GitHub stars

Tags: agentskit · ai-agents · fetch · retry · sse · ssrf · timeout · edge

Verified proof

How this fits the ecosystem

Adapters, tools and the other AgentsKit repositories each carried their own retry loop, Retry-After parsing, SSE line splitter and private-IP check, with different bugs in each. @agentskit/net owns them, built on eventsource-parser and ipaddr.js, so callers import one tested implementation.

  • AgentsKit: @agentskit/adapters (streaming, retries) and @agentskit/tools (fetching user-supplied URLs) are the intended consumers.
  • Registry: ready agents and templates at registry.agentskit.io.
  • Playbook: production patterns at playbook.agentskit.io.

Docs: package guide · agent handoff

Install

npm install @agentskit/net

Quick example

import { assertPublicUrl, fetchWithRetry, parseSSEResponse, readJson } from '@agentskit/net'

// Refuse private, loopback and metadata addresses before fetching a user-supplied URL.
const { url } = await assertPublicUrl('https://api.example.com/v1/models')

// Idempotent requests retry on 429/5xx, honouring Retry-After; each attempt times out.
const models = await readJson(await fetchWithRetry(url, undefined, { timeoutMs: 10_000 }), {
  maxBytes: 1_000_000,
})
console.log(models)

// Server-sent events as an async iterable.
const stream = await fetch('https://api.example.com/v1/stream', { method: 'POST' })
for await (const event of parseSSEResponse(stream)) {
  if (event.data === '[DONE]') break
  console.log(event.event ?? 'message', event.data)
}

Features

| Area | API | Replaces | |---|---|---| | Retry | retry, computeBackoff, parseRetryAfter, isRetryableStatus, RETRYABLE_STATUSES | hand-written for loops with fixed sleeps, ignored Retry-After | | Fetch | fetchWithRetry | retrying POSTs twice, leaking discarded response bodies, timeouts that span all attempts | | Timeouts | timeoutSignal, anySignal, withTimeout | setTimeout + AbortController boilerplate | | Bodies | readBody, readText, readJson | await res.text() on an unbounded response | | SSE | parseSSE, parseSSEResponse | split('\n') + startsWith('data: ') parsers that break on CRLF, multi-line data and chunk boundaries | | Addresses | assertPublicUrl, isPublicAddress, classifyAddress | regexes over 127./10./192.168. that miss IPv6, IPv4-mapped and metadata addresses |

  • Idempotent by default: fetchWithRetry retries GET/HEAD/OPTIONS/PUT/DELETE/TRACE; pass retryMethods: 'all' to opt in for POST. Streaming bodies are never retried.

  • Typed errors: NetError with AK_NET_TIMEOUT, AK_NET_BODY_TOO_LARGE, AK_NET_BLOCKED_ADDRESS, AK_NET_INVALID_INPUT, AK_NET_SSE_PARSE_FAILED.

  • DNS is injected: assertPublicUrl takes a lookup function, so the package has no node: imports. Checking before connecting does not stop DNS rebinding; pin the resolved address when that matters.

  • Built on: eventsource-parser, ipaddr.js.

  • Guardrail rules: NET_RULES (readonly NetRule[]) from @agentskit/net/rules detects duplicate HTTP retry, SSE, timeout, address and body handling. Add @agentskit/cross-platform as a dev dependency to run its scanner; pass NET_RULES to scanText(file, source, rules) or scanRepository(options). Both return findings that compareToBaseline(findings, baseline) ratchets. Use <id>-ignore: <reason> for an approved one-rule suppression, for example net-retry-after-ignore: legacy retry handler. The repository check is node scripts/check-net-rules.mjs.

    import { NET_RULES } from '@agentskit/net/rules'
    import { scanText } from '@agentskit/cross-platform'
    
    const findings = scanText('src/http.ts', 'const body = await response.text()', NET_RULES)
    console.log(findings.length)

Cancellable waits and deadlines

sleep(ms, signal?) accepts delays from 0 through 2,147,483,647 milliseconds. It uses an abortable timer by default, clears that timer on abort, and rejects with the signal's actual reason. retry uses this public helper by default; its optional sleep callback has the shape (ms, signal?) => Promise<void>. A one-argument callback remains compatible; callbacks that need prompt cancellation should honor the optional signal.

withTimeout(work, ms, parent?) accepts positive deadlines through 2,147,483,647 milliseconds and passes work a signal that aborts on the deadline or when the parent signal aborts. An elapsed deadline rejects with NetError code AK_NET_TIMEOUT; an invalid timeout rejects with AK_NET_INVALID_INPUT. A caller abort preserves its exact reason, and success or an original work failure passes through unchanged. The wrapper rejects on time even if work ignores the signal, but only cooperative work such as fetch can be stopped; arbitrary JavaScript cannot be forcibly cancelled.

import { retry, sleep, withTimeout } from '@agentskit/net'

const parent = new AbortController()
const response = await withTimeout(
  signal => fetch('https://api.example.com/data', { signal }),
  5_000,
  parent.signal,
)

await retry(async () => fetch('https://api.example.com/retry'), {
  sleep: (ms, signal) => sleep(ms, signal),
})

Ecosystem

| Package | Role | |---------|------| | @agentskit/core | AgentsKitError, the base of NetError | | @agentskit/adapters | Provider streaming and retries | | @agentskit/tools | Fetching user-supplied URLs safely |

Contributors

License

MIT — see LICENSE.

Docs

Full documentation · GitHub

Maturity and compatibility

  • Stability: beta — see docs/STABILITY.md. Not 1.0.
  • Node.js 20+ (20.19+), Bun, Deno, modern browsers and edge runtimes; TypeScript strict mode
  • Published as @agentskit/net

Contributing

See CONTRIBUTING.md and the monorepo LICENSE.