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

@steve-life/agent-sdk

v0.1.3

Published

Pure TypeScript SDK for routing normalized agent requests across configured agent and model nodes.

Downloads

524

Readme

Agent SDK

A pure TypeScript SDK for routing normalized agent requests across Codex SDK and Claude Agent SDK adapters.

The SDK is designed for applications that have many logical nodes and many backing agents. Client code owns the catalog, users can choose nodes and models at runtime, and the router handles fallback when a provider or local pool is at its limit.

Features

  • TypeScript-first configuration with codexAdapter(), claudeAgentAdapter(), and agentPool().
  • User-selectable nodes and models through router.listNodes().
  • Logical agent pools: one node can contain multiple ordered backing agents.
  • Automatic fallback on provider rate limits, quota/capacity errors, and local pool concurrency limits.
  • Streaming events for text, provider raw events, usage, router fallback, router limits, and thinking/progress deltas.
  • Direct apiKey support from client code, with env-based config kept only as a compatibility path.

Install

npm install @steve-life/agent-sdk

Quick Start

import {
  agentPool,
  claudeAgentAdapter,
  codexAdapter,
  createAgentRouter
} from "@steve-life/agent-sdk";

const router = createAgentRouter({
  adapters: [
    agentPool({
      name: "planner",
      displayName: "Planning Layer",
      agents: [
        codexAdapter({
          name: "codex-primary",
          models: ["gpt-5.3-codex", "gpt-5.3-codex-spark"],
          apiKey: process.env.OPENAI_API_KEY,
          thinkingLevel: "high"
        }),
        claudeAgentAdapter({
          name: "claude-backup",
          models: ["claude-sonnet"],
          apiKey: process.env.ANTHROPIC_API_KEY
        })
      ]
    }),
    codexAdapter({
      name: "custom-codex",
      displayName: "Custom Codex-Compatible",
      models: ["custom-model-main", "custom-model-fast"],
      baseUrl: "https://provider.example/v1",
      apiKey: process.env.CUSTOM_PROVIDER_API_KEY
    })
  ],
  defaultAdapter: "planner",
  fastAdapter: "custom-codex"
});

const result = await router.run({
  prompt: "Review this repository and summarize the risky areas.",
  cwd: process.cwd()
});

console.log(result.output);

User Selection

Use listNodes() to render a node/model picker without exposing API keys.

const nodes = router.listNodes();

await router.run({
  prompt: "Create a refactor plan.",
  node: nodes[0].name,
  model: nodes[0].allowedModels[0]
});

agentPool() exposes one logical selectable node by default. Fallback agents are hidden from normal selection, but available for diagnostics:

const internalNodes = router.listNodes({ includeHidden: true });

Streaming

runStream() emits the complete normalized router event stream. Use thinking.delta for model progress or reasoning summaries, text.delta for visible output, provider.raw when you need the underlying SDK event, and router.limit to show why the router moved to the next agent.

for await (const event of router.runStream({ prompt: "Plan the refactor" })) {
  if (event.type === "thinking.delta") {
    renderThinking(event.delta);
  }

  if (event.type === "text.delta") {
    process.stdout.write(event.delta);
  }

  if (event.type === "router.limit") {
    console.warn(`Switching from ${event.node}: ${event.limit.kind}`);
  }

  if (event.type === "provider.raw") {
    debugProviderEvent(event.raw);
  }
}

For callback-style consumers, runWithHandlers() consumes the same stream and awaits each handler in event order. Handler failures reject the run. If the stream emits router.error, onError receives the normalized error payload before the original provider error is rethrown.

const result = await router.runWithHandlers(
  { prompt: "Plan the refactor" },
  {
    onThinkingDelta(delta) {
      renderThinking(delta);
    },
    onTextDelta(delta) {
      process.stdout.write(delta);
    },
    onRawEvent(raw) {
      debugProviderEvent(raw);
    },
    onUsage(usage) {
      updateTokenMeter(usage);
    },
    onError(error) {
      reportStreamError(error);
    }
  }
);

console.log(result.output);

Routing Rules

  • request.node wins first.
  • request.model must be allowed by the selected node.
  • request.model without request.node selects the first node whose allowlist contains that model.
  • Fallback skips nodes that do not allow an explicit request model.
  • A non-empty model allowlist must include the node's default model.
  • Matching is exact string matching.

Providers

Only two provider kinds are public:

  • codex: backed by @openai/codex-sdk
  • claude-agent: backed by @anthropic-ai/claude-agent-sdk

Custom OpenAI-compatible endpoints should use codexAdapter({ baseUrl }). Custom Claude Agent endpoints should use claudeAgentAdapter({ baseUrl }); the SDK injects that value as ANTHROPIC_BASE_URL and passes the model allowlist as settings.availableModels.

Env Compatibility

TypeScript configuration is the recommended path. Env-defined nodes are still supported for older integrations, but they are not the best fit for systems with large dynamic node catalogs or user-selectable agents.

See .env.example for the compatibility format.

Development

npm install
npm run typecheck
npm test
npm pack --dry-run

License

MIT