STEERPLANE

TypeScript SDK

The full SteerPlane guardrail pipeline for Node.js — guard(), the SteerPlane class, and a direct REST client.

The TypeScript SDK mirrors the Python SDK feature-for-feature: the same loop detector, cost tracker, and policy engine, running the same guarantees in a Node.js process.

npm install steerplane

guard() — higher-order function

The TypeScript equivalent of the Python @guard decorator wraps an async function instead of decorating it.

import { guard } from "steerplane";

const runAgent = guard(
  async () => {
    await agent.run(); // your code, unchanged
  },
  {
    agentName: "support_bot",
    maxCostUsd: 10.0,
    maxSteps: 50,
    policy: { deniedActions: ["delete_*", "drop_*"] },
    enforcement: "alert",
  }
);

await runAgent();

SteerPlane class — context-manager style

For logging individual steps or nested runs, use the SteerPlane class directly.

import { SteerPlane } from "steerplane";

const sp = new SteerPlane({ agentId: "support_bot" });

await sp.run(
  async (run) => {
    await run.logStep({ action: "search_web", tokens: 1200, cost: 0.004 });
    await run.logStep({ action: "summarize", tokens: 800, cost: 0.002 });
  },
  { maxCostUsd: 10, maxSteps: 50 }
);

getActiveRun()

Retrieve the currently active run from anywhere in the call stack — useful inside nested helper functions that don't have direct access to the run object.

import { getActiveRun } from "steerplane";

function helper() {
  const run = getActiveRun();
  run?.logStep({ action: "helper_call", tokens: 50 });
}

Core classes (same guarantees as Python)

ExportPurpose
LoopDetector, detectLoopThe same O(W²) sliding-window loop detector.
CostTracker, DEFAULT_PRICINGPer-session cost accumulation and built-in model pricing.
PolicyEngine, globMatchThe same deny → allow → rate-limit → approval evaluation order.
RunManagerRun lifecycle and step logging (used internally by SteerPlane.run).
import { PolicyEngine } from "steerplane";

const policy = new PolicyEngine({
  deniedActions: ["delete_*", "drop_*"],
  allowedActions: ["search_*", "read_*"],
  // note: RateLimitSpec fields are snake_case, unlike the rest of the TS API
  rateLimits: [{ pattern: "send_email", max_count: 5, window_seconds: 60 }],
});

const decision = policy.check("delete_users");
// throws PolicyViolationError

SteerPlaneClient — direct REST access

For custom integrations that don't fit the guard()/SteerPlane shapes, SteerPlaneClient talks to the control-plane API directly (the same API the CLI and dashboard use). Its methods take positional arguments and manage run/step IDs explicitly — guard() and SteerPlane are thin wrappers around this client that handle those details for you.

import { SteerPlaneClient, generateRunId } from "steerplane";

const client = new SteerPlaneClient(process.env.STEERPLANE_API_URL, process.env.STEERPLANE_API_KEY);

const runId = generateRunId();
await client.startRun(runId, "support_bot", /* maxCostUsd */ 10, /* maxSteps */ 50);

await client.logStep({
  runId,
  stepNumber: 1,
  action: "search_web",
  tokens: 1200,
  costUsd: 0.004,
});

await client.endRun(runId, "completed", /* totalCost */ 0.004, /* totalSteps */ 1);

Errors

The same exception hierarchy as Python — see Exceptions reference for what each one means. In TypeScript they're thrown, not raised:

import { LoopDetectedError, CostLimitExceeded, PolicyViolationError } from "steerplane";

try {
  await runAgent();
} catch (err) {
  if (err instanceof CostLimitExceeded) {
    // handle cost breach
  }
}

Configuration resolution (env vars → defaults) and the .steerplane.yml file work identically across both SDKs — see CLI & Configuration.

On this page