Spend guardrails
Add spend guardrails to CrewAI
Screwtape.ai decides whether an AI agent is allowed to spend money, and keeps the proof. Call POST /v1/judge before any payment. Pay only on pass. Screwtape advises and records; your CrewAI code must honor the verdict.
Install-free snippet
Evidence is an array of strings. Free: 3 calls/day with no key, 10/day with a free key.
import os, requests
def spend_allowed(task: str, planned_action: str, evidence: list[str] | None = None) -> dict:
headers = {"content-type": "application/json"}
if os.getenv("SCREWTAPE_KEY"):
headers["authorization"] = f"Bearer {os.environ['SCREWTAPE_KEY']}"
r = requests.post(
"https://screwtape.ai/v1/judge",
headers=headers,
timeout=20,
json={"task": task, "agent_output": planned_action, "evidence": evidence or []},
)
if r.status_code != 200:
return {"verdict": "fail", "reasons": [f"check unavailable: HTTP {r.status_code}"]} # fail closed
return r.json()
# Call before any payment. Pay only on pass.
v = spend_allowed(
"Pay invoice INV-42 from Acme",
"Pay $120.00 to Acme",
["PO-42: Acme, $120.00"],
)
if v["verdict"] == "pass":
pay() # your payment call
elif v["verdict"] == "retry":
fix_and_retry(v["reasons"])
else:
ask_a_human(v["reasons"])
# Optional: catch a duplicate invoice first
# POST https://screwtape.ai/v1/duplicate with the same Bearer key
# Optional: reserve against a shared run cap
# POST https://screwtape.ai/v1/budget {run_id, event_id, amount, cap, merchant}
# Optional: sign what the agent did
# POST https://screwtape.ai/v1/receipt {agent_id, event_id, action, status}
Why check before a CrewAI payment?
Agents can pay the wrong amount, the wrong party, or the same invoice twice. Screwtape returns pass, fail, or retry with reasons and a signed receipt so your code can stop before the payment runs.
Do I need to install a package?
No. Call HTTPS endpoints with your HTTP client. Optional free API key via POST /v1/signup. Without a key you still get a small shared free allowance per day.
What if the check is unavailable?
Fail closed: treat a non-200 response as fail and do not pay. The snippets below do that.
How do I catch a duplicate invoice?
POST /v1/duplicate with the invoice fields before or instead of judge. It returns unique, duplicate, possible_duplicate, or replay.
How do I share a budget across agents?
POST /v1/budget with run_id, event_id, amount, cap, and merchant. Honor block. Children inherit the root cap.
How do I keep proof of what the agent did?
POST /v1/receipt with agent_id, event_id, action, and status. Verify for free at GET /v1/receipt/verify or on /verify/. To close a whole run, send children: a list of prior receipt ids; the summary signs a root digest over them.
All spend-guardrail guides · Framework connection examples · Machine-readable API notes · Verify a receipt · Receipt format
