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.
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>
pg_ws_. Get yours at proceedgate.dev/pay.html โ free, no card needed.Base URL
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
| Field | Type | Required | Description |
|---|---|---|---|
agent_id | string | โ | Identifier for the agent making the call (e.g. "scraper-prod-1") |
task_hash | string | โ | SHA-256 (or any hash) of the current task/input. Identical hashes trigger loop detection. |
action | enum | tool_call ยท model_call ยท retry ยท override ยท plan_execute. Default: tool_call | |
step_hash | string | Optional sub-step hash for finer loop granularity. | |
session_id | string | Optional 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)
| Field | Type | Description |
|---|---|---|
allowed | boolean | Always true on 200 |
zone | "safe" | "gray" | Loop detection zone. gray means AI reviewed and approved. |
iteration_count | number | Times this exact pattern was seen in the last 60 seconds. |
proceed_token | string | Signed ES256 JWT โ proof this check passed. Expires in 45s. |
credits_remaining | number | Credits left in your workspace after this call. |
Response (429 โ blocked)
| Field | Type | Description |
|---|---|---|
allowed | boolean | Always false |
zone | "storm" | "gray" | Why it was blocked |
iteration_count | number | How many identical requests triggered the block |
error | string | loop_detected |
reason | string | Human-readable explanation |
hint | string | How 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
| Field | Type | Description |
|---|---|---|
policy_id | string | retry_friction_v1 or low_confidence_loop_v1 |
action | string | Action type: tool_call, model_call, retry |
actor.id | string | Agent identifier |
actor.project | string | Workspace ID |
context.attempt_in_window | number | Attempt count in current window |
context.window_seconds | number | Window duration |
context.tool | string | Tool name |
context.confidence | number | Optional: confidence score (0-1) |
context.session_id | string | Optional: 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
| Event | When fired |
|---|---|
storm.detected | Loop enters storm zone (>10 identical requests/min). Includes block_count, estimated_cost_saved_usd, and behavioral fingerprint. |
credits.low | Credits fall below threshold |
subscription.created | New subscription activated |
subscription.renewed | Subscription extended |
subscription.expiring | 7 days before expiration |
budget.exceeded | Daily/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.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
agent_id | string | โ | Agent that owns this session |
budget_usd | string | โ | Maximum USD spend for this session (e.g. "50.00") |
duration_hours | number | Session 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.
Response (200)
| Field | Type | Description |
|---|---|---|
session_id | string | Session identifier |
agent_id | string | Agent that owns the session |
status | enum | open ยท closed ยท exceeded |
budget_usd | string | Original budget cap |
total_spent_usd | string | Cumulative spend so far |
remaining_usd | string | Budget remaining |
request_count | number | Total checks made in this session |
expires_at | ISO 8601 | Session expiry time |
created_at | ISO 8601 | Session 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:
| Tool | Description |
|---|---|
gate_check | Check if an action is allowed under current policy |
gate_redeem | Resolve friction and get proceed token after payment |
get_balance | Current credit balance and budget status |
set_budget | Set daily/weekly/monthly spending limits |
get_usage_report | Cost breakdown by action type and tool |
Error Codes
| HTTP | error | Meaning | Fix |
|---|---|---|---|
| 400 | invalid_request | Missing or invalid body field | Check agent_id and task_hash are present |
| 401 | missing_authorization | No Bearer token in header | Add Authorization: Bearer pg_ws_... |
| 401 | invalid_api_key_format | Key doesn't start with pg_ws_ | Use the key from your dashboard |
| 402 | insufficient_credits | Workspace out of credits | Top up at proceedgate.dev/pay.html |
| 404 | workspace_not_found | API key not linked to a workspace | Re-generate your key from the dashboard |
| 402 | session_budget_exceeded | Session budget cap reached | Close session and open a new one with a higher budget |
| 404 | session_not_found | Session ID doesn't exist | Check the session_id or create a new session |
| 410 | session_expired | Session past its duration_hours | Open a new session |
| 429 | loop_detected | Retry storm detected | Vary task_hash between tasks; wait 60s to reset |
| 500 | internal_error | Server error | Retry with exponential backoff; check status page |
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
}
}
| Field | Type | Description |
|---|---|---|
creditCost | number | Credits consumed per request (0 for free endpoints) |
creditPriceMicroUsdc | number | Price per credit in microUSDC (10 = $0.00001) |
loopDetection | object | Loop detection config: max requests, window, zone names |
budgetLimits | string[] | Supported budget cap granularities |
sessionSupport | boolean | Whether cumulative session tracking is available |
/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"]
}
}
| Field | Type | Description |
|---|---|---|
realm | string | Service domain โ "cost-governance" |
categories | string[] | Tags for agent discovery / search |
supportedIntents | string[] | What actions the API supports |
protocols | string[] | Payment protocols supported (x402, MPP) |