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

@relayplane/sdk

v1.1.10

Published

RelayPlane SDK - Local-first AI workflow engine for building multi-step AI workflows

Downloads

372

Readme

@relayplane/sdk

The local-first AI workflow engine. Switch providers without rewriting your app.

npm version License: MIT

Install

npm install @relayplane/sdk

Quick Start

import { relay } from "@relayplane/sdk";

const result = await relay
  .workflow("content-pipeline")
  .step("draft")
  .with("openai:gpt-5.2")
  .prompt("Write a blog post about {{input.topic}}")
  .step("review")
  .with("anthropic:claude-sonnet-4-5-20250929")
  .prompt("Improve this draft for clarity and engagement")
  .depends("draft")
  .run({ topic: "AI workflows" });

console.log(result.steps.review);

That's it. Runs locally with your API keys. No gateway. No surprises.

Switch Providers in One Line

// OpenAI
.with("openai:gpt-5.2")

// Anthropic
.with("anthropic:claude-sonnet-4-5-20250929")

// Google
.with("google:gemini-3-flash")

// xAI
.with("xai:grok-beta")

// Local (Ollama)
.with("local:llama3.3")

Same code. Same response format. Change one string.

Why RelayPlane?

| Without RelayPlane | With RelayPlane | |-------------------|-----------------| | Different SDK for each provider | One SDK, every provider | | Rewrite code to switch models | Change one string | | Silent model changes break production | Explicit provider:model — what you write runs | | DIY retry, fallback, caching | Built-in reliability | | Observability is an afterthought | Telemetry from day one | | Tool calls need separate plumbing | MCP steps native in workflows |

Complete Example

import { relay } from "@relayplane/sdk";
import { z } from "zod";

const InvoiceSchema = z.object({
  invoiceNumber: z.string(),
  vendor: z.string(),
  totalAmount: z.number(),
  items: z.array(z.object({
    description: z.string(),
    quantity: z.number(),
    unitPrice: z.number(),
  })),
});

const result = await relay
  .workflow("invoice-processor")

  // Step 1: Extract structured data
  .step("extract", {
    schema: InvoiceSchema,
    systemPrompt: "Extract all invoice fields as structured JSON.",
  })
  .with("openai:gpt-5.2")

  // Step 2: Validate with a different model
  .step("validate", {
    systemPrompt: "Verify totals and flag discrepancies.",
  })
  .with("anthropic:claude-sonnet-4-5-20250929")
  .depends("extract")

  // Step 3: Generate summary
  .step("summarize")
  .with("openai:gpt-5-mini")
  .prompt("Create executive summary for finance approval.")
  .depends("validate")

  .run({ fileUrl: "https://example.com/invoice.pdf" });

console.log(result.steps.extract);   // Typed as InvoiceSchema
console.log(result.steps.summarize);

MCP Tool Integration

Mix AI steps with external tools using the Model Context Protocol:

relay.configure({
  mcp: {
    servers: {
      crm: { url: "http://localhost:3100" },
      github: { url: "http://localhost:3101" },
    },
  },
});

const result = await relay
  .workflow("lead-enrichment")

  // AI step: Extract company name
  .step("extract")
  .with("openai:gpt-5.2")
  .prompt("Extract the company name from: {{input.email}}")

  // MCP step: Look up in CRM
  .step("lookup")
  .mcp("crm:searchCompany")
  .params({ name: "{{steps.extract.companyName}}" })
  .depends("extract")

  // AI step: Generate personalized outreach
  .step("outreach")
  .with("anthropic:claude-sonnet-4-5-20250929")
  .prompt("Write a personalized email using this CRM data: {{steps.lookup}}")
  .depends("lookup")

  .run({ email: "[email protected]" });

Configuration

Environment Variables (Recommended)

OPENAI_API_KEY=sk-...
ANTHROPIC_API_KEY=sk-ant-...
GOOGLE_API_KEY=...
XAI_API_KEY=...

Programmatic

relay.configure({
  providers: {
    openai: { apiKey: process.env.OPENAI_API_KEY },
    anthropic: { apiKey: process.env.ANTHROPIC_API_KEY },
  },
});

Per-Run Override

await relay
  .workflow("example")
  .step("test").with("openai:gpt-5.2")
  .run(input, {
    providers: {
      openai: { apiKey: "sk-override-key" },
    },
  });

Supported Providers

| Provider | Example Models | Format | |----------|----------------|--------| | OpenAI | GPT-5.2, GPT-5-mini, o3-mini | openai:gpt-5.2 | | Anthropic | Claude Opus 4.5, Sonnet 4.5, Haiku 4.5 | anthropic:claude-sonnet-4-5-20250929 | | Google | Gemini 3 Pro, Gemini 3 Flash, Gemini 2.5 Flash | google:gemini-3-flash | | xAI | Grok Beta | xai:grok-beta | | Perplexity | Sonar Pro, Sonar Reasoning | perplexity:sonar-pro | | Local | Any Ollama model | local:llama3.3 |

Note: Use exact model IDs from each provider. See relayplane.com/docs/providers for the complete list of supported models.

API Reference

Workflow Builder

relay
  .workflow("name")           // Create workflow
  .step("stepName", config?)  // Add step
  .with("provider:model")     // Set AI model
  .prompt("text")             // Set prompt
  .mcp("server:tool")         // Or use MCP tool
  .params({ ... })            // MCP parameters
  .depends("step1", "step2")  // Declare dependencies
  .webhook("https://...")     // Add webhook (cloud)
  .schedule("0 9 * * *")      // Add schedule (cloud)
  .run(input, options?)       // Execute

Builder Chain Order

The SDK uses phantom types for compile-time safety. This means methods must be called in a specific order:

AI Steps:

.step() → .with() → [.prompt() | .depends() | .step() | .run()]

MCP Steps:

.step() → .mcp() → .params() → [.depends() | .step() | .run()]

Key constraints:

  • After .prompt(), you cannot call .depends() — call .depends() before .prompt() if needed
  • After .mcp(), you must call .params() before .step() or .run()
  • TypeScript will enforce these constraints at compile time

Example: Correct ordering

// AI step with dependencies - call .depends() before .prompt()
.step("review")
.with("anthropic:claude-sonnet-4-5-20250929")
.depends("extract")                    // Dependencies first
.prompt("Review the extracted data")   // Prompt last

// MCP step - .params() is required after .mcp()
.step("lookup")
.mcp("crm:searchCompany")
.params({ name: "{{steps.extract.company}}" })
.depends("extract")

Step Config

.step("name", {
  schema: ZodSchema,           // Structured output validation
  systemPrompt: "...",         // System prompt
  userPrompt: "...",           // User prompt
  retry: { maxAttempts: 3 },   // Retry config
  metadata: { ... },           // Custom metadata
})

Result

const result = await workflow.run(input);

result.success        // boolean
result.steps          // { stepName: output, ... }
result.finalOutput    // Last step's output
result.error          // { message, stepName, cause }
result.metadata       // { workflowName, startTime, endTime, duration }

Error Handling

const result = await relay
  .workflow("example")
  .step("process").with("openai:gpt-5.2")
  .run(input);

if (!result.success) {
  console.error(`Failed at step: ${result.error.stepName}`);
  console.error(result.error.message);
}

TypeScript: Typed Results with Schemas

import { z } from "zod";

const UserSchema = z.object({
  name: z.string(),
  email: z.string().email(),
});

const result = await relay
  .workflow("extract-user")
  .step("extract", { schema: UserSchema })
  .with("openai:gpt-5.2")
  .run({ text: "Contact: John at [email protected]" });

// result.steps.extract is typed as { name: string; email: string }
console.log(result.steps.extract.name);

Cloud Features (Optional)

Webhooks & Schedules

await relay
  .workflow("daily-report")
  .schedule("0 9 * * *")
  .webhook("https://slack.com/webhook/...")
  .step("generate").with("openai:gpt-5.2")
  .run(input);

Key-Value Store

// Store data across runs
await relay.kv.set("user:settings", { theme: "dark" });
const settings = await relay.kv.get("user:settings");

// With TTL
await relay.kv.set("cache:data", data, { ttl: 3600 });

Backup & Restore

const backupId = await relay.backup.create({
  name: "daily-backup",
  includes: { workflows: true, configs: true },
});

await relay.backup.restore({ backupId, mode: "merge" });

Pricing: Free tier available. Pro ($99/mo) unlocks webhooks & schedules.

BYOK (Bring Your Own Keys)

RelayPlane never proxies your API calls. Your keys talk directly to providers.

  • No markup on API costs
  • No usage fees beyond providers
  • Your data stays between you and the provider

CLI

npx relay login      # Authenticate (optional)
npx relay status     # Check connection
npx relay dashboard  # Open web dashboard
npx relay logout     # Sign out

Links

License

MIT