SDK-First Integration for AI Agent Control

Runplane sits between your agent and execution. Wrap your tools with the SDK, and decisions are enforced at runtime: ALLOW, BLOCK, or REQUIRE_APPROVAL.

How It Works

1. Bring Your Tools

Your existing agent tools

2. Auto-Mapped Actions

Canonical types generated

3. Baseline Policies

Ready-to-use, customizable

4. Wrap with guard()

Enforced at runtime

Installation

npm install @runplane/runplane-sdk

SDK Setup

import { Runplane } from "@runplane/runplane-sdk"

const runplane = new Runplane({
  baseUrl: "https://runplane.ai",
  apiKey: process.env.RUNPLANE_SYSTEM_KEY,
  failMode: "closed"  // block if Runplane unreachable
})

failMode: "closed" blocks actions if Runplane is unreachable. Use "open" to allow execution if unreachable (not recommended for production).

Wrap Execution with guard()

The guard() method wraps your tool execution. Runplane evaluates the action against your policies and enforces the decision before the callback runs.

await runplane.guard(
  "delete_employee",          // canonical action type
  "hr_system",                // target resource or system
  { employeeId: "emp_7421" }, // context for policy evaluation
  async () => {
    // This callback only runs if ALLOWED or APPROVED
    await deleteEmployee("emp_7421")
  }
)

How guard() works:

  • 1. Sends action + context to Runplane for policy evaluation
  • 2. Receives decision: ALLOW, BLOCK, or REQUIRE_APPROVAL
  • 3. If ALLOW: callback executes immediately
  • 4. If BLOCK: callback never runs, throws GuardBlockedError
  • 5. If REQUIRE_APPROVAL: waits for human approval, then executes or blocks

Decision States

ALLOW

Callback executes immediately. Low risk, policy permits.

BLOCK

Callback never runs. Policy violation or excessive risk.

REQUIRE_APPROVAL

Pauses until human approves or denies.

Error Handling

import { GuardBlockedError, GuardDeniedError } from "@runplane/runplane-sdk"

try {
  await runplane.guard(
    "delete_production_database",
    "prod-db",
    { table: "users" },
    async () => {
      await dropTable("users")
    }
  )
} catch (error) {
  if (error instanceof GuardBlockedError) {
    // Policy blocked the action
    console.log("Action blocked:", error.reason)
  } else if (error instanceof GuardDeniedError) {
    // Human denied the approval request
    console.log("Approval denied:", error.reason)
  }
}

Framework Integration

Runplane works with any AI agent framework. Wrap your tool implementations with guard().

LangChain

import { tool } from "@langchain/core/tools"
import { z } from "zod"

const deleteRecordTool = tool(
  async ({ recordId }) => {
    // Wrap with Runplane guard
    await runplane.guard(
      "delete_record",
      "database",
      { recordId },
      async () => {
        await db.delete(recordId)
      }
    )
    return "Record deleted"
  },
  {
    name: "delete_record",
    description: "Delete a record from the database",
    schema: z.object({ recordId: z.string() })
  }
)

Vercel AI SDK

import { tool } from "ai"
import { z } from "zod"

const sendEmailTool = tool({
  description: "Send an email to a user",
  parameters: z.object({
    to: z.string(),
    subject: z.string(),
    body: z.string()
  }),
  execute: async ({ to, subject, body }) => {
    // Wrap with Runplane guard
    await runplane.guard(
      "send_email",
      "email_service",
      { to, subject },
      async () => {
        await sendEmail({ to, subject, body })
      }
    )
    return { sent: true }
  }
})

Importing Existing Tools

Use the dashboard to import tools from your agent framework. Runplane automatically maps them to canonical action types and applies baseline policies. You remain in control — customize policies for any action type.

Supported import sources:

  • LangChain tool definitions
  • Vercel AI SDK tools
  • OpenAPI specifications
  • Manual tool registration

Direct API Access (Advanced)

For environments where the SDK cannot be used, you can call the decision endpoint directly. However, the SDK is the recommended integration path.

curl -X POST https://runplane.ai/api/decide \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer RUNPLANE_SYSTEM_KEY" \
  -d '{
    "actionType": "send_email",
    "target": "email_service",
    "context": { "recipientCount": 50000 }
  }'

Response:

{
  "decision": "REQUIRE_APPROVAL",
  "reason": "Bulk email requires approval",
  "requestId": "req_abc123"
}

Note: When using the direct API, you are responsible for handling the decision and blocking/allowing execution in your code. The SDK handles this automatically.

Full SDK reference and tool management available in the dashboard after account creation.