Skip to main content

Endpoint

POST /v1/preflight/{toolName}
Dry-run policy evaluation. Does not create/resolve approvals or execute the tool. Use this to check if a tool call would be allowed before attempting it.
Preflight checks are useful for agents that plan before acting. They return the policy decision without side effects.

Path Parameters

toolName
string
required
The name of the tool to evaluate (e.g., exec, read, write, fetch)

Request Headers

Authorization
string
required
Bearer token for authentication
Authorization: Bearer <token>
Content-Type
string
required
Must be application/json

Request Body

The request body schema is identical to POST /v1/tool/{toolName}.
agent
string
required
Agent identifier
session
string
required
Session identifier
params
object
required
Tool-specific parameters
run_id
string
Optional run identifier
input
object
Optional tool input

Response Fields

allowed
boolean
required
Whether the tool call would be allowed (true for allow or watch decisions)
decision
string
required
Policy decision: allow, deny, watch, ask, or require_approval
message
string
required
Human-readable decision message
matched_policies
array
required
Array of policy names that matched this tool call
eval_duration_us
integer
required
Policy evaluation time in microseconds
suggestions
array
Array of suggested commands to allow the operation (appears on deny)

Status Codes

StatusMeaning
200 OKEvaluation successful
400 Bad RequestInvalid JSON body
401 UnauthorizedMissing or invalid bearer token
Unlike POST /v1/tool/{toolName}, preflight never returns 403 Forbidden or 202 Accepted. It always returns 200 OK with the evaluation result.

Examples

Check Allowed Command

TOKEN="$(cat ~/.rampart/token)"
curl -X POST "http://127.0.0.1:9090/v1/preflight/exec" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "agent": "claude-code",
    "session": "repo/main",
    "params": {
      "command": "npm test"
    }
  }'
Response (200 OK):
{
  "allowed": true,
  "decision": "allow",
  "message": "development command allowed",
  "matched_policies": ["allow-dev"],
  "eval_duration_us": 7
}

Check Blocked Command

curl -X POST "http://127.0.0.1:9090/v1/preflight/exec" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "agent": "claude-code",
    "session": "repo/main",
    "params": {
      "command": "rm -rf /"
    }
  }'
Response (200 OK):
{
  "allowed": false,
  "decision": "deny",
  "message": "destructive command blocked",
  "matched_policies": ["block-destructive"],
  "eval_duration_us": 8
}

Check Credential Access

curl -X POST "http://127.0.0.1:9090/v1/preflight/read" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "agent": "cline",
    "session": "project/feature",
    "params": {
      "path": "/home/user/.aws/credentials"
    }
  }'
Response (200 OK):
{
  "allowed": false,
  "decision": "deny",
  "message": "credential access blocked",
  "matched_policies": ["block-credential-reads"],
  "eval_duration_us": 3
}

Check Watched Command

curl -X POST "http://127.0.0.1:9090/v1/preflight/exec" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "agent": "aider",
    "session": "webapp/dev",
    "params": {
      "command": "curl https://api.example.com"
    }
  }'
Response (200 OK):
{
  "allowed": true,
  "decision": "watch",
  "message": "network request logged",
  "matched_policies": ["log-network"],
  "eval_duration_us": 6
}
watch decisions return allowed: true because the tool call is permitted, but the activity is logged for monitoring.

Check Approval-Required Command

curl -X POST "http://127.0.0.1:9090/v1/preflight/exec" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "agent": "claude-code",
    "session": "myapp/production",
    "params": {
      "command": "kubectl delete pod critical-service"
    }
  }'
Response (200 OK):
{
  "allowed": false,
  "decision": "require_approval",
  "message": "production change requires approval",
  "matched_policies": ["require-human"],
  "eval_duration_us": 10
}
Preflight returns allowed: false for require_approval and ask decisions because the tool call cannot proceed without human intervention.

Common Use Cases

Plan Before Execute

import requests

def can_execute(command, agent="my-agent", session="default"):
    """Check if a command would be allowed before executing it."""
    with open(os.path.expanduser("~/.rampart/token")) as f:
        token = f.read().strip()
    
    response = requests.post(
        "http://localhost:9090/v1/preflight/exec",
        headers={"Authorization": f"Bearer {token}"},
        json={
            "agent": agent,
            "session": session,
            "params": {"command": command}
        }
    )
    
    result = response.json()
    return result.get("allowed", False)

# Use in agent planning
if can_execute("npm install dangerous-package"):
    print("Safe to proceed")
else:
    print("Command would be blocked — finding alternative")

Batch Policy Check

#!/bin/bash
# Check multiple commands before attempting them

TOKEN="$(cat ~/.rampart/token)"

for cmd in "git push" "docker build" "rm -rf /tmp/cache"; do
  result=$(curl -s -X POST "http://127.0.0.1:9090/v1/preflight/exec" \
    -H "Authorization: Bearer $TOKEN" \
    -H "Content-Type: application/json" \
    -d '{"agent":"ci","session":"build/main","params":{"command":"'"$cmd"'"}}')
  
  allowed=$(echo "$result" | jq -r '.allowed')
  
  if [ "$allowed" = "true" ]; then
    echo "✓ $cmd"
  else
    echo "✗ $cmd"
  fi
done

Agent Planning Loop

const axios = require('axios');
const fs = require('fs');

const token = fs.readFileSync(process.env.HOME + '/.rampart/token', 'utf8').trim();

async function isAllowed(command) {
  const response = await axios.post(
    'http://localhost:9090/v1/preflight/exec',
    {
      agent: 'js-agent',
      session: 'automation/prod',
      params: { command }
    },
    {
      headers: { Authorization: `Bearer ${token}` }
    }
  );
  
  return response.data.allowed;
}

// Agent planning: try safe alternatives first
const options = ['npm ci', 'npm install --prefer-offline', 'npm install'];

for (const cmd of options) {
  if (await isAllowed(cmd)) {
    console.log(`Using: ${cmd}`);
    // execute the command
    break;
  }
}

Differences from Tool Evaluation

Feature/v1/tool/{toolName}/v1/preflight/{toolName}
Executes toolCaller decidesNo
Creates approvalsYes (on ask/require_approval)No
Audit logYesYes
Returns 403 ForbiddenYes (enforce mode)No
Returns 202 AcceptedYes (approval required)No
Always returns 200 OKNoYes
Side effectsPossible (approvals, notifications)None (audit only)

Next Steps

Tool Evaluation

Execute and evaluate tool calls

Approvals

Manage approval workflows

Build docs developers (and LLMs) love