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

@agntz/client

v0.4.0

Published

Official TypeScript HTTP client for the agntz API. Universal (Node + browser), SSE streaming, AbortSignal-native.

Readme

@agntz/client

Official TypeScript HTTP client for hosted Agntz and self-hosted workers. It runs in Node 22+ and modern browsers, with zero runtime dependencies.

Install

pnpm add @agntz/client

Usage

import { AgntzClient, type ContentBlock } from "@agntz/client";

const client = new AgntzClient({
  apiKey: process.env.AGNTZ_API_KEY!,
  baseUrl: process.env.AGNTZ_WORKER_URL ?? "https://api.agntz.co",
});

const result = await client.agents.run({
  agentId: "support",
  input: { message: "Can I change my shipping address?" },
  sessionId: "user-42",
  context: ["app/user/u_123"],
});

console.log(result.output);
console.log(result.model, result.usage, result.resolvedAgentVersion);

agents.run, agents.stream, and agents.start share one input contract. The active manifest kind selects text generation, structured output, transcription, or image generation.

The normalized result also includes runId, optional traceId / sessionId, requested and resolved agent versions, provider, actual model, finish reason, provider response id, warnings, and retention metadata.

Per-run client tools

Use kind: client when the manifest should own a tool's name, description, and JSON Schema, but the invoking application must supply the implementation:

tools:
  - kind: client
    name: get_current_selection
    description: Read the user's current editor selection
    inputSchema:
      type: object
      properties:
        includeText: { type: boolean }
      additionalProperties: false
    timeoutMs: 30000
const result = await client.agents.run({
  agentId: "editor-assistant",
  input: "Summarize what I selected",
  clientTools: {
    get_current_selection: async ({ includeText }, ctx) =>
      editor.getSelection({ includeText, signal: ctx.signal }),
  },
});

The SDK keeps this as one run() promise (or one public stream() iterator). Internally it maintains the attached SSE request, calls the local handler, and submits the result back to the same logical Run. Handler source is never sent. Every reachable client tool must have a handler before the Run is created; agents.start/runs.start reject client-tool manifests because they are unattended. Handler errors and the 30-second default deadline are returned to the model as tool errors. Results must be JSON-serializable and no larger than 40,000 serialized characters.

Unlike a signed callback tool, a client tool is invocation-scoped and requires the SDK connection to remain attached. It does not survive reconnects or worker restarts.

Rich content, artifacts, and retention

Local image and audio files are uploaded automatically and replaced with tenant-scoped artifact references before the run starts:

const transcript = await client.agents.run({
  agentId: "social-narration-transcription",
  content: [
    {
      type: "audio",
      file: { path: "./narration.mp3", mediaType: "audio/mpeg" },
    },
  ],
  retention: {
    mode: "none",
    artifactTtlSeconds: 3600,
  },
});

console.log(transcript.output, transcript.model, transcript.usage);

Use mode: "none" for synchronous stateless calls, "result" to retain a redacted result/run record, and "session" for conversation history and traces. Durable agents.start/runs.start calls require result or session.

Artifacts can also be managed explicitly:

const artifact = await client.artifacts.upload({
  file: { path: "./frame.png", mediaType: "image/png" },
  expiresInSeconds: 3600,
});
const imageBlob = await client.artifacts.download(artifact.id);
await client.artifacts.delete(artifact.id);

Content blocks preserve order:

const content = [
  { type: "text", text: "Compare these frames." },
  { type: "image", url: "https://example.com/one.png", detail: "high" },
  { type: "image", base64: encodedPng, mediaType: "image/png" },
  { type: "image", artifactId: artifact.id },
] satisfies ContentBlock[];

Images accept auto, low, or high detail. Audio blocks accept URL, base64, artifact id, or local file sources. Node supports path objects, byte arrays, ArrayBuffer, and Blob; browser code should use Blob or uploaded artifact ids.

ttlSeconds and artifactTtlSeconds accept 60 seconds through one year. Explicit input uploads are capped at seven days by the worker. A caller may tighten a manifest retention default but cannot loosen it.

Transcription and image output

Transcription manifests return:

{
  text: string;
  segments?: unknown[];
  language?: string;
  durationInSeconds?: number;
}

Image manifests return managed references:

{
  artifacts: Array<{
    artifactId: string;
    mediaType: string;
    sizeBytes: number;
    expiresAt: string;
  }>;
}

Download generated images with client.artifacts.download(artifactId). Built-in hosted transcription and image adapters currently use OpenAI.

Streaming

const controller = new AbortController();

for await (const event of client.agents.stream({
  agentId: "support",
  input: { message: "Hello" },
  signal: controller.signal,
})) {
  if (event.type === "start") console.log("started", event.kind);
  if (event.type === "text-delta") process.stdout.write(event.text);
  if (event.type === "complete") console.log("output", event.output);
  if (event.type === "error") console.error(event.error);
}

Resource surface

await client.health();

await client.agents.import({
  agents: [{ id: "support", manifest: supportYaml }],
});
const agents = await client.agents.list();
const agent = await client.agents.get("support");

const run = await client.runs.start({ agentId: "support", input: "hi" });
await client.runs.get(run.id);
await client.runs.cancel(run.id);
await client.runs.list({ agentId: "support", status: "completed" });

const traces = await client.traces.list({ agentId: "support" });
const traceId = traces.rows[0]?.traceId;
if (traceId) {
  await client.traces.get(traceId);
  await client.traces.delete(traceId);
}

await client.sessions.import({ sessions });
await client.sessions.list({ agentId: "support" });
await client.sessions.get("user-42");
await client.sessions.delete("user-42");

Memory

Memory calls are grant-bounded. Pass the same namespace grants you use in run context.

const grants = ["app/user/u_123"];

await client.memory.import({ entries });
await client.memory.scan(grants);
await client.memory.list(grants, { limit: 20 });
await client.memory.read(grants, "prefs");
await client.memory.correct(grants, entryId, "Prefers email receipts");
await client.memory.deleteEntry(grants, entryId);
await client.memory.curate(grants);
await client.memory.deleteScope(grants, "app/user/u_123", { recursive: true });

Datasets and evals

await client.datasets.create(dataset);
await client.datasets.list({ agentId: "support" });
await client.datasets.get("refund-cases");
await client.datasets.update("refund-cases", { description: "Updated" });
await client.datasets.delete("refund-cases");

await client.evals.create(definition);
await client.evals.list({ agentId: "support" });
await client.evals.get("support-quality");

const evalRun = await client.evals.run({
  evalId: "support-quality",
  datasetId: "refund-cases",
  agentVersion: "2026-06-18T15:30:00.000Z",
});

await client.evals.getRun(evalRun.id);
await client.evals.cancelRun(evalRun.id);
await client.evals.listRuns({ evalId: "support-quality" });
await client.evals.getLatestScore({
  evalId: "support-quality",
  datasetId: "refund-cases",
  resolvedAgentVersion: "2026-06-18T15:30:00.000Z",
});
await client.evals.listLatestScores({ evalId: "support-quality" });

Provider-native batches

Batch definitions use the strict provider-native subset of a standard kind: llm manifest. Import a reusable dataset, submit a run, then save a new manifest version with another model and compare item outputs.

const dataset = await client.datasets.import({
  source: { path: "./customers.csv" },
  format: "csv",
  datasetId: "customers",
  name: "Customers",
});

const batch = await client.batches.create(batchYaml);
const run = await client.batches.run({
  batchId: batch.id,
  datasetId: dataset.id,
  idempotencyKey: "customers-2026-07-29",
});

await client.batches.getRun(run.id);
await client.batches.listRuns({ batchId: batch.id });
await client.batches.items(run.id, { limit: 500 });
await client.batches.resultsJsonl(run.id);
await client.batches.cancel(run.id);
await client.batches.compare(firstRun.id, secondRun.id);

Batch results are durable until explicitly deleted. They do not create ordinary runs, sessions, or traces. Use client.batches.deleteRun(runId) once a run is terminal.

Auth

The client sends:

Authorization: Bearer ar_live_...

Generate API keys from the hosted app or your self-hosted UI. Do not embed live API keys in browser code; proxy through your own backend.

Errors and cancellation

  • AgntzError is the base class for client errors.
  • AuthenticationError represents 401 responses.
  • NotFoundError represents 404 responses.
  • StreamError represents SSE protocol failures.

AgntzError preserves the worker's stable code and HTTP status; check error.status === 429 for rate limiting.

Pass an AbortSignal via signal on any call, or defaultSignal on the client. Breaking from a for await stream loop closes the underlying response.

Documentation