Control every AI action before it executes
Runplane is an enforcement layer, not an agent runtime.
Runplane intercepts every action before execution and returns a decision: ALLOW, BLOCK, or REQUIRE_APPROVAL.
Gateway-First Architecture
All decisions are made server-side via Runplane's Guard API (https://runplane.ai/api/v1/guard). The SDK routes execution through the Guard API and enforces the result.
How Runplane Works
Every action flows through the Guard API before execution. The API evaluates policies and returns a decision. The callback only executes if the decision is ALLOW.
Action Sent
Agent calls guard() with action, target, context
Decision Made
Guard API evaluates policies and returns decision
Execution Controlled
Callback runs only if ALLOW, never if BLOCK
Decision Model
ALLOWCallback executes immediately.
The action proceeds without delay. The callback function runs and returns its result.
BLOCKCallback never runs.
The SDK throws ShieldError. The action is permanently blocked.
REQUIRE_APPROVALExecution pauses until human decision.
SDK polls for approval. If approved, callback executes. If denied, throws ShieldError.
System Flow
1. Import Tools
Bring your existing agent tools. These define what actions your agent can take.
2. Action Mapping
Tools are normalized into canonical action types for consistent policy enforcement.
deleteUser()delete_recordsendEmail()send_email3. Policy Configuration
Define rules based on action type, target system, and runtime context.
delete_recordusers-database4. Guard API
Every action is sent to the Guard API before execution. This is the enforcement boundary.
await shield.guard(action, target, context, callback)5. Decision
Guard API evaluates policies and returns one of three decisions.
ALLOWBLOCKREQUIRE_APPROVAL6. Execution
ShieldError7. Audit
Every action and decision is recorded in the audit log.
Guard API
The Guard API (/api/v1/guard) is the core primitive. It receives action + context, evaluates policies, and returns a decision. The SDK's guard() method wraps this API.
await shield.guard(
"delete_record", // action type
"users-database", // target
{ recordId: "user_123" }, // context
async () => { // callback
await deleteUser("user_123")
}
)Approval Flow
When the Guard API returns REQUIRE_APPROVAL, the SDK pauses execution and polls for a human decision. Approvals are managed in the Runplane dashboard.
How it works:
- 1SDK calls Guard API, receives
REQUIRE_APPROVALwithapprovalId - 2SDK begins polling the approval endpoint
- 3Request appears in Runplane Dashboard → Approvals
- 4Human reviews action, context, and risk level
- 5aApprove → callback executes, guard() returns result
- 5bDeny → callback never runs, guard() throws
ShieldError
The SDK does not provide approval UI.
Approvals must be managed through the Runplane dashboard. The SDK only polls for the decision.
What Happens on First Run
When you first integrate Runplane, you may see unexpected behavior. This section explains what to expect.
No output? Execution is waiting.
If your code appears to hang with no output, the action likely received REQUIRE_APPROVAL. The SDK is polling and waiting for a human decision.
To resolve: Go to Runplane Dashboard → Approvals and approve or deny the pending request.
ShieldError thrown? Action was blocked.
If ShieldError is thrown, the action received BLOCK. The callback never ran.
To resolve: Check your policy configuration. The action matched a BLOCK rule.
Callback executed immediately? Action was allowed.
If the callback ran without delay, the action received ALLOW. This is the expected behavior for low-risk actions.
Summary: If nothing happens on first run, check the Approvals tab in the dashboard. The SDK is waiting for human input.
SDK vs Direct API
SDK (Recommended)
- Automatic decision enforcement
- Approval polling handled internally
- Throws
ShieldErroron BLOCK - Fail-closed by default
Direct API
- You call
/api/v1/guarddirectly - You must enforce the decision yourself
- You must implement approval polling
- You must handle failure modes
Failure Modes
The SDK provides two failure modes that determine behavior when Runplane is unavailable.
failMode: "closed"defaultIf Runplane is unavailable, all actions are blocked. This is the safe-by-default guarantee.
- Invalid API key → BLOCK
- Network failure → BLOCK
- Timeout → BLOCK
- Approval timeout → BLOCK
- Denied approval → ShieldError (code: DENIED)
failMode: "open"If Runplane is unavailable, actions proceed without control. Use only when explicitly desired.
Warning: This disables the safety guarantee. Actions will execute without policy evaluation.
const shield = new Shield({
failMode: "closed" // blocks if unreachable (default)
})Installation & Setup
npm install @runplane/runplane-sdkimport { Shield } from "@runplane/runplane-sdk"
const shield = new Shield({
baseUrl: "https://runplane.ai",
apiKey: process.env.RUNPLANE_API_KEY,
failMode: "closed"
})await shield.guard(
"delete_record",
"users-database",
{ recordId: "user_123" },
async () => {
await deleteUser("user_123")
}
)SDK Integration Guides
Framework-specific guides for integrating Runplane with your existing agent infrastructure.
LangChain Guardrails
Add runtime control to LangChain Python agents. Wrap any tool with guard() for ALLOW, BLOCK, or REQUIRE_APPROVAL decisions.
MCP Guardrails
Control Model Context Protocol tool execution. Enforce policies before Claude or any LLM accesses MCP servers.
OpenAI Function Calling
Add approval gates and blocking to GPT function calls. Intercept function_call results before execution.
Vercel AI SDK
Runtime guardrails for AI SDK tools. Add blocking and human approval before tool execution.
CrewAI Multi-Agent
Runtime control for multi-agent workflows. Prevent cascading failures when one agent triggers another.
All Integrations
View the full list of SDK integrations and framework guides.