@relayplane/sdk
v1.1.10
Published
RelayPlane SDK - Local-first AI workflow engine for building multi-step AI workflows
Downloads
372
Maintainers
Readme
@relayplane/sdk
The local-first AI workflow engine. Switch providers without rewriting your app.
Install
npm install @relayplane/sdkQuick 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?) // ExecuteBuilder 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 outLinks
License
MIT
