Documentation

ProceedGate is a circuit breaker for AI agents. One HTTP call before each action detects retry storms, enforces budgets, and returns a signed token as proof of governance.

Quickstart

Get a free API key at proceedgate.dev/pay.html โ€” 5,000 checks/month, no credit card.

Need more checks? Top up packs ($5 / $10 / $15) add checks to your workspace in one transaction.

1. Make your first check

curl -X POST https://governor.proceedgate.dev/v1/check \
  -H "Authorization: Bearer $PG_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "agent_id":  "my-agent",
    "task_hash": "sha256-of-current-task",
    "action":    "tool_call"
  }'

2. Handle the response

// โœ… Allowed (HTTP 200)
{
  "allowed": true,
  "zone": "safe",
  "iteration_count": 3,
  "proceed_token": "eyJ...",
  "credits_remaining": 1997
}

// ๐Ÿšซ Loop detected (HTTP 429)
{
  "allowed": false,
  "zone": "storm",
  "iteration_count": 11,
  "error": "loop_detected",
  "reason": "11 identical requests in 60s"
}

3. Drop it into your agent loop

// Node.js
async function pgCheck(agentId, taskHash) {
  const res = await fetch('https://governor.proceedgate.dev/v1/check', {
    method: 'POST',
    headers: { 'Authorization': `Bearer ${process.env.PG_KEY}`, 'Content-Type': 'application/json' },
    body: JSON.stringify({ agent_id: agentId, task_hash: taskHash, action: 'tool_call' }),
  });
  if (res.status === 429) throw new Error('loop_detected');
  if (!res.ok) throw new Error('check_failed');
  return res.json();
}

// In your agent loop:
for (const url of urls) {
  await pgCheck('scraper', sha256(url));  // throws on block
  const data = await fetch(url);
}

Authentication

All requests require a Bearer token in the Authorization header:

Authorization: Bearer pg_ws_<your-key>
API keys start with pg_ws_. Get yours at proceedgate.dev/pay.html โ€” free, no card needed.

Base URL

https://governor.proceedgate.dev

All endpoints are served over HTTPS. The API is hosted on Cloudflare Workers (global edge, <50ms p99).

POST/v1/check

The primary endpoint. Runs loop detection + credit check and returns a signed proceed_token. Auto-derives your workspace from the API key โ€” no extra config needed.

Request body

FieldTypeRequiredDescription
agent_idstringโœ“Identifier for the agent making the call (e.g. "scraper-prod-1")
task_hashstringโœ“SHA-256 (or any hash) of the current task/input. Identical hashes trigger loop detection.
actionenumtool_call ยท model_call ยท retry ยท override ยท plan_execute. Default: tool_call
step_hashstringOptional sub-step hash for finer loop granularity.
session_idstringOptional session ID for cumulative budget tracking. When set, spend is tracked against the session budget and response includes X-Proceedgate-Session-Spent / X-Proceedgate-Session-Remaining headers.

Response (200 โ€” allowed)

FieldTypeDescription
allowedbooleanAlways true on 200
zone"safe" | "gray"Loop detection zone. gray means AI reviewed and approved.
iteration_countnumberTimes this exact pattern was seen in the last 60 seconds.
proceed_tokenstringSigned ES256 JWT โ€” proof this check passed. Expires in 45s.
credits_remainingnumberCredits left in your workspace after this call.

Response (429 โ€” blocked)

FieldTypeDescription
allowedbooleanAlways false
zone"storm" | "gray"Why it was blocked
iteration_countnumberHow many identical requests triggered the block
errorstringloop_detected
reasonstringHuman-readable explanation
hintstringHow to fix (vary task_hash, wait 60s)

POST/v1/governor/check

Full governance check with AI reasoning, loop detection, and policy evaluation. Returns detailed reasoning chain and confidence scores.

Request body

FieldTypeDescription
policy_idstringretry_friction_v1 or low_confidence_loop_v1
actionstringAction type: tool_call, model_call, retry
actor.idstringAgent identifier
actor.projectstringWorkspace ID
context.attempt_in_windownumberAttempt count in current window
context.window_secondsnumberWindow duration
context.toolstringTool name
context.confidencenumberOptional: confidence score (0-1)
context.session_idstringOptional: session ID for cumulative budget tracking

Response (200 allowed)

{
  "allowed": true,
  "decision_id": "dec_01KMT...",
  "proceed_token": "eyJhbG...",
  "expires_in_seconds": 45,
  "reason_code": "none",
  "confidence": 0.98,
  "ai_reasoning": "All governance checks passed...",
  "reasoning_chain": [
    { "step": "pattern_check", "conclusion": "Request is within safe limits" },
    { "step": "budget_check", "conclusion": "Cost budget allows operation" },
    { "step": "governance_decision", "conclusion": "ALLOW" }
  ]
}

Response (402 friction required)

Returned when your workspace is out of checks (credits). Top up packs are available at /topup.html.

x402-price: 0.004 USDC
x402-recipient: 0x607Fc9D41858Aa...
x402-chain: BSC

POST/v1/governor/redeem

Resolve friction by providing a payment transaction hash. Returns a proceed_token upon successful verification.

Request

Header: x402-tx-hash: 0x...

{
  "decision_id": "dec_01KMT..."
}

Response (200)

{
  "ok": true,
  "decision_id": "dec_01KMT...",
  "proceed_token": "eyJhbG...",
  "expires_in_seconds": 45,
  "receipt": {
    "tx_hash": "0x...",
    "paid_price": "0.004 USDC",
    "paid_chain": "bsc"
  }
}

POST/v1/check/batch

Check multiple agent tasks in a single HTTP call. Useful when orchestrating many parallel agents. Returns an array of results in the same order as the input.

Request body

{
  "checks": [
    { "agent_id": "researcher", "task_hash": "abc123", "action": "model_call" },
    { "agent_id": "scraper",    "task_hash": "def456", "action": "tool_call" }
  ]
}

Maximum 50 checks per batch. Each check follows the same schema as /v1/check.

Response (200)

{
  "ok": true,
  "results": [
    { "allowed": true,  "zone": "safe",  "iteration_count": 1, "proceed_token": "eyJ..." },
    { "allowed": false, "zone": "storm", "iteration_count": 12, "error": "loop_detected" }
  ],
  "credits_remaining": 1990
}

GET/v1/me

Returns workspace info for the authenticated API key โ€” plan, credits, features.

curl https://governor.proceedgate.dev/v1/me \
  -H "Authorization: Bearer $PG_KEY"
{
  "ok": true,
  "workspace_id": "free-abc123",
  "plan": { "id": "free", "name": "Free" },
  "credits": { "remaining": 1997, "included": 2000 }
}

GET/v1/me/stats

Returns real-time governance stats for your workspace: decisions, storms blocked, cost saved, and a 60-minute storm chart.

{
  "ok": true,
  "workspace_id": "free-abc123",
  "total_decisions": 42,
  "storms_blocked": 3,
  "cost_saved_usd": 0.15,
  "decisions": [ /* last 50 */ ],
  "storm_chart": [ /* 60 per-minute buckets */ ]
}

GET/v1/billing/balance

Returns current credit balance and usage.

curl "https://governor.proceedgate.dev/v1/billing/balance?workspace_id=free-abc123" \
  -H "Authorization: Bearer $PG_KEY"

PUT/v1/billing/budget

Set daily, weekly, or monthly spend caps. When the cap is hit, /v1/check returns 402 and optionally fires a webhook.

curl -X PUT https://governor.proceedgate.dev/v1/billing/budget \
  -H "Authorization: Bearer $PG_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "workspace_id": "free-abc123", "daily": 100, "weekly": 500 }'

GET/v1/billing/usage

Returns detailed usage breakdown for your workspace: credits used by action type, tool, and daily totals.

curl "https://governor.proceedgate.dev/v1/billing/usage?workspace_id=free-abc123&period=week" \
  -H "Authorization: Bearer $PG_KEY"

Response (200)

{
  "workspace_id": "free-abc123",
  "period": "week",
  "total_credits_used": 142,
  "total_cost_usd": 0.00142,
  "breakdown": {
    "by_action": { "tool_call": 100, "model_call": 42 },
    "by_tool": { "web_scrape": 80, "search_api": 62 },
    "by_day": [
      { "date": "2026-03-28", "credits": 45 }
    ]
  }
}

PUT/v1/billing/:workspaceId/webhook

Configure a webhook endpoint for real-time governance alerts. Webhooks are HMAC-SHA256 signed โ€” verify the X-ProceedGate-Signature header to ensure authenticity.

curl -X PUT https://governor.proceedgate.dev/v1/billing/YOUR_WORKSPACE_ID/webhook \
  -H "Authorization: Bearer $PG_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "webhook_url": "https://your-server.com/webhook", "webhook_secret": "whsec_...", "events": ["storm.detected", "credits.low"] }'

Supported events

EventWhen fired
storm.detectedLoop enters storm zone (>10 identical requests/min). Includes block_count, estimated_cost_saved_usd, and behavioral fingerprint.
credits.lowCredits fall below threshold
subscription.createdNew subscription activated
subscription.renewedSubscription extended
subscription.expiring7 days before expiration
budget.exceededDaily/weekly/monthly budget limit hit

storm.detected payload

{
  "event": "storm.detected",
  "timestamp": "2026-05-01T12:34:56.000Z",
  "data": {
    "workspace_id": "w1",
    "request_hash": "sha256:abc123...",
    "block_count": 47,
    "total_blocked_ms": 5230,
    "estimated_cost_saved_usd": 2.35,
    "alert_severity": "high",
    "fingerprint": { "burst_index": 0.87, "entropy": 0.341, "fanout_ratio": 2.1 }
  }
}

Signature verification (Node.js)

// Verify incoming webhook from ProceedGate
import { createHmac, timingSafeEqual } from 'node:crypto';

function verifyWebhook(rawBody, signatureHeader, secret) {
  const expected = createHmac('sha256', secret).update(rawBody).digest('hex');
  const a = Buffer.from('sha256=' + expected);
  const b = Buffer.from(signatureHeader);
  return a.length === b.length && timingSafeEqual(a, b);
}
// Usage: verifyWebhook(rawBody, req.headers['x-proceedgate-signature'], SECRET)

See examples/storm-webhook-slack.mjs for a complete Slack integration with deduplication and severity-based routing.

POST/v1/governor/session

Open a budget session. Sessions track cumulative spend across multiple /v1/check calls โ€” like an escrow with a hard cap. Inspired by the MPP voucher accumulation pattern.

Sessions are optional. If you just want per-workspace budget limits, use PUT /v1/billing/budget instead. Sessions are useful when you need per-agent, per-task budget caps with a defined time window.

Request body

FieldTypeRequiredDescription
agent_idstringโœ“Agent that owns this session
budget_usdstringโœ“Maximum USD spend for this session (e.g. "50.00")
duration_hoursnumberSession lifetime in hours. Default: 24

Response (201)

{
  "ok": true,
  "session_id": "ses_m1abc_x7k3f2",
  "budget_usd": "50.00",
  "expires_at": "2026-03-29T14:30:00.000Z"
}

Example: full session flow

# 1. Open session with $50 budget
curl -X POST https://governor.proceedgate.dev/v1/governor/session \
  -H "Authorization: Bearer $PG_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "agent_id": "scraper-1", "budget_usd": "50.00", "duration_hours": 8 }'

# 2. Run checks with session_id โ€” spend is tracked cumulatively
curl -X POST https://governor.proceedgate.dev/v1/governor/check \
  -H "Authorization: Bearer $PG_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "agent_id": "scraper-1", "task_hash": "abc123", "session_id": "ses_m1abc_x7k3f2" }'
# Response headers include:
#   X-Proceedgate-Session-Spent: 0.010000
#   X-Proceedgate-Session-Remaining: 49.990000

# 3. Close session when done (settle)
curl -X DELETE https://governor.proceedgate.dev/v1/governor/session/ses_m1abc_x7k3f2 \
  -H "Authorization: Bearer $PG_KEY"

GET/v1/governor/session/:id

Get the current status of a session โ€” cumulative spend, remaining budget, and request count.

GET /v1/governor/session/ses_m1abc_x7k3f2

Response (200)

FieldTypeDescription
session_idstringSession identifier
agent_idstringAgent that owns the session
statusenumopen ยท closed ยท exceeded
budget_usdstringOriginal budget cap
total_spent_usdstringCumulative spend so far
remaining_usdstringBudget remaining
request_countnumberTotal checks made in this session
expires_atISO 8601Session expiry time
created_atISO 8601Session creation time

DELETE/v1/governor/session/:id

Close a session and finalize the cumulative spend. Like an MPP settlement โ€” no more checks can be made against this session after closing.

Response (200)

{
  "ok": true,
  "session_id": "ses_m1abc_x7k3f2",
  "final_spent_usd": "12.350000",
  "request_count": 247,
  "status": "closed"
}

GET/.well-known/jwks.json

Public key discovery for verifying proceed_token JWTs. Standard JWKS format. Use this to verify governance tokens downstream without calling the governor.

curl https://governor.proceedgate.dev/.well-known/jwks.json

Usage with jose (Node.js)

import * as jose from 'jose';

const JWKS = jose.createRemoteJWKSet(
  new URL('https://governor.proceedgate.dev/.well-known/jwks.json')
);

const { payload } = await jose.jwtVerify(proceedToken, JWKS, {
  issuer:   'https://governor.proceedgate.dev',
  audience: 'agent-cost-governor',
});
// payload.sub = agent_id, payload.jti = decision_id

GET/health

Returns 200 OK with API status and latency. Use for uptime monitoring.

curl https://governor.proceedgate.dev/health

Node.js Integration

Set PG_KEY in your environment, then call pgCheck() before each agent action.

// pgCheck.js
const PG_KEY = process.env.PG_KEY;
const PG_URL = 'https://governor.proceedgate.dev/v1/governor/check';

export async function pgCheck(agentId, taskHash, action = 'tool_call') {
  const res = await fetch(PG_URL, {
    method: 'POST',
    headers: { 'Authorization': `Bearer ${PG_KEY}`, 'Content-Type': 'application/json' },
    body: JSON.stringify({ agent_id: agentId, task_hash: taskHash, action }),
  });
  const data = await res.json();
  if (res.status === 429) throw new Error(`loop_detected: ${data.reason}`);
  if (res.status === 402) throw new Error('insufficient_credits');
  if (!res.ok)            throw new Error(`pg_error: ${data.error}`);
  return data; // { allowed, zone, proceed_token, credits_remaining }
}

// Usage in Apify actor:
import { createHash } from 'crypto';
const sha256 = s => createHash('sha256').update(s).digest('hex');

for (const url of urlQueue) {
  await pgCheck('apify-actor', sha256(url));
  const html = await fetch(url).then(r => r.text());
  await processPage(html);
}

Python Integration

# pg_check.py
import os, hashlib, httpx

PG_KEY = os.environ["PG_KEY"]
PG_URL = "https://governor.proceedgate.dev/v1/governor/check"

def pg_check(agent_id: str, task_hash: str, action: str = "tool_call"):
    res = httpx.post(
        PG_URL,
        headers={"Authorization": f"Bearer {PG_KEY}", "Content-Type": "application/json"},
        json={"agent_id": agent_id, "task_hash": task_hash, "action": action},
        timeout=10,
    )
    data = res.json()
    if res.status_code == 429:
        raise RuntimeError(f"loop_detected: {data.get('reason')}")
    if res.status_code == 402:
        raise RuntimeError("insufficient_credits")
    res.raise_for_status()
    return data

# Usage:
def sha256(s): return hashlib.sha256(s.encode()).hexdigest()

for url in urls:
    pg_check("scraper", sha256(url))
    html = httpx.get(url).text

@proceedgate/node

Framework-agnostic Node.js / TypeScript SDK. Detects retry storms, enforces budgets, returns signed tokens. Works with any agent framework.

npm i @proceedgate/node

gateStep โ€” non-throwing check

import { createProceedGateClient, gateStep } from '@proceedgate/node';

const client = createProceedGateClient({
  baseUrl: 'https://governor.proceedgate.dev',
  actor: { id: 'my-agent', project: 'my-workspace-id' },
  apiKey: process.env.PG_KEY,
});

const result = await gateStep(client, {
  policyId: 'retry_friction_v1',
  action: 'tool_call',
  context: { attempt_in_window: 3, window_seconds: 60, tool: 'web_scrape' },
});

if (result.kind === 'ok') {
  // Allowed โ€” proceed_token in result.proceedToken
} else {
  console.log('Blocked:', result.friction?.price); // e.g. "0.004 USDC"
}

requireGateStepOk โ€” throws on friction

import { requireGateStepOk, ProceedGateFrictionError } from '@proceedgate/node';

try {
  await requireGateStepOk(client, {
    policyId: 'retry_friction_v1',
    action: 'retry',
    context: { attempt_in_window: 7, window_seconds: 60 },
  });
  // Allowed โ€” run action
} catch (e) {
  if (e instanceof ProceedGateFrictionError) {
    console.log('Blocked:', e.decisionId, e.friction);
  }
}

@proceedgate/langchain

LangChain integration with three components: callback handler, tool wrapper, and agent executor. Works with @langchain/core โ‰ฅ0.2.

npm i @proceedgate/langchain

Callback handler (intercepts all LLM + tool calls)

import { ProceedGateCallbackHandler } from '@proceedgate/langchain';
import { ChatOpenAI } from '@langchain/openai';

const handler = new ProceedGateCallbackHandler({
  apiKey: process.env.PG_KEY,
  workspaceId: 'my-workspace',
  onFriction: 'block',
});

const model = new ChatOpenAI({ callbacks: [handler] });

Tool wrapper

import { wrapToolWithGate } from '@proceedgate/langchain';

const gatedSearch = wrapToolWithGate(searchTool, {
  apiKey: process.env.PG_KEY,
  workspaceId: 'my-workspace',
});

@proceedgate/vercel-ai

Vercel AI SDK integration. Wraps language models and tools with ProceedGate governance via the middleware API. Compatible with ai โ‰ฅ3.0.

npm i @proceedgate/vercel-ai

Middleware (gates every LLM call)

import { generateText, wrapLanguageModel } from 'ai';
import { openai } from '@ai-sdk/openai';
import { proceedGateMiddleware } from '@proceedgate/vercel-ai';

const model = wrapLanguageModel({
  model: openai('gpt-4o'),
  middleware: proceedGateMiddleware({
    apiKey: process.env.PG_KEY,
    workspaceId: 'my-workspace',
    onFriction: 'block',
    maxBudget: 5.00, // $5 hard cap
  }),
});

const result = await generateText({ model, prompt: 'Analyze...' });

Tool gating

import { tool } from 'ai';
import { z } from 'zod';
import { gatedTool } from '@proceedgate/vercel-ai';

const gate = gatedTool({ apiKey: process.env.PG_KEY, workspaceId: 'ws' });

const searchTool = gate(
  tool({
    description: 'Search the web',
    parameters: z.object({ query: z.string() }),
    execute: async ({ query }) => doSearch(query),
  }),
  { costEstimate: 0.01 }
);

proceedgate-crewai (Python)

CrewAI integration for Python agents. Three components: callback handler, tool decorator, and budget-aware crew wrapper.

pip install proceedgate-crewai

Tool decorator

from proceedgate_crewai import gated_tool

@gated_tool(api_key="pg_ws_...", workspace_id="my-ws")
def search_web(query: str) -> str:
    return external_search_api(query)

Budget-aware crew

from crewai import Crew, Agent, Task
from proceedgate_crewai import BudgetAwareCrew

crew = Crew(agents=[...], tasks=[...])

gated = BudgetAwareCrew(
    crew=crew,
    api_key="pg_ws_...",
    workspace_id="my-ws",
    max_budget=2.50,  # $2.50 hard stop
)

result = gated.kickoff(inputs={"topic": "BNB Chain DeFi"})
print(f"Spent: ${gated.total_cost:.4f}")

@proceedgate/mcp-server

Model Context Protocol server for AI coding tools (Claude Code, Cursor, etc.). Exposes 5 tools for governance, balance, and usage reporting.

npm i -g @proceedgate/mcp-server

Claude Desktop / Claude Code setup

// claude_desktop_config.json
{
  "mcpServers": {
    "proceedgate": {
      "command": "proceedgate-mcp",
      "args": ["--api-key", "pg_ws_...", "--workspace-id", "my-ws"]
    }
  }
}

Available MCP tools:

ToolDescription
gate_checkCheck if an action is allowed under current policy
gate_redeemResolve friction and get proceed token after payment
get_balanceCurrent credit balance and budget status
set_budgetSet daily/weekly/monthly spending limits
get_usage_reportCost breakdown by action type and tool

Error Codes

HTTPerrorMeaningFix
400invalid_requestMissing or invalid body fieldCheck agent_id and task_hash are present
401missing_authorizationNo Bearer token in headerAdd Authorization: Bearer pg_ws_...
401invalid_api_key_formatKey doesn't start with pg_ws_Use the key from your dashboard
402insufficient_creditsWorkspace out of creditsTop up at proceedgate.dev/pay.html
404workspace_not_foundAPI key not linked to a workspaceRe-generate your key from the dashboard
402session_budget_exceededSession budget cap reachedClose session and open a new one with a higher budget
404session_not_foundSession ID doesn't existCheck the session_id or create a new session
410session_expiredSession past its duration_hoursOpen a new session
429loop_detectedRetry storm detectedVary task_hash between tasks; wait 60s to reset
500internal_errorServer errorRetry with exponential backoff; check status page
On 429, do not retry immediately โ€” that will just extend the block. Use a different task_hash for genuinely new work, or wait 60 seconds for the window to reset.

GET/openapi.json

Returns the full OpenAPI 3.1 specification for the ProceedGate API. AI agents can use this endpoint to auto-discover capabilities, pricing, and payment requirements before making requests.

curl https://governor.proceedgate.dev/openapi.json

The spec includes two custom extensions designed for machine-to-machine discovery:

x-cost-info Extension

Each endpoint in the OpenAPI spec includes an x-cost-info object that tells agents what a request will cost before they make it. This follows the same discovery pattern as MPP's x-payment-info.

Example (on /v1/check)

{
  "x-cost-info": {
    "creditCost": 1,
    "creditPriceMicroUsdc": 10,
    "loopDetection": {
      "enabled": true,
      "maxIdenticalRequests": 10,
      "windowSeconds": 60,
      "zones": ["safe", "gray", "storm"]
    },
    "budgetLimits": ["daily", "weekly", "monthly"],
    "sessionSupport": true
  }
}
FieldTypeDescription
creditCostnumberCredits consumed per request (0 for free endpoints)
creditPriceMicroUsdcnumberPrice per credit in microUSDC (10 = $0.00001)
loopDetectionobjectLoop detection config: max requests, window, zone names
budgetLimitsstring[]Supported budget cap granularities
sessionSupportbooleanWhether cumulative session tracking is available
Free endpoints like /v1/billing/balance have "creditCost": 0 so agents know they can call them without spending credits.

x-service-info Extension

The top-level info object includes x-service-info โ€” a machine-readable summary of what ProceedGate does and which protocols it supports. This helps AI agents decide whether this API is relevant to their task.

{
  "x-service-info": {
    "realm": "cost-governance",
    "categories": ["ai-agents", "cost-control", "loop-detection", "budget-management"],
    "supportedIntents": ["check", "budget", "session"],
    "documentation": "https://proceedgate.dev",
    "protocols": ["x402", "mpp"]
  }
}
FieldTypeDescription
realmstringService domain โ€” "cost-governance"
categoriesstring[]Tags for agent discovery / search
supportedIntentsstring[]What actions the API supports
protocolsstring[]Payment protocols supported (x402, MPP)