Skip to main content

Blueprint: SaaS Quota Watchdog

Protecting Specialized API Budgets from Autonomous Agent Loops

Agents using expensive SaaS APIs (e.g., Clearbit, Apollo, specialized research tools) can exhaust a month's worth of credits in a single recursive loop. The Gateway deterministically enforces configured per-user and per-org request limits in a 60-second sliding window. Tool-specific daily or monthly budgets are a separate boundary: enforce those with an external persistent counter immediately before every SaaS tool execution.

This blueprint demonstrates supported per-minute Gateway request limiting.

Architecture

1. Master Policy Definition

{
"name": "saas-economic-policy",
"priority": 8000,
"rules": [
{
"id": "limit-saas-lookups",
"effect": "allow",
"principals": ["*"],
"actions": ["saas:lookup"],
"resources": ["*"]
}
]
}

Configure the supported Gateway limit with CZ_GATEWAY_RATE_LIMIT_PER_USER or CZ_GATEWAY_RATE_LIMIT_PER_ORG. These limits count Gateway requests in a 60-second sliding window, regardless of whether a request produces a saas:lookup tool call. Tool-specific daily and monthly quotas require an external persistent counter immediately before tool execution.

2. Implementation

Python Prototype

from openai import OpenAI, RateLimitError

client = OpenAI(
api_key="ignored",
base_url="http://cz-gateway:8001/v1",
default_headers={"X-ControlZero-User-ID": "marketing-bot"}
)

def perform_bulk_research(targets: list):
for target in targets:
try:
# The Gateway limits this LLM request, not a later SaaS tool execution.
response = client.chat.completions.create(
model="gpt-5.4-mini",
messages=[{"role": "user", "content": f"Lookup info for {target}"}],
tools=[{"type": "function", "function": {"name": "saas:lookup", "parameters": {"type": "object"}}}]
)
print(f"Gateway request accepted for {target}")
except RateLimitError:
print("CRITICAL: Per-minute Gateway request limit reached. Stopping loop.")
break
except Exception as e:
print(f"Error: {e}")

# Scenario: Attempting to exceed the configured per-minute limit
bulk_list = [f"company-{i}" for i in range(200)]
perform_bulk_research(bulk_list)

3. Validation Checklist

  • Rate Limit Check: Verify that Gateway requests beyond the configured 60-second limit receive HTTP 429 and raise RateLimitError.
  • Persistent Quotas: If tool-specific daily or monthly quotas are required, verify an external counter runs immediately before each SaaS execution, persists across restarts, and resets on the intended schedule.
  • Multi-User Limits: Verify that User A hitting a user-level limit does not block User B.